diff options
author | gman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-03 22:56:18 +0000 |
---|---|---|
committer | gman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-03 22:56:18 +0000 |
commit | aa078b67d3d8e976ffeee26e2dcccb6e938b7008 (patch) | |
tree | 3f9edf829005027d107a5f20527a78780386f135 /o3d/plugin | |
parent | 04c2262254185379aa762a69ab4410f3aedab9af (diff) | |
download | chromium_src-aa078b67d3d8e976ffeee26e2dcccb6e938b7008.zip chromium_src-aa078b67d3d8e976ffeee26e2dcccb6e938b7008.tar.gz chromium_src-aa078b67d3d8e976ffeee26e2dcccb6e938b7008.tar.bz2 |
Add SetRect to Texture2d and TextureCUBE
Originally I was going to replace Lock/Unlock with
only SetRect (and maybe GetRect) and I did that.
But then as I was going through the code things started
not being so cool. The JavaScript texture.SetRect where
as before it allocated no memory, now it needed to allocate
a temporary buffer just to be able to write the texture.
DrawImage also would have have required copying the original
texture out using GetRect, then modifying it, then copying it
back even in D3D or it would have required a temporary buffer.
That's what happens under the hood in the GL implementation
of Texture2D but why should D3D suffer because of the of GL?
Or maybe it's a reasonable compomise the D3D should go slower
so that GL isn't twice as slow as it it could be?
So, I left Lock/Unlock and added SetRect as well.
This CL should help the video guys and we can decide if
we want to get rid of Lock/Unlock later.
SetRect is really only there because trying to make GL
act like D3D makes GL slow since we had to get a copy
of the texture from GL before Locking. SetRect, since
it is not exposing the original data doesn't need to do
that.
So, now there are both. If need to read (and write) to
the texture use Lock. If you only need to write use
SetRect.
I also fixed Lock/Unlock so they return a pitch which
is required for D3D. While I did that I made Lock/Unlock
private so you have to use the TextureXXXLockHelpers
to access the data.
I didn't do the command buffer versions.
I also added stubs for texture tests. We need to add
more tests.
I feel like a lot of clean up needs to happen.
It seesm like Bitmap should be split into
Bitmap2D
BitmapCUBE
BitmapVolume
Possibly. And maybe BitmapCube should effectively
just be typedef Bitmap2D BitmapCUBE[6] and
BitmapVolume would be std::vector<Bitmap2D>
Then we wouldn't need face and volume versions
of various functions. You'd just get the face or
the slice Bitma2D and then use the 2D functions.
We should decide if that's what we want before
pushing a new release. Otherwise we should remove
bitmap.idl from idl_scons.lst and the one sample
And ship without exposing Bitmap until we are
sure they API we are exposing is the one we want.
Review URL: http://codereview.chromium.org/159725
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22332 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/plugin')
-rw-r--r-- | o3d/plugin/build.scons | 1 | ||||
-rw-r--r-- | o3d/plugin/cross/texture_static_glue.cc | 388 | ||||
-rw-r--r-- | o3d/plugin/idl/texture.idl | 246 | ||||
-rw-r--r-- | o3d/plugin/plugin.gyp | 1 |
4 files changed, 435 insertions, 201 deletions
diff --git a/o3d/plugin/build.scons b/o3d/plugin/build.scons index 53d4dcf..d0a251c 100644 --- a/o3d/plugin/build.scons +++ b/o3d/plugin/build.scons @@ -194,6 +194,7 @@ inputs = AUTOGEN_CC_FILES + [ 'cross/np_v8_bridge.cc', 'cross/out_of_memory.cc', 'cross/stream_manager.cc', + 'cross/texture_static_glue.cc', 'cross/config_common.cc', ] diff --git a/o3d/plugin/cross/texture_static_glue.cc b/o3d/plugin/cross/texture_static_glue.cc new file mode 100644 index 0000000..2e34786 --- /dev/null +++ b/o3d/plugin/cross/texture_static_glue.cc @@ -0,0 +1,388 @@ +/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <vector>
+#include "core/cross/pointer_utils.h"
+#include "core/cross/error.h"
+#include "core/cross/math_utilities.h"
+#include "core/cross/texture.h"
+
+namespace {
+
+void SetRectCheck(o3d::Texture* self,
+ void* data,
+ int pitch,
+ o3d::Texture::Format format,
+ int destination_x,
+ int destination_y,
+ int texture_width,
+ int texture_height,
+ int source_width,
+ int source_height,
+ const std::vector<float>& values) {
+ unsigned num_components;
+ unsigned swizzle[4] = {2, 1, 0, 3};
+ switch (format) {
+ case o3d::Texture::XRGB8:
+ num_components = 3;
+ break;
+ case o3d::Texture::R32F:
+ swizzle[0] = 0;
+ num_components = 1;
+ break;
+ case o3d::Texture::ARGB8:
+ case o3d::Texture::ABGR16F:
+ num_components = 4;
+ break;
+ case o3d::Texture::ABGR32F: {
+ num_components = 4;
+ const o3d::Texture::RGBASwizzleIndices& indices =
+ self->GetABGR32FSwizzleIndices();
+ for (int ii = 0; ii < 4; ++ii) {
+ swizzle[ii] = indices[ii];
+ }
+ break;
+ }
+ default:
+ DCHECK(false);
+ return;
+ }
+
+ // clip
+ int source_x = 0;
+ int source_y = 0;
+ int copy_width = source_width;
+ int copy_height = source_height;
+
+ if (destination_x < 0) {
+ copy_width += destination_x;
+ source_x -= destination_x;
+ destination_x = 0;
+ }
+ if (destination_x + copy_width > static_cast<int>(texture_width)) {
+ copy_width -= destination_x + copy_width - texture_width;
+ }
+
+ if (destination_y < 0) {
+ copy_height += destination_y;
+ source_y -= destination_y;
+ destination_y = 0;
+ }
+ if (destination_y + copy_height > static_cast<int>(texture_height)) {
+ copy_height -= destination_y + copy_height - texture_height;
+ }
+
+ if (copy_width <= 0 || copy_height <= 0) {
+ return;
+ }
+
+ const float* source =
+ &values[0] +
+ (source_y * source_width + source_x) * num_components;
+ unsigned source_stride = (source_width - copy_width) * num_components;
+ switch (format) {
+ case o3d::Texture::ABGR16F: {
+ uint16* dest_line =
+ static_cast<uint16*>(data) +
+ (destination_y * texture_width + destination_x) * num_components;
+ while (copy_height > 0) {
+ uint16* destination = dest_line;
+ for (int xx = 0; xx < copy_width; ++xx) {
+ for (unsigned element = 0; element < num_components; ++element) {
+ destination[element] = Vectormath::Aos::FloatToHalf(
+ source[swizzle[element]]);
+ }
+ destination += num_components;
+ source += num_components;
+ }
+ dest_line = o3d::AddPointerOffset<uint16*>(dest_line, pitch);
+ source += source_stride;
+ --copy_height;
+ }
+ break;
+ }
+ case o3d::Texture::R32F:
+ case o3d::Texture::ABGR32F: {
+ float* dest_line =
+ static_cast<float*>(data) +
+ (destination_y * texture_width + destination_x) * num_components;
+ while (copy_height > 0) {
+ float* destination = dest_line;
+ for (int xx = 0; xx < copy_width; ++xx) {
+ for (unsigned element = 0; element < num_components; ++element) {
+ destination[element] = source[swizzle[element]];
+ }
+ destination += num_components;
+ source += num_components;
+ }
+ dest_line = o3d::AddPointerOffset<float*>(dest_line, pitch);
+ source += source_stride;
+ --copy_height;
+ }
+ break;
+ }
+ default: {
+ uint8* dest_line =
+ static_cast<uint8*>(data) +
+ (destination_y * texture_width + destination_x) * 4;
+ while (copy_height > 0) {
+ uint8* destination = dest_line;
+ for (int xx = 0; xx < copy_width; ++xx) {
+ destination[0] = static_cast<unsigned char>(
+ source[swizzle[0]] * 255.0f);
+ destination[1] = static_cast<unsigned char>(
+ source[swizzle[1]] * 255.0f);
+ destination[2] = static_cast<unsigned char>(
+ source[swizzle[2]] * 255.0f);
+ destination[3] = (num_components == 4) ?
+ static_cast<unsigned char>(source[swizzle[3]] * 255.0f) : 255;
+ destination += 4;
+ source += num_components;
+ }
+ dest_line = o3d::AddPointerOffset<uint8*>(dest_line, pitch);
+ source += source_stride;
+ --copy_height;
+ }
+ break;
+ }
+ }
+}
+
+void SetRectCheck2D(o3d::Texture2D* self,
+ int level,
+ int destination_x,
+ int destination_y,
+ int source_width,
+ const std::vector<float>& values,
+ bool check_needed) {
+ if (level < 0 || level >= self->levels()) {
+ O3D_ERROR(self->service_locator())
+ << "level (" << level << " out of range";
+ return;
+ }
+ if (values.empty() || source_width <= 0) {
+ return;
+ }
+ unsigned num_values = values.size();
+ unsigned texture_width = std::max(self->width() >> level, 1);
+ unsigned texture_height = std::max(self->height() >> level, 1);
+ unsigned num_components;
+ switch (self->format()) {
+ case o3d::Texture::XRGB8:
+ num_components = 3;
+ break;
+ case o3d::Texture::R32F:
+ num_components = 1;
+ break;
+ case o3d::Texture::ARGB8:
+ case o3d::Texture::ABGR16F:
+ num_components = 4;
+ break;
+ case o3d::Texture::ABGR32F: {
+ num_components = 4;
+ break;
+ }
+ default:
+ O3D_ERROR(self->service_locator())
+ << "Texture::Set not supported for this type of texture";
+ return;
+ }
+ if (num_values % num_components != 0) {
+ O3D_ERROR(self->service_locator())
+ << "The number of elements passed in must be a multiple of "
+ << num_components;
+ }
+ unsigned num_elements = num_values / num_components;
+ if (num_elements % source_width != 0) {
+ O3D_ERROR(self->service_locator())
+ << "The number of elements passed in must be a multiple of the "
+ << "width";
+ return;
+ }
+ unsigned source_height = num_elements / source_width;
+ if (check_needed) {
+ unsigned needed = num_components * texture_width * texture_height;
+ if (num_values != needed) {
+ O3D_ERROR(self->service_locator())
+ << "needed " << needed << " values but " << num_values
+ << " passed in.";
+ return;
+ }
+ }
+ o3d::Texture2D::LockHelper helper(self, level);
+ void* data = helper.GetData();
+ if (!data) {
+ O3D_ERROR(self->service_locator()) << "could not lock texture";
+ return;
+ }
+
+ SetRectCheck(self, data, helper.pitch(), self->format(),
+ destination_x, destination_y,
+ texture_width, texture_height,
+ source_width, source_height,
+ values);
+}
+
+void SetRectCheckCUBE(o3d::TextureCUBE* self,
+ o3d::TextureCUBE::CubeFace face,
+ int level,
+ int destination_x,
+ int destination_y,
+ int source_width,
+ const std::vector<float>& values,
+ bool check_needed) {
+ if (level < 0 || level >= self->levels()) {
+ O3D_ERROR(self->service_locator())
+ << "level (" << level << " out of range";
+ return;
+ }
+ if (values.empty() || source_width <= 0) {
+ return;
+ }
+ unsigned num_values = values.size();
+ unsigned texture_width = std::max(self->edge_length() >> level, 1);
+ unsigned texture_height = texture_width;
+ unsigned num_components;
+ switch (self->format()) {
+ case o3d::Texture::XRGB8:
+ num_components = 3;
+ break;
+ case o3d::Texture::R32F:
+ num_components = 1;
+ break;
+ case o3d::Texture::ARGB8:
+ case o3d::Texture::ABGR16F:
+ num_components = 4;
+ break;
+ case o3d::Texture::ABGR32F: {
+ num_components = 4;
+ break;
+ }
+ default:
+ O3D_ERROR(self->service_locator())
+ << "Texture::Set not supported for this type of texture";
+ return;
+ }
+ if (num_values % num_components != 0) {
+ O3D_ERROR(self->service_locator())
+ << "The number of elements passed in must be a multiple of "
+ << num_components;
+ }
+ unsigned num_elements = num_values / num_components;
+ if (num_elements % source_width != 0) {
+ O3D_ERROR(self->service_locator())
+ << "The number of elements passed in must be a multiple of the "
+ << "width";
+ return;
+ }
+ unsigned source_height = num_elements / source_width;
+ if (check_needed) {
+ unsigned needed = num_components * texture_width * texture_height;
+ if (num_values != needed) {
+ O3D_ERROR(self->service_locator())
+ << "needed " << needed << " values but " << num_values
+ << " passed in.";
+ return;
+ }
+ }
+ o3d::TextureCUBE::LockHelper helper(self, face, level);
+ void* data = helper.GetData();
+ if (!data) {
+ O3D_ERROR(self->service_locator()) << "could not lock texture";
+ return;
+ }
+
+ SetRectCheck(self, data, helper.pitch(), self->format(),
+ destination_x, destination_y,
+ texture_width, texture_height,
+ source_width, source_height,
+ values);
+}
+
+} // anonymous namespace
+
+namespace glue {
+namespace namespace_o3d {
+namespace class_Texture2D {
+
+void userglue_method_SetRect(o3d::Texture2D* self,
+ int level,
+ int destination_x,
+ int destination_y,
+ int source_width,
+ const std::vector<float>& values) {
+ SetRectCheck2D(self,
+ level,
+ destination_x,
+ destination_y,
+ source_width,
+ values,
+ false);
+}
+void userglue_method_Set(o3d::Texture2D* self,
+ int level,
+ const std::vector<float>& values) {
+ SetRectCheck2D(self, level, 0, 0, self->width(), values, true);
+}
+
+} // namespace class_Texture2D
+
+namespace class_TextureCUBE {
+
+void userglue_method_SetRect(o3d::TextureCUBE* self,
+ o3d::TextureCUBE::CubeFace face,
+ int level,
+ int destination_x,
+ int destination_y,
+ int source_width,
+ const std::vector<float>& values) {
+ SetRectCheckCUBE(self,
+ face,
+ level,
+ destination_x,
+ destination_y,
+ source_width,
+ values,
+ false);
+}
+void userglue_method_Set(o3d::TextureCUBE* self,
+ o3d::TextureCUBE::CubeFace face,
+ int level,
+ const std::vector<float>& values) {
+ SetRectCheckCUBE(self, face, level, 0, 0, self->edge_length(), values, true);
+}
+
+
+} // namespace class_Texture2D
+
+} // namespace namespace_o3d
+} // namespace glue
+
diff --git a/o3d/plugin/idl/texture.idl b/o3d/plugin/idl/texture.idl index 81d1a5c..763518e 100644 --- a/o3d/plugin/idl/texture.idl +++ b/o3d/plugin/idl/texture.idl @@ -138,7 +138,7 @@ namespace o3d { %] RenderSurface? GetRenderSurface(int mip_level, Pack pack); - // TODO: Add Get, GetRect and/or expose Bitmap. + // TODO: Add Get, GetRect. %[ Sets the values of the data stored in the texture. @@ -166,7 +166,7 @@ namespace o3d { \param level the mip level to update. \param values Values to be stored in the buffer. %] - [nocpp, userglue, include="core/cross/math_utilities.h"] + [nocpp, userglue] void Set(int level, float[] values); %[ @@ -187,7 +187,7 @@ namespace o3d { \param values Values to be stored in the buffer. \see o3d.Texture2D.set %] - [nocpp, userglue, include="core/cross/math_utilities.h"] + [nocpp, userglue] void SetRect(int level, int destination_x, int destination_y, @@ -213,204 +213,6 @@ namespace o3d { int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int dest_mip); - - [verbatim=cpp_glue] %{ - void SetRectCheck(o3d::Texture2D* self, - int level, - int destination_x, - int destination_y, - int source_width, - const std::vector<float>& values, - bool check_needed) { - if (level < 0 || level >= self->levels()) { - O3D_ERROR(self->service_locator()) - << "level (" << level << " out of range"; - return; - } - if (values.empty() || source_width <= 0) { - return; - } - unsigned num_values = values.size(); - unsigned texture_width = std::max(self->width() >> level, 1); - unsigned texture_height = std::max(self->height() >> level, 1); - unsigned num_components; - unsigned swizzle[4] = {2, 1, 0, 3}; - switch (self->format()) { - case o3d::Texture::XRGB8: - num_components = 3; - break; - case o3d::Texture::R32F: - swizzle[0] = 0; - num_components = 1; - break; - case o3d::Texture::ARGB8: - case o3d::Texture::ABGR16F: - num_components = 4; - break; - case o3d::Texture::ABGR32F: { - num_components = 4; - const o3d::Texture::RGBASwizzleIndices& indices = - self->GetABGR32FSwizzleIndices(); - for (int ii = 0; ii < 4; ++ii) { - swizzle[ii] = indices[ii]; - } - break; - } - default: - O3D_ERROR(self->service_locator()) - << "Texture::Set not supported for this type of texture"; - return; - } - if (num_values % num_components != 0) { - O3D_ERROR(self->service_locator()) - << "The number of elements passed in must be a multiple of " - << num_components; - } - unsigned num_elements = num_values / num_components; - if (num_elements % source_width != 0) { - O3D_ERROR(self->service_locator()) - << "The number of elements passed in must be a multiple of the " - << "width"; - return; - } - unsigned source_height = num_elements / source_width; - if (check_needed) { - unsigned needed = num_components * texture_width * texture_height; - if (num_values != needed) { - O3D_ERROR(self->service_locator()) - << "needed " << needed << " values but " << num_values - << " passed in."; - return; - } - } - - // clip - int source_x = 0; - int source_y = 0; - int copy_width = source_width; - int copy_height = source_height; - - if (destination_x < 0) { - copy_width += destination_x; - source_x -= destination_x; - destination_x = 0; - } - if (destination_x + copy_width > static_cast<int>(texture_width)) { - copy_width -= destination_x + copy_width - texture_width; - } - - if (destination_y < 0) { - copy_height += destination_y; - source_y -= destination_y; - destination_y = 0; - } - if (destination_y + copy_height > static_cast<int>(texture_height)) { - copy_height -= destination_y + copy_height - texture_height; - } - - if (copy_width <= 0 || copy_height <= 0) { - return; - } - - void* data; - if (!self->Lock(level, &data)) { - O3D_ERROR(self->service_locator()) << "could not lock texture"; - return; - } - const float* source = - &values[0] + - (source_y * source_width + source_x) * num_components; - unsigned source_stride = (source_width - copy_width) * num_components; - unsigned destination_stride = - (texture_width - copy_width) * num_components; - switch (self->format()) { - case o3d::Texture::ABGR16F: { - unsigned short* destination = - static_cast<unsigned short*>(data) + - (destination_y * texture_width + destination_x) * num_components; - while (copy_height > 0) { - for (int xx = 0; xx < copy_width; ++xx) { - for (unsigned element = 0; element < num_components; ++element) { - destination[element] = Vectormath::Aos::FloatToHalf( - source[swizzle[element]]); - } - destination += num_components; - source += num_components; - } - destination += destination_stride; - source += source_stride; - --copy_height; - } - break; - } - case o3d::Texture::R32F: - case o3d::Texture::ABGR32F: { - float* destination = - static_cast<float*>(data) + - (destination_y * texture_width + destination_x) * num_components; - while (copy_height > 0) { - for (int xx = 0; xx < copy_width; ++xx) { - for (unsigned element = 0; element < num_components; ++element) { - destination[element] = source[swizzle[element]]; - } - destination += num_components; - source += num_components; - } - destination += destination_stride; - source += source_stride; - --copy_height; - } - break; - } - default: { - destination_stride = (texture_width - copy_width) * 4; - uint8* destination = - static_cast<uint8*>(data) + - (destination_y * texture_width + destination_x) * 4; - while (copy_height > 0) { - for (int xx = 0; xx < copy_width; ++xx) { - destination[0] = static_cast<unsigned char>( - source[swizzle[0]] * 255.0f); - destination[1] = static_cast<unsigned char>( - source[swizzle[1]] * 255.0f); - destination[2] = static_cast<unsigned char>( - source[swizzle[2]] * 255.0f); - destination[3] = (num_components == 4) ? - static_cast<unsigned char>(source[swizzle[3]] * 255.0f) : 255; - destination += 4; - source += num_components; - } - destination += destination_stride; - source += source_stride; - --copy_height; - } - break; - } - } - if (!self->Unlock(level)) { - O3D_ERROR(self->service_locator()) << "could not unlock texture"; - } - } - void userglue_method_SetRect(o3d::Texture2D* self, - int level, - int destination_x, - int destination_y, - int source_width, - const std::vector<float>& values) { - SetRectCheck(self, - level, - destination_x, - destination_y, - source_width, - values, - false); - } - void userglue_method_Set(o3d::Texture2D* self, - int level, - const std::vector<float>& values) { - SetRectCheck(self, level, 0, 0, self->width(), values, true); - } - %} }; // Texture2D @@ -458,6 +260,48 @@ namespace o3d { RenderSurface? GetRenderSurface(CubeFace face, int mip_level, Pack pack); %[ + Sets the values of the data stored in the texture. + + It is not recommend that you call this for large textures but it is useful + for making simple ramps or noise textures for shaders. + + See o3d.Texture2D.set for details on formats. + + \param face the face to update. + \param level the mip level to update. + \param values Values to be stored in the buffer. + %] + [nocpp, userglue] + void Set(CubeFace face, int level, float[] values); + + %[ + Sets a rectangular area of values in a texture. + + Does clipping. In other words if you pass in a 10x10 pixel array + and give it destination of (-5, -5) it will only use the bottom 5x5 + pixels of the array you passed in to set the top 5x5 pixels of the + texture. + + See o3d.Texture2D.set for details on formats. + + \param face the face to update. + \param level the mip level to update. + \param destination_x The x coordinate of the area in the texture to affect. + \param destination_y The y coordinate of the area in the texture to affect. + \param source_width The width of the area to effect. The height is + determined by the size of the array passed in. + \param values Values to be stored in the buffer. + \see o3d.Texture2D.set + %] + [nocpp, userglue] + void SetRect(CubeFace face, + int level, + int destination_x, + int destination_y, + int source_width, + float[] values); + + %[ Copy pixels from source bitmap to certain mip level. Scales if the width and height of source and dest do not match. diff --git a/o3d/plugin/plugin.gyp b/o3d/plugin/plugin.gyp index f241187..dc9d65b 100644 --- a/o3d/plugin/plugin.gyp +++ b/o3d/plugin/plugin.gyp @@ -61,6 +61,7 @@ 'cross/plugin_main.h', 'cross/stream_manager.cc', 'cross/stream_manager.h', + 'cross/texture_static_glue.cc', ], 'conditions' : [ ['OS != "linux"', |