summaryrefslogtreecommitdiffstats
path: root/o3d/command_buffer/service/cross/gl
diff options
context:
space:
mode:
authorgspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-27 23:15:42 +0000
committergspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-27 23:15:42 +0000
commit05b47f7a8c5451f858dc220df0e3a97542edace6 (patch)
treea2273d619f0625c9d44d40842845ccce2eac1045 /o3d/command_buffer/service/cross/gl
parent5cdc8bdb4c847cefe7f4542bd10c9880c2c557a0 (diff)
downloadchromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.zip
chromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.tar.gz
chromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.tar.bz2
This is the O3D source tree's initial commit to the Chromium tree. It
is not built or referenced at all by the chrome build yet, and doesn't yet build in it's new home. We'll change that shortly. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17035 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/command_buffer/service/cross/gl')
-rw-r--r--o3d/command_buffer/service/cross/gl/effect_gl.cc633
-rw-r--r--o3d/command_buffer/service/cross/gl/effect_gl.h151
-rw-r--r--o3d/command_buffer/service/cross/gl/gapi_gl.cc141
-rw-r--r--o3d/command_buffer/service/cross/gl/gapi_gl.h395
-rw-r--r--o3d/command_buffer/service/cross/gl/geometry_gl.cc548
-rw-r--r--o3d/command_buffer/service/cross/gl/geometry_gl.h144
-rw-r--r--o3d/command_buffer/service/cross/gl/gl_utils.h63
-rw-r--r--o3d/command_buffer/service/cross/gl/sampler_gl.cc235
-rw-r--r--o3d/command_buffer/service/cross/gl/sampler_gl.h87
-rw-r--r--o3d/command_buffer/service/cross/gl/states_gl.cc342
-rw-r--r--o3d/command_buffer/service/cross/gl/texture_gl.cc678
-rw-r--r--o3d/command_buffer/service/cross/gl/texture_gl.h223
12 files changed, 3640 insertions, 0 deletions
diff --git a/o3d/command_buffer/service/cross/gl/effect_gl.cc b/o3d/command_buffer/service/cross/gl/effect_gl.cc
new file mode 100644
index 0000000..9343d96
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/effect_gl.cc
@@ -0,0 +1,633 @@
+/*
+ * 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.
+ */
+
+
+// This file contains the implementation of the EffectParamGL and EffectGL
+// classes, as well as the effect-related GAPI functions on GL.
+
+#include <map>
+
+#include "base/cross/std_functional.h"
+#include "command_buffer/service/cross/gl/gapi_gl.h"
+#include "command_buffer/service/cross/effect_utils.h"
+
+namespace o3d {
+namespace command_buffer {
+
+EffectParamGL::EffectParamGL(effect_param::DataType data_type,
+ EffectGL *effect,
+ unsigned int param_index)
+ : EffectParam(data_type),
+ effect_(effect),
+ low_level_param_index_(param_index) {
+ DCHECK(effect_);
+ effect_->LinkParam(this);
+}
+
+EffectParamGL::~EffectParamGL() {
+ if (effect_)
+ effect_->UnlinkParam(this);
+}
+
+static effect_param::DataType CgTypeToCBType(CGtype cg_type) {
+ switch (cg_type) {
+ case CG_FLOAT:
+ case CG_FLOAT1:
+ return effect_param::FLOAT1;
+ case CG_FLOAT2:
+ return effect_param::FLOAT2;
+ case CG_FLOAT3:
+ return effect_param::FLOAT3;
+ case CG_FLOAT4:
+ return effect_param::FLOAT4;
+ case CG_INT:
+ case CG_INT1:
+ return effect_param::INT;
+ case CG_BOOL:
+ case CG_BOOL1:
+ return effect_param::BOOL;
+ case CG_FLOAT4x4:
+ return effect_param::MATRIX4;
+ case CG_SAMPLER:
+ case CG_SAMPLER1D:
+ case CG_SAMPLER2D:
+ case CG_SAMPLER3D:
+ case CG_SAMPLERCUBE:
+ return effect_param::SAMPLER;
+ default : {
+ DLOG(INFO) << "Cannot convert CGtype "
+ << cgGetTypeString(cg_type)
+ << " to a Param type.";
+ return effect_param::UNKNOWN;
+ }
+ }
+}
+
+EffectParamGL *EffectParamGL::Create(EffectGL *effect,
+ unsigned int index) {
+ DCHECK(effect);
+ const EffectGL::LowLevelParam &low_level_param =
+ effect->low_level_params_[index];
+ CGtype cg_type =
+ cgGetParameterType(EffectGL::GetEitherCgParameter(low_level_param));
+ effect_param::DataType type = CgTypeToCBType(cg_type);
+ if (type == effect_param::UNKNOWN) return NULL;
+ return new EffectParamGL(type, effect, index);
+}
+
+// Fills the Desc structure, appending name and semantic if any, and if enough
+// room is available in the buffer.
+bool EffectParamGL::GetDesc(unsigned int size, void *data) {
+ using effect_param::Desc;
+ if (size < sizeof(Desc)) // NOLINT
+ return false;
+ if (!effect_)
+ return false;
+ const EffectGL::LowLevelParam &low_level_param =
+ effect_->low_level_params_[low_level_param_index_];
+ CGparameter cg_param = EffectGL::GetEitherCgParameter(low_level_param);
+ const char *name = low_level_param.name;
+ const char* semantic = cgGetParameterSemantic(cg_param);
+ unsigned int name_size =
+ name ? static_cast<unsigned int>(strlen(name)) + 1 : 0;
+ unsigned int semantic_size = semantic ?
+ static_cast<unsigned int>(strlen(semantic)) + 1 : 0;
+ unsigned int total_size = sizeof(Desc) + name_size + semantic_size; // NOLINT
+
+ Desc *desc = static_cast<Desc *>(data);
+ memset(desc, 0, sizeof(*desc));
+ desc->size = total_size;
+ desc->data_type = data_type();
+ desc->data_size = GetDataSize(data_type());
+ desc->name_offset = 0;
+ desc->name_size = name_size;
+ desc->semantic_offset = 0;
+ desc->semantic_size = semantic_size;
+ unsigned int current_offset = sizeof(Desc);
+ if (name && current_offset + name_size <= size) {
+ desc->name_offset = current_offset;
+ memcpy(static_cast<char *>(data) + current_offset, name, name_size);
+ current_offset += name_size;
+ }
+ if (semantic && current_offset + semantic_size <= size) {
+ desc->semantic_offset = current_offset;
+ memcpy(static_cast<char *>(data) + current_offset, semantic, semantic_size);
+ current_offset += semantic_size;
+ }
+ return true;
+}
+
+// Sets the data into the Cg effect parameter, using the appropriate Cg call.
+bool EffectParamGL::SetData(GAPIGL *gapi,
+ unsigned int size,
+ const void * data) {
+ if (!effect_)
+ return false;
+
+ EffectGL::LowLevelParam &low_level_param =
+ effect_->low_level_params_[low_level_param_index_];
+ CGparameter vp_param = low_level_param.vp_param;
+ CGparameter fp_param = low_level_param.fp_param;
+ effect_param::DataType type = data_type();
+ if (size < effect_param::GetDataSize(type))
+ return false;
+
+ switch (type) {
+ case effect_param::FLOAT1:
+ if (vp_param)
+ cgSetParameter1f(vp_param, *static_cast<const float *>(data));
+ if (fp_param)
+ cgSetParameter1f(fp_param, *static_cast<const float *>(data));
+ break;
+ case effect_param::FLOAT2:
+ if (vp_param)
+ cgSetParameter2fv(vp_param, static_cast<const float *>(data));
+ if (fp_param)
+ cgSetParameter2fv(fp_param, static_cast<const float *>(data));
+ break;
+ case effect_param::FLOAT3:
+ if (vp_param)
+ cgSetParameter3fv(vp_param, static_cast<const float *>(data));
+ if (fp_param)
+ cgSetParameter3fv(fp_param, static_cast<const float *>(data));
+ break;
+ case effect_param::FLOAT4:
+ if (vp_param)
+ cgSetParameter4fv(vp_param, static_cast<const float *>(data));
+ if (fp_param)
+ cgSetParameter4fv(fp_param, static_cast<const float *>(data));
+ break;
+ case effect_param::MATRIX4:
+ if (vp_param)
+ cgSetMatrixParameterfr(vp_param, static_cast<const float *>(data));
+ if (fp_param)
+ cgSetMatrixParameterfr(fp_param, static_cast<const float *>(data));
+ break;
+ case effect_param::INT:
+ if (vp_param) cgSetParameter1i(vp_param, *static_cast<const int *>(data));
+ if (fp_param) cgSetParameter1i(fp_param, *static_cast<const int *>(data));
+ break;
+ case effect_param::BOOL: {
+ int bool_value = *static_cast<const bool *>(data)?1:0;
+ if (vp_param) cgSetParameter1i(vp_param, bool_value);
+ if (fp_param) cgSetParameter1i(fp_param, bool_value);
+ break;
+ }
+ case effect_param::SAMPLER: {
+ low_level_param.sampler_id = *static_cast<const ResourceID *>(data);
+ if (effect_ == gapi->current_effect()) {
+ gapi->DirtyEffect();
+ }
+ break;
+ }
+ default:
+ DLOG(ERROR) << "Invalid parameter type.";
+ return false;
+ }
+ return true;
+}
+EffectGL::EffectGL(CGprogram vertex_program,
+ CGprogram fragment_program)
+ : vertex_program_(vertex_program),
+ fragment_program_(fragment_program),
+ update_samplers_(true) {
+}
+
+EffectGL::~EffectGL() {
+ for (ParamResourceList::iterator it = resource_params_.begin();
+ it != resource_params_.end(); ++it) {
+ (*it)->ResetEffect();
+ }
+}
+
+void EffectGL::LinkParam(EffectParamGL *param) {
+ resource_params_.push_back(param);
+}
+
+void EffectGL::UnlinkParam(EffectParamGL *param) {
+ std::remove(resource_params_.begin(), resource_params_.end(), param);
+}
+
+// Rewrites vertex program assembly code to match GL semantics for clipping.
+// This parses the source, breaking it down into pieces:
+// - declaration ("!!ARBvp1.0")
+// - comments (that contain the parameter information)
+// - instructions
+// - "END" token.
+// Then it rewrites the instructions so that 'result.position' doesn't get
+// written directly, instead it is written to a temporary variable. Then a
+// transformation is done on that variable before outputing to
+// 'result.position':
+// - offset x an y by half a pixel (times w).
+// - remap z from [0..w] to [-w..w].
+//
+// Note that for the 1/2 pixel offset, we need a parameter that depends on the
+// current viewport. This is done through 'program.env[0]' which is shared
+// across all programs (so we only have to update it once when we change the
+// viewport), because Cg won't use them currently (it uses 'program.local'
+// instead).
+static bool RewriteVertexProgramSource(String *source) {
+ String::size_type pos = source->find('\n');
+ if (pos == String::npos) {
+ DLOG(ERROR) << "could not find program declaration";
+ return false;
+ }
+ String decl(*source, 0, pos + 1);
+ String::size_type start_comments = pos + 1;
+ // skip the comments that contain the parameters etc.
+ for (; pos < source->size(); pos = source->find('\n', pos)) {
+ ++pos;
+ if (pos >= source->size())
+ break;
+ if ((*source)[pos] != '#')
+ break;
+ }
+ if (pos >= source->size()) {
+ // we only found comments.
+ return false;
+ }
+ String comments(*source, start_comments, pos - start_comments);
+
+ String::size_type end_token = source->find("\nEND", pos + 1);
+ if (end_token == String::npos) {
+ DLOG(ERROR) << "Compiled shader doesn't have an END token";
+ return false;
+ }
+ String instructions(*source, pos, end_token + 1 - pos);
+
+ // Replace accesses to 'result.position' by accesses to our temp variable
+ // '$O3D_HPOS'.
+ // '$' is a valid symbol for identifiers, but Cg doesn't seem to be using
+ // it, so we can use it to ensure we don't have name conflicts.
+ static const char kOutPositionRegister[] = "result.position";
+ for (String::size_type i = instructions.find(kOutPositionRegister);
+ i < String::npos; i = instructions.find(kOutPositionRegister, i)) {
+ instructions.replace(i, strlen(kOutPositionRegister), "$O3D_HPOS");
+ }
+
+ *source = decl +
+ comments +
+ // .x = 1/viewport.width; .y = 1/viewport.height; .z = 2.0;
+ "PARAM $O3D_HELPER = program.env[0];\n"
+ "TEMP $O3D_HPOS;\n" +
+ instructions +
+ // hpos.x <- hpos.x + hpos.w / viewport.width;
+ // hpos.y <- hpos.y - hpos.w / viewport.height;
+ "MAD $O3D_HPOS.xy, $O3D_HELPER.xyyy, $O3D_HPOS.w, $O3D_HPOS.xyyy;\n"
+ // hpos.z <- hpos.z * 2 - hpos.w
+ "MAD $O3D_HPOS.z, $O3D_HPOS.z, $O3D_HELPER.z, -$O3D_HPOS.w;\n"
+ "MOV result.position, $O3D_HPOS;\n"
+ "END\n";
+ return true;
+}
+
+EffectGL *EffectGL::Create(GAPIGL *gapi,
+ const String& effect_code,
+ const String& vertex_program_entry,
+ const String& fragment_program_entry) {
+ CGcontext context = gapi->cg_context();
+ // Compile the original vertex program once, to get the ARBVP1 assembly code.
+ CGprogram original_vp = cgCreateProgram(
+ context, CG_SOURCE, effect_code.c_str(), CG_PROFILE_ARBVP1,
+ vertex_program_entry.c_str(), NULL);
+ const char* listing = cgGetLastListing(context);
+ if (original_vp == NULL) {
+ DLOG(ERROR) << "Effect Compile Error: " << cgGetErrorString(cgGetError())
+ << " : " << listing;
+ return NULL;
+ }
+
+ if (listing && listing[0] != 0) {
+ DLOG(WARNING) << "Effect Compile Warnings: " << listing;
+ }
+
+ String vp_assembly = cgGetProgramString(original_vp, CG_COMPILED_PROGRAM);
+ cgDestroyProgram(original_vp);
+ if (!RewriteVertexProgramSource(&vp_assembly)) {
+ return NULL;
+ }
+ CGprogram vertex_program = cgCreateProgram(
+ context, CG_OBJECT, vp_assembly.c_str(), CG_PROFILE_ARBVP1,
+ vertex_program_entry.c_str(), NULL);
+ listing = cgGetLastListing(context);
+ if (vertex_program == NULL) {
+ DLOG(ERROR) << "Effect post-rewrite Compile Error: "
+ << cgGetErrorString(cgGetError()) << " : " << listing;
+ return false;
+ }
+
+ if (listing && listing[0] != 0) {
+ DLOG(WARNING) << "Effect post-rewrite compile warnings: " << listing;
+ }
+
+ CHECK_GL_ERROR();
+
+ // If the program rewrite introduced some syntax or semantic errors, we won't
+ // know it until we load the program (through a GL error).
+ // So flush all GL errors first...
+ do {} while (glGetError() != GL_NO_ERROR);
+
+ // ... Then load the program ...
+ cgGLLoadProgram(vertex_program);
+
+ // ... And check for GL errors.
+ if (glGetError() != GL_NO_ERROR) {
+ DLOG(ERROR) << "Effect post-rewrite GL Error: "
+ << glGetString(GL_PROGRAM_ERROR_STRING_ARB)
+ << "\nSource: \n"
+ << vp_assembly;
+ return NULL;
+ }
+
+ CGprogram fragment_program = cgCreateProgram(
+ context, CG_SOURCE, effect_code.c_str(), CG_PROFILE_ARBFP1,
+ fragment_program_entry.c_str(), NULL);
+ listing = cgGetLastListing(context);
+ if (fragment_program == NULL) {
+ DLOG(ERROR) << "Effect Compile Error: "
+ << cgGetErrorString(cgGetError()) << " : "
+ << listing;
+ return NULL;
+ }
+
+ if (listing && listing[0] != 0) {
+ DLOG(WARNING) << "Effect Compile Warnings: " << listing;
+ }
+
+ cgGLLoadProgram(fragment_program);
+
+ // Also check for GL errors, in case Cg managed to compile, but generated a
+ // bad program.
+ if (glGetError() != GL_NO_ERROR) {
+ DLOG(ERROR) << "Effect GL Error: "
+ << glGetString(GL_PROGRAM_ERROR_STRING_ARB);
+ return false;
+ }
+ EffectGL *effect = new EffectGL(vertex_program, fragment_program);
+ effect->Initialize();
+ return effect;
+}
+
+int EffectGL::GetLowLevelParamIndexByName(const char *name) {
+ DCHECK(name);
+ for (unsigned int index = 0; index < low_level_params_.size(); ++index) {
+ if (!strcmp(name, low_level_params_[index].name)) {
+ return index;
+ }
+ }
+ return -1;
+}
+
+void EffectGL::AddLowLevelParams(CGparameter cg_param,
+ bool vp) {
+ // Loop over all *leaf* parameters, visiting only CGparameters that have
+ // had storage allocated to them.
+ for (; cg_param != NULL; cg_param = cgGetNextLeafParameter(cg_param)) {
+ CGenum variability = cgGetParameterVariability(cg_param);
+ if (variability != CG_UNIFORM)
+ continue;
+ CGenum direction = cgGetParameterDirection(cg_param);
+ if (direction != CG_IN)
+ continue;
+ const char *name = cgGetParameterName(cg_param);
+ if (!name)
+ continue;
+
+ int index = GetLowLevelParamIndexByName(name);
+ if (index < 0) {
+ LowLevelParam param = {name, NULL, NULL, kInvalidResource};
+ index = low_level_params_.size();
+ low_level_params_.push_back(param);
+ CGtype cg_type = cgGetParameterType(cg_param);
+ if (cg_type == CG_SAMPLER ||
+ cg_type == CG_SAMPLER1D ||
+ cg_type == CG_SAMPLER2D ||
+ cg_type == CG_SAMPLER3D ||
+ cg_type == CG_SAMPLERCUBE) {
+ sampler_params_.push_back(index);
+ }
+ }
+ if (vp) {
+ low_level_params_[index].vp_param = cg_param;
+ } else {
+ low_level_params_[index].fp_param = cg_param;
+ }
+ }
+}
+
+void EffectGL::Initialize() {
+ AddLowLevelParams(cgGetFirstLeafParameter(vertex_program_, CG_PROGRAM), true);
+ AddLowLevelParams(cgGetFirstLeafParameter(vertex_program_, CG_GLOBAL), true);
+ AddLowLevelParams(cgGetFirstLeafParameter(fragment_program_, CG_PROGRAM),
+ false);
+ AddLowLevelParams(cgGetFirstLeafParameter(fragment_program_, CG_GLOBAL),
+ false);
+}
+
+// Begins rendering with the effect, setting all the appropriate states.
+bool EffectGL::Begin(GAPIGL *gapi) {
+ cgGLBindProgram(vertex_program_);
+ cgGLBindProgram(fragment_program_);
+ // sampler->ApplyStates will mess with the texture binding on unit 0, so we
+ // do 2 passes.
+ // First to set the sampler states on the texture
+ for (unsigned int i = 0; i < sampler_params_.size(); ++i) {
+ unsigned int param_index = sampler_params_[i];
+ ResourceID id = low_level_params_[param_index].sampler_id;
+ if (id != kInvalidResource) {
+ SamplerGL *sampler = gapi->GetSampler(id);
+ if (!sampler->ApplyStates(gapi)) {
+ return false;
+ }
+ }
+ }
+ // Second to enable/disable the sampler params.
+ for (unsigned int i = 0; i < sampler_params_.size(); ++i) {
+ unsigned int param_index = sampler_params_[i];
+ const LowLevelParam &ll_param = low_level_params_[param_index];
+ ResourceID id = ll_param.sampler_id;
+ if (id != kInvalidResource) {
+ SamplerGL *sampler = gapi->GetSampler(id);
+ GLuint gl_texture = sampler->gl_texture();
+ cgGLSetTextureParameter(ll_param.fp_param, gl_texture);
+ cgGLEnableTextureParameter(ll_param.fp_param);
+ } else {
+ cgGLSetTextureParameter(ll_param.fp_param, 0);
+ cgGLDisableTextureParameter(ll_param.fp_param);
+ }
+ }
+ return true;
+}
+
+// Terminates rendering with the effect, resetting all the appropriate states.
+void EffectGL::End(GAPIGL *gapi) {
+}
+
+// Gets the parameter count from the list.
+unsigned int EffectGL::GetParamCount() const {
+ return low_level_params_.size();
+}
+
+// Gets a handle to the selected parameter, and wraps it into an
+// EffectParamGL if successful.
+EffectParamGL *EffectGL::CreateParam(unsigned int index) {
+ if (index < low_level_params_.size()) return NULL;
+ return EffectParamGL::Create(this, index);
+}
+
+// Gets a handle to the selected parameter, and wraps it into an
+// EffectParamGL if successful.
+EffectParamGL *EffectGL::CreateParamByName(const char *name) {
+ int index = GetLowLevelParamIndexByName(name);
+ if (index < 0) return NULL;
+ EffectParamGL::Create(this, index);
+}
+
+BufferSyncInterface::ParseError GAPIGL::CreateEffect(ResourceID id,
+ unsigned int size,
+ const void *data) {
+ if (id == current_effect_id_) DirtyEffect();
+ // Even though Assign would Destroy the effect at id, we do it explicitly in
+ // case the creation fails.
+ effects_.Destroy(id);
+ // Data is vp_main \0 fp_main \0 effect_text.
+ String vertex_program_entry;
+ String fragment_program_entry;
+ String effect_code;
+ if (!ParseEffectData(size, data,
+ &vertex_program_entry,
+ &fragment_program_entry,
+ &effect_code)) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ EffectGL * effect = EffectGL::Create(this, effect_code,
+ vertex_program_entry,
+ fragment_program_entry);
+ if (!effect) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ effects_.Assign(id, effect);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::DestroyEffect(ResourceID id) {
+ if (id == current_effect_id_) DirtyEffect();
+ return effects_.Destroy(id) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+BufferSyncInterface::ParseError GAPIGL::SetEffect(ResourceID id) {
+ DirtyEffect();
+ current_effect_id_ = id;
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::GetParamCount(ResourceID id,
+ unsigned int size,
+ void *data) {
+ EffectGL *effect = effects_.Get(id);
+ if (!effect || size < sizeof(Uint32)) // NOLINT
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ *static_cast<Uint32 *>(data) = effect->GetParamCount();
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::CreateParam(ResourceID param_id,
+ ResourceID effect_id,
+ unsigned int index) {
+ EffectGL *effect = effects_.Get(effect_id);
+ if (!effect) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ EffectParamGL *param = effect->CreateParam(index);
+ if (!param) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ effect_params_.Assign(param_id, param);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::CreateParamByName(ResourceID param_id,
+ ResourceID effect_id,
+ unsigned int size,
+ const void *name) {
+ EffectGL *effect = effects_.Get(effect_id);
+ if (!effect) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ std::string string_name(static_cast<const char *>(name), size);
+ EffectParamGL *param = effect->CreateParamByName(string_name.c_str());
+ if (!param) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ effect_params_.Assign(param_id, param);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::DestroyParam(ResourceID id) {
+ return effect_params_.Destroy(id) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+BufferSyncInterface::ParseError GAPIGL::SetParamData(ResourceID id,
+ unsigned int size,
+ const void *data) {
+ EffectParamGL *param = effect_params_.Get(id);
+ if (!param) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ return param->SetData(this, size, data) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+BufferSyncInterface::ParseError GAPIGL::GetParamDesc(ResourceID id,
+ unsigned int size,
+ void *data) {
+ EffectParamGL *param = effect_params_.Get(id);
+ if (!param) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ return param->GetDesc(size, data) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+// If the current effect is valid, call End on it, and tag for revalidation.
+void GAPIGL::DirtyEffect() {
+ if (validate_effect_) return;
+ DCHECK(current_effect_);
+ current_effect_->End(this);
+ current_effect_ = NULL;
+ validate_effect_ = true;
+}
+
+// Gets the current effect, and calls Begin on it (if successful).
+// Should only be called if the current effect is not valid.
+bool GAPIGL::ValidateEffect() {
+ DCHECK(validate_effect_);
+ DCHECK(!current_effect_);
+ current_effect_ = effects_.Get(current_effect_id_);
+ if (!current_effect_) return false;
+ validate_effect_ = false;
+ return current_effect_->Begin(this);
+}
+
+} // namespace command_buffer
+} // namespace o3d
diff --git a/o3d/command_buffer/service/cross/gl/effect_gl.h b/o3d/command_buffer/service/cross/gl/effect_gl.h
new file mode 100644
index 0000000..fc29bf3
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/effect_gl.h
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+
+// This file contains the declaration of the EffectParamGL and EffectGL classes.
+
+#ifndef O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_EFFECT_GL_H_
+#define O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_EFFECT_GL_H_
+
+#include <vector>
+#include "command_buffer/common/cross/gapi_interface.h"
+#include "command_buffer/service/cross/resource.h"
+#include "command_buffer/service/cross/gl/gl_utils.h"
+
+namespace o3d {
+namespace command_buffer {
+
+class GAPIGL;
+class EffectGL;
+
+// GL version of EffectParam.
+class EffectParamGL: public EffectParam {
+ public:
+ EffectParamGL(effect_param::DataType data_type,
+ EffectGL *effect,
+ unsigned int param_index);
+ virtual ~EffectParamGL();
+
+ // Sets the data into the GL effect parameter.
+ bool SetData(GAPIGL *gapi, unsigned int size, const void * data);
+
+ // Gets the description of the parameter.
+ bool GetDesc(unsigned int size, void *data);
+
+ // Resets the effect back-pointer. This is called when the effect gets
+ // destroyed, to invalidate the parameter.
+ void ResetEffect() { effect_ = NULL; }
+
+ // Creates an EffectParamGL from the EffectGL, by index.
+ static EffectParamGL *Create(EffectGL *effect,
+ unsigned int index);
+ private:
+ EffectGL *effect_;
+ unsigned int low_level_param_index_;
+ DISALLOW_COPY_AND_ASSIGN(EffectParamGL);
+};
+
+// GL version of Effect.
+class EffectGL : public Effect {
+ public:
+ EffectGL(CGprogram vertex_program,
+ CGprogram fragment_program);
+ virtual ~EffectGL();
+
+ // Compiles and creates an effect from source code.
+ static EffectGL *Create(GAPIGL *gapi,
+ const String &effect_code,
+ const String &vertex_program_entry,
+ const String &fragment_program_entry);
+
+ // Applies the effect states (vertex shader, pixel shader) to GL.
+ bool Begin(GAPIGL *gapi);
+
+ // Resets the effect states (vertex shader, pixel shader) to GL.
+ void End(GAPIGL *gapi);
+
+ // Gets the number of parameters in the effect.
+ unsigned int GetParamCount() const;
+
+ // Creates an effect parameter with the specified index.
+ EffectParamGL *CreateParam(unsigned int index);
+
+ // Creates an effect parameter of the specified name.
+ EffectParamGL *CreateParamByName(const char *name);
+
+ private:
+ struct LowLevelParam {
+ const char *name;
+ CGparameter vp_param;
+ CGparameter fp_param;
+ ResourceID sampler_id;
+ };
+ typedef std::vector<LowLevelParam> LowLevelParamList;
+ typedef std::vector<EffectParamGL *> ParamResourceList;
+
+ static CGparameter GetEitherCgParameter(
+ const LowLevelParam &low_level_param) {
+ return low_level_param.vp_param ?
+ low_level_param.vp_param : low_level_param.fp_param;
+ }
+
+ int GetLowLevelParamIndexByName(const char *name);
+ void AddLowLevelParams(CGparameter cg_param, bool vp);
+
+ // Creates the low level structures.
+ void Initialize();
+
+ // Links a param into this effect.
+ void LinkParam(EffectParamGL *param);
+
+ // Unlinks a param into this effect.
+ void UnlinkParam(EffectParamGL *param);
+
+ CGprogram vertex_program_;
+ CGprogram fragment_program_;
+ // List of all the Param resources created.
+ ParamResourceList resource_params_;
+ // List of all the Cg parameters present in either the vertex program or the
+ // fragment program.
+ LowLevelParamList low_level_params_;
+ // List of the indices of the low level params that are samplers.
+ std::vector<unsigned int> sampler_params_;
+ bool update_samplers_;
+
+ friend class EffectParamGL;
+ DISALLOW_COPY_AND_ASSIGN(EffectGL);
+};
+
+
+} // namespace command_buffer
+} // namespace o3d
+
+#endif // O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_EFFECT_GL_H_
diff --git a/o3d/command_buffer/service/cross/gl/gapi_gl.cc b/o3d/command_buffer/service/cross/gl/gapi_gl.cc
new file mode 100644
index 0000000..a09375a
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/gapi_gl.cc
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+
+// This file implements the GAPIGL class.
+
+#include <build/build_config.h>
+#include "command_buffer/service/cross/gl/gl_utils.h"
+#include "command_buffer/service/cross/gl/gapi_gl.h"
+
+#ifdef OS_LINUX
+#include "command_buffer/service/linux/x_utils.h"
+#endif // OS_LINUX
+
+namespace o3d {
+namespace command_buffer {
+
+GAPIGL::GAPIGL()
+#ifdef OS_LINUX
+ : window_(NULL),
+#endif
+ cg_context_(NULL),
+ current_vertex_struct_(kInvalidResource),
+ validate_streams_(true),
+ max_vertices_(0),
+ current_effect_id_(kInvalidResource),
+ validate_effect_(true),
+ current_effect_(NULL) {
+}
+
+GAPIGL::~GAPIGL() {
+}
+
+bool GAPIGL::Initialize() {
+#ifdef OS_LINUX
+ DCHECK(window_);
+ if (!window_->Initialize())
+ return false;
+ if (!window_->MakeCurrent())
+ return false;
+ InitCommon();
+ CHECK_GL_ERROR();
+ return true;
+#else
+ return false;
+#endif
+}
+
+void GAPIGL::InitCommon() {
+ cg_context_ = cgCreateContext();
+ // Set up all Cg State Assignments for OpenGL.
+ cgGLRegisterStates(cg_context_);
+ cgGLSetDebugMode(CG_FALSE);
+ // Enable the profiles we use.
+ cgGLEnableProfile(CG_PROFILE_ARBVP1);
+ cgGLEnableProfile(CG_PROFILE_ARBFP1);
+ // Initialize global GL settings.
+ // Tell GL that texture buffers can be single-byte aligned.
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+ glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
+
+ // Get the initial viewport (set to the window size) to set up the helper
+ // constant.
+ GLint viewport[4];
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ SetViewport(viewport[0], viewport[1], viewport[2], viewport[3], 0.f, 1.f);
+ CHECK_GL_ERROR();
+}
+
+void GAPIGL::Destroy() {
+ vertex_buffers_.DestroyAllResources();
+ index_buffers_.DestroyAllResources();
+ vertex_structs_.DestroyAllResources();
+ effects_.DestroyAllResources();
+ effect_params_.DestroyAllResources();
+ // textures_.DestroyAllResources();
+ // samplers_.DestroyAllResources();
+ cgDestroyContext(cg_context_);
+ cg_context_ = NULL;
+#ifdef OS_LINUX
+ DCHECK(window_);
+ window_->Destroy();
+#endif
+}
+
+void GAPIGL::BeginFrame() {
+}
+
+void GAPIGL::EndFrame() {
+#ifdef OS_LINUX
+ DCHECK(window_);
+ window_->SwapBuffers();
+#endif
+ CHECK_GL_ERROR();
+}
+
+void GAPIGL::Clear(unsigned int buffers,
+ const RGBA &color,
+ float depth,
+ unsigned int stencil) {
+ glClearColor(color.red, color.green, color.blue, color.alpha);
+ glClearDepth(depth);
+ glClearStencil(stencil);
+ glClear((buffers & COLOR ? GL_COLOR_BUFFER_BIT : 0) |
+ (buffers & DEPTH ? GL_DEPTH_BUFFER_BIT : 0) |
+ (buffers & STENCIL ? GL_STENCIL_BUFFER_BIT : 0));
+ CHECK_GL_ERROR();
+}
+
+} // namespace command_buffer
+} // namespace o3d
diff --git a/o3d/command_buffer/service/cross/gl/gapi_gl.h b/o3d/command_buffer/service/cross/gl/gapi_gl.h
new file mode 100644
index 0000000..8d71800
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/gapi_gl.h
@@ -0,0 +1,395 @@
+/*
+ * 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.
+ */
+
+
+// This file contains the GAPIGL class, implementing the GAPI interface for
+// GL.
+
+#ifndef O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_GAPI_GL_H__
+#define O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_GAPI_GL_H__
+
+#include <build/build_config.h>
+#include "command_buffer/common/cross/gapi_interface.h"
+#include "command_buffer/service/cross/gl/gl_utils.h"
+#include "command_buffer/service/cross/gl/effect_gl.h"
+#include "command_buffer/service/cross/gl/geometry_gl.h"
+#include "command_buffer/service/cross/gl/sampler_gl.h"
+#include "command_buffer/service/cross/gl/texture_gl.h"
+
+namespace o3d {
+namespace command_buffer {
+#if defined(OS_LINUX)
+class XWindowWrapper;
+#endif // defined(OS_LINUX)
+
+// This class implements the GAPI interface for GL.
+class GAPIGL : public GAPIInterface {
+ public:
+ GAPIGL();
+ virtual ~GAPIGL();
+
+#if defined(OS_LINUX)
+ void set_window_wrapper(XWindowWrapper *window) { window_ = window; }
+#elif defined(OS_WIN)
+ void set_hwnd(HWND hwnd) { hwnd_ = hwnd; }
+#endif
+
+ // Initializes the graphics context, bound to a window.
+ // Returns:
+ // true if successful.
+ virtual bool Initialize();
+
+ // Destroys the graphics context.
+ virtual void Destroy();
+
+ // Implements the BeginFrame function for GL.
+ virtual void BeginFrame();
+
+ // Implements the EndFrame function for GL.
+ virtual void EndFrame();
+
+ // Implements the Clear function for GL.
+ virtual void Clear(unsigned int buffers,
+ const RGBA &color,
+ float depth,
+ unsigned int stencil);
+
+ // Implements the SetViewport function for GL.
+ virtual void SetViewport(unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height,
+ float z_min,
+ float z_max);
+
+ // Implements the CreateVertexBuffer function for GL.
+ virtual ParseError CreateVertexBuffer(ResourceID id,
+ unsigned int size,
+ unsigned int flags);
+
+ // Implements the DestroyVertexBuffer function for GL.
+ virtual ParseError DestroyVertexBuffer(ResourceID id);
+
+ // Implements the SetVertexBufferData function for GL.
+ virtual ParseError SetVertexBufferData(ResourceID id,
+ unsigned int offset,
+ unsigned int size,
+ const void *data);
+
+ // Implements the GetVertexBufferData function for GL.
+ virtual ParseError GetVertexBufferData(ResourceID id,
+ unsigned int offset,
+ unsigned int size,
+ void *data);
+
+ // Implements the CreateIndexBuffer function for GL.
+ virtual ParseError CreateIndexBuffer(ResourceID id,
+ unsigned int size,
+ unsigned int flags);
+
+ // Implements the DestroyIndexBuffer function for GL.
+ virtual ParseError DestroyIndexBuffer(ResourceID id);
+
+ // Implements the SetIndexBufferData function for GL.
+ virtual ParseError SetIndexBufferData(ResourceID id,
+ unsigned int offset,
+ unsigned int size,
+ const void *data);
+
+ // Implements the GetIndexBufferData function for GL.
+ virtual ParseError GetIndexBufferData(ResourceID id,
+ unsigned int offset,
+ unsigned int size,
+ void *data);
+
+ // Implements the CreateVertexStruct function for GL.
+ virtual ParseError CreateVertexStruct(ResourceID id,
+ unsigned int input_count);
+
+ // Implements the DestroyVertexStruct function for GL.
+ virtual ParseError DestroyVertexStruct(ResourceID id);
+
+ // Implements the SetVertexInput function for GL.
+ virtual ParseError SetVertexInput(ResourceID vertex_struct_id,
+ unsigned int input_index,
+ ResourceID vertex_buffer_id,
+ unsigned int offset,
+ unsigned int stride,
+ vertex_struct::Type type,
+ vertex_struct::Semantic semantic,
+ unsigned int semantic_index);
+
+ // Implements the SetVertexStruct function for GL.
+ virtual ParseError SetVertexStruct(ResourceID id);
+
+ // Implements the Draw function for GL.
+ virtual ParseError Draw(PrimitiveType primitive_type,
+ unsigned int first,
+ unsigned int count);
+
+ // Implements the DrawIndexed function for GL.
+ virtual ParseError DrawIndexed(PrimitiveType primitive_type,
+ ResourceID index_buffer_id,
+ unsigned int first,
+ unsigned int count,
+ unsigned int min_index,
+ unsigned int max_index);
+
+ // Implements the CreateEffect function for GL.
+ virtual ParseError CreateEffect(ResourceID id,
+ unsigned int size,
+ const void *data);
+
+ // Implements the DestroyEffect function for GL.
+ virtual ParseError DestroyEffect(ResourceID id);
+
+ // Implements the SetEffect function for GL.
+ virtual ParseError SetEffect(ResourceID id);
+
+ // Implements the GetParamCount function for GL.
+ virtual ParseError GetParamCount(ResourceID id,
+ unsigned int size,
+ void *data);
+
+ // Implements the CreateParam function for GL.
+ virtual ParseError CreateParam(ResourceID param_id,
+ ResourceID effect_id,
+ unsigned int index);
+
+ // Implements the CreateParamByName function for GL.
+ virtual ParseError CreateParamByName(ResourceID param_id,
+ ResourceID effect_id,
+ unsigned int size,
+ const void *name);
+
+ // Implements the DestroyParam function for GL.
+ virtual ParseError DestroyParam(ResourceID id);
+
+ // Implements the SetParamData function for GL.
+ virtual ParseError SetParamData(ResourceID id,
+ unsigned int size,
+ const void *data);
+
+ // Implements the GetParamDesc function for GL.
+ virtual ParseError GetParamDesc(ResourceID id,
+ unsigned int size,
+ void *data);
+
+ // Implements the CreateTexture2D function for GL.
+ virtual ParseError CreateTexture2D(ResourceID id,
+ unsigned int width,
+ unsigned int height,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags);
+
+ // Implements the CreateTexture3D function for GL.
+ virtual ParseError CreateTexture3D(ResourceID id,
+ unsigned int width,
+ unsigned int height,
+ unsigned int depth,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags);
+
+ // Implements the CreateTextureCube function for GL.
+ virtual ParseError CreateTextureCube(ResourceID id,
+ unsigned int side,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags);
+
+ // Implements the SetTextureData function for GL.
+ virtual ParseError SetTextureData(ResourceID id,
+ unsigned int x,
+ unsigned int y,
+ unsigned int z,
+ unsigned int width,
+ unsigned int height,
+ unsigned int depth,
+ unsigned int level,
+ texture::Face face,
+ unsigned int pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ const void *data);
+
+ // Implements the GetTextureData function for GL.
+ virtual ParseError GetTextureData(ResourceID id,
+ unsigned int x,
+ unsigned int y,
+ unsigned int z,
+ unsigned int width,
+ unsigned int height,
+ unsigned int depth,
+ unsigned int level,
+ texture::Face face,
+ unsigned int pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ void *data);
+
+ // Implements the DestroyTexture function for GL.
+ virtual ParseError DestroyTexture(ResourceID id);
+
+ // Implements the CreateSampler function for GL.
+ virtual ParseError CreateSampler(ResourceID id);
+
+ // Implements the DestroySampler function for GL.
+ virtual ParseError DestroySampler(ResourceID id);
+
+ // Implements the SetSamplerStates function for GL.
+ virtual ParseError SetSamplerStates(ResourceID id,
+ sampler::AddressingMode addressing_u,
+ sampler::AddressingMode addressing_v,
+ sampler::AddressingMode addressing_w,
+ sampler::FilteringMode mag_filter,
+ sampler::FilteringMode min_filter,
+ sampler::FilteringMode mip_filter,
+ unsigned int max_anisotropy);
+
+ // Implements the SetSamplerBorderColor function for GL.
+ virtual ParseError SetSamplerBorderColor(ResourceID id, const RGBA &color);
+
+ // Implements the SetSamplerTexture function for GL.
+ virtual ParseError SetSamplerTexture(ResourceID id, ResourceID texture_id);
+
+ // Implements the SetScissor function for GL.
+ virtual void SetScissor(bool enable,
+ unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height);
+
+ // Implements the SetPointLineRaster function for GL.
+ virtual void SetPointLineRaster(bool line_smooth,
+ bool point_sprite,
+ float point_size);
+
+ // Implements the SetPolygonOffset function for GL.
+ virtual void SetPolygonOffset(float slope_factor, float units);
+
+ // Implements the SetPolygonRaster function for GL.
+ virtual void SetPolygonRaster(PolygonMode fill_mode,
+ FaceCullMode cull_mode);
+
+ // Implements the SetAlphaTest function for GL.
+ virtual void SetAlphaTest(bool enable,
+ float reference,
+ Comparison comp);
+
+ // Implements the SetDepthTest function for GL.
+ virtual void SetDepthTest(bool enable,
+ bool write_enable,
+ Comparison comp);
+
+ // Implements the SetStencilTest function for GL.
+ virtual void SetStencilTest(bool enable,
+ bool separate_ccw,
+ unsigned int write_mask,
+ unsigned int compare_mask,
+ unsigned int ref,
+ Uint32 func_ops);
+
+ // Implements the SetColorWritefunction for GL.
+ virtual void SetColorWrite(bool red,
+ bool green,
+ bool blue,
+ bool alpha,
+ bool dither);
+
+ // Implements the SetBlending function for GL.
+ virtual void SetBlending(bool enable,
+ bool separate_alpha,
+ BlendEq color_eq,
+ BlendFunc color_src_func,
+ BlendFunc color_dst_func,
+ BlendEq alpha_eq,
+ BlendFunc alpha_src_func,
+ BlendFunc alpha_dst_func);
+
+ // Implements the SetBlendingColor function for GL.
+ virtual void SetBlendingColor(const RGBA &color);
+
+ // Gets a vertex buffer by resource ID.
+ VertexBufferGL *GetVertexBuffer(ResourceID id) {
+ return vertex_buffers_.Get(id);
+ }
+
+ // Gets a texture by resource ID.
+ TextureGL *GetTexture(ResourceID id) {
+ return textures_.Get(id);
+ }
+
+ // Gets a sampler by resource ID.
+ SamplerGL *GetSampler(ResourceID id) {
+ return samplers_.Get(id);
+ }
+
+ CGcontext cg_context() const { return cg_context_; }
+
+ EffectGL *current_effect() const { return current_effect_; }
+ // "Dirty" the current effect. This resets the vertex and fragment program,
+ // and requires ValidateEffect() to be called before further draws occur.
+ void DirtyEffect();
+ private:
+ void InitCommon();
+ // Validates the current vertex struct to GL, setting the vertex attributes.
+ bool ValidateStreams();
+ // Validates the current effect to GL. This sets the vertex and fragment
+ // programs, and updates parameters if needed.
+ bool ValidateEffect();
+
+#ifdef OS_LINUX
+ XWindowWrapper *window_;
+#endif
+ CGcontext cg_context_;
+
+ ResourceID current_vertex_struct_;
+ bool validate_streams_;
+ unsigned int max_vertices_;
+ ResourceID current_effect_id_;
+ bool validate_effect_;
+ EffectGL *current_effect_;
+
+ ResourceMap<VertexBufferGL> vertex_buffers_;
+ ResourceMap<IndexBufferGL> index_buffers_;
+ ResourceMap<VertexStructGL> vertex_structs_;
+ ResourceMap<EffectGL> effects_;
+ ResourceMap<EffectParamGL> effect_params_;
+ ResourceMap<TextureGL> textures_;
+ ResourceMap<SamplerGL> samplers_;
+};
+
+} // namespace command_buffer
+} // namespace o3d
+
+#endif // O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_GAPI_GL_H__
diff --git a/o3d/command_buffer/service/cross/gl/geometry_gl.cc b/o3d/command_buffer/service/cross/gl/geometry_gl.cc
new file mode 100644
index 0000000..2dd8758
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/geometry_gl.cc
@@ -0,0 +1,548 @@
+/*
+ * 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.
+ */
+
+
+// This file contains the implementation of the VertexBufferGL, IndexBufferGL
+// and VertexStructGL classes, as well as the geometry-related GAPI functions.
+
+#include "command_buffer/service/cross/gl/gapi_gl.h"
+#include "command_buffer/service/cross/gl/geometry_gl.h"
+
+namespace o3d {
+namespace command_buffer {
+
+VertexBufferGL::~VertexBufferGL() {
+ glDeleteBuffers(1, &gl_buffer_);
+ CHECK_GL_ERROR();
+}
+
+// Creates the GL buffer object.
+void VertexBufferGL::Create() {
+ glGenBuffers(1, &gl_buffer_);
+ glBindBuffer(GL_ARRAY_BUFFER, gl_buffer_);
+ GLenum usage =
+ (flags() & vertex_buffer::DYNAMIC) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
+ glBufferData(GL_ARRAY_BUFFER, size(), NULL, usage);
+ CHECK_GL_ERROR();
+}
+
+// Sets the data into the GL buffer object.
+bool VertexBufferGL::SetData(unsigned int offset,
+ unsigned int size,
+ const void *data) {
+ if (!gl_buffer_) {
+ LOG(ERROR) << "Calling SetData on a non-initialized VertexBufferGL.";
+ return false;
+ }
+ if ((offset >= this->size()) || (offset + size > this->size())) {
+ LOG(ERROR) << "Invalid size or offset on VertexBufferGL::SetData.";
+ return false;
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, gl_buffer_);
+ glBufferSubData(GL_ARRAY_BUFFER, offset, size, data);
+ CHECK_GL_ERROR();
+ return true;
+}
+
+// Gets the data from the GL buffer object.
+bool VertexBufferGL::GetData(unsigned int offset,
+ unsigned int size,
+ void *data) {
+ if (!gl_buffer_) {
+ LOG(ERROR) << "Calling GetData on a non-initialized VertexBufferGL.";
+ return false;
+ }
+ if ((offset >= this->size()) || (offset + size > this->size())) {
+ LOG(ERROR) << "Invalid size or offset on VertexBufferGL::GetData.";
+ return false;
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, gl_buffer_);
+ glGetBufferSubData(GL_ARRAY_BUFFER, offset, size, data);
+ CHECK_GL_ERROR();
+ return true;
+}
+
+IndexBufferGL::~IndexBufferGL() {
+ glDeleteBuffers(1, &gl_buffer_);
+}
+
+// Creates the GL buffer object.
+void IndexBufferGL::Create() {
+ glGenBuffers(1, &gl_buffer_);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_buffer_);
+ GLenum usage =
+ (flags() & vertex_buffer::DYNAMIC) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, size(), NULL, usage);
+ CHECK_GL_ERROR();
+}
+
+// Sets the data into the GL buffer object.
+bool IndexBufferGL::SetData(unsigned int offset,
+ unsigned int size,
+ const void *data) {
+ if (!gl_buffer_) {
+ LOG(ERROR) << "Calling SetData on a non-initialized IndexBufferGL.";
+ return false;
+ }
+ if ((offset >= this->size()) || (offset + size > this->size())) {
+ LOG(ERROR) << "Invalid size or offset on IndexBufferGL::SetData.";
+ return false;
+ }
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_buffer_);
+ glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, data);
+ CHECK_GL_ERROR();
+ return true;
+}
+
+// Gets the data from the GL buffer object.
+bool IndexBufferGL::GetData(unsigned int offset,
+ unsigned int size,
+ void *data) {
+ if (!gl_buffer_) {
+ LOG(ERROR) << "Calling GetData on a non-initialized IndexBufferGL.";
+ return false;
+ }
+ if ((offset >= this->size()) || (offset + size > this->size())) {
+ LOG(ERROR) << "Invalid size or offset on IndexBufferGL::GetData.";
+ return false;
+ }
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_buffer_);
+ glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, data);
+ CHECK_GL_ERROR();
+ return true;
+}
+
+// Sets the input element in the VertexStruct resource.
+void VertexStructGL::SetInput(unsigned int input_index,
+ ResourceID vertex_buffer_id,
+ unsigned int offset,
+ unsigned int stride,
+ vertex_struct::Type type,
+ vertex_struct::Semantic semantic,
+ unsigned int semantic_index) {
+ Element &element = GetElement(input_index);
+ element.vertex_buffer = vertex_buffer_id;
+ element.offset = offset;
+ element.stride = stride;
+ element.type = type;
+ element.semantic = semantic;
+ element.semantic_index = semantic_index;
+ dirty_ = true;
+}
+
+namespace {
+
+inline const GLvoid *OffsetToPtr(GLintptr offset) {
+ return static_cast<char *>(NULL) + offset;
+}
+
+} // anonymous namespace
+
+unsigned int VertexStructGL::SetStreams(GAPIGL *gapi) {
+ if (dirty_) Compile();
+ unsigned int max_vertices = UINT_MAX;
+ for (unsigned int i = 0; i < kMaxAttribs; ++i) {
+ const AttribDesc &attrib = attribs_[i];
+ if (attrib.vertex_buffer_id == kInvalidResource) {
+ if (i == 0) {
+ glDisableClientState(GL_VERTEX_ARRAY);
+ } else {
+ glDisableVertexAttribArray(i);
+ }
+ } else {
+ glEnableVertexAttribArray(i);
+ VertexBufferGL *vertex_buffer =
+ gapi->GetVertexBuffer(attrib.vertex_buffer_id);
+ if (!vertex_buffer) {
+ glDisableVertexAttribArray(i);
+ max_vertices = 0;
+ continue;
+ }
+ DCHECK_NE(vertex_buffer->gl_buffer(), 0);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer->gl_buffer());
+ glVertexAttribPointer(i, attrib.size, attrib.type, attrib.normalized,
+ attrib.stride, OffsetToPtr(attrib.offset));
+ max_vertices = std::min(max_vertices,
+ vertex_buffer->size() / attrib.stride);
+ }
+ }
+ CHECK_GL_ERROR();
+ return max_vertices;
+}
+
+namespace {
+
+// from the ARB_vertex_program extension, at
+// http://www.opengl.org/registry/specs/ARB/vertex_program.txt
+//
+// Generic
+// Attribute Conventional Attribute Conventional Attribute Command
+// --------- ------------------------ ------------------------------
+// 0 vertex position Vertex
+// 1 vertex weights 0-3 WeightARB, VertexWeightEXT
+// 2 normal Normal
+// 3 primary color Color
+// 4 secondary color SecondaryColorEXT
+// 5 fog coordinate FogCoordEXT
+// 6 - -
+// 7 - -
+// 8 texture coordinate set 0 MultiTexCoord(TEXTURE0, ...)
+// 9 texture coordinate set 1 MultiTexCoord(TEXTURE1, ...)
+// 10 texture coordinate set 2 MultiTexCoord(TEXTURE2, ...)
+// 11 texture coordinate set 3 MultiTexCoord(TEXTURE3, ...)
+// 12 texture coordinate set 4 MultiTexCoord(TEXTURE4, ...)
+// 13 texture coordinate set 5 MultiTexCoord(TEXTURE5, ...)
+// 14 texture coordinate set 6 MultiTexCoord(TEXTURE6, ...)
+// 15 texture coordinate set 7 MultiTexCoord(TEXTURE7, ...)
+// 8+n texture coordinate set n MultiTexCoord(TEXTURE0+n, ...)
+//
+// Note: we only accept at most 8 texture coordinates for maximum compatibility
+// with DirectX.
+
+inline unsigned int GetAttribIndex(vertex_struct::Semantic semantic,
+ unsigned int semantic_index) {
+ switch (semantic) {
+ case vertex_struct::POSITION:
+ DCHECK_EQ(semantic_index, 0);
+ return 0;
+ case vertex_struct::NORMAL:
+ DCHECK_EQ(semantic_index, 0);
+ return 2;
+ case vertex_struct::COLOR:
+ DCHECK_LT(semantic_index, 2);
+ return 3 + semantic_index;
+ case vertex_struct::TEX_COORD:
+ DCHECK_LT(semantic_index, 8);
+ return 8 + semantic_index;
+ default:
+ DLOG(FATAL) << "Not reached.";
+ break;
+ }
+}
+
+inline void ExtractSizeTypeNormalized(vertex_struct::Type type,
+ GLint *size,
+ GLenum *gl_type,
+ GLboolean *normalized) {
+ switch (type) {
+ case vertex_struct::FLOAT1:
+ case vertex_struct::FLOAT2:
+ case vertex_struct::FLOAT3:
+ case vertex_struct::FLOAT4:
+ *size = type - vertex_struct::FLOAT1 + 1;
+ *gl_type = GL_FLOAT;
+ *normalized = false;
+ break;
+ case vertex_struct::UCHAR4N:
+ *size = 4;
+ *gl_type = GL_UNSIGNED_BYTE;
+ *normalized = true;
+ break;
+ default:
+ DLOG(FATAL) << "Not reached.";
+ break;
+ }
+}
+
+} // anonymous namespace
+
+#ifndef COMPILER_MSVC
+// Although required by the spec, this causes problems on MSVC. It is needed by
+// GCC.
+const unsigned int VertexStructGL::kMaxAttribs;
+#endif
+
+void VertexStructGL::Compile() {
+ DCHECK(dirty_);
+ for (unsigned int i = 0; i < kMaxAttribs; ++i) {
+ attribs_[i].vertex_buffer_id = kInvalidResource;
+ }
+ for (unsigned int i = 0; i < count_ ; ++i) {
+ const Element &element = GetElement(i);
+ unsigned int index = GetAttribIndex(element.semantic,
+ element.semantic_index);
+ DCHECK_LT(index, kMaxAttribs);
+ AttribDesc &attrib = attribs_[index];
+ attrib.vertex_buffer_id = element.vertex_buffer;
+ ExtractSizeTypeNormalized(element.type, &attrib.size, &attrib.type,
+ &attrib.normalized);
+ attrib.stride = element.stride;
+ attrib.offset = element.offset;
+ }
+ dirty_ = false;
+}
+
+BufferSyncInterface::ParseError GAPIGL::CreateVertexBuffer(ResourceID id,
+ unsigned int size,
+ unsigned int flags) {
+ VertexBufferGL *vertex_buffer = new VertexBufferGL(size, flags);
+ vertex_buffer->Create();
+ vertex_buffers_.Assign(id, vertex_buffer);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::DestroyVertexBuffer(ResourceID id) {
+ return vertex_buffers_.Destroy(id) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+BufferSyncInterface::ParseError GAPIGL::SetVertexBufferData(ResourceID id,
+ unsigned int offset,
+ unsigned int size,
+ const void *data) {
+ VertexBufferGL *vertex_buffer = vertex_buffers_.Get(id);
+ if (!vertex_buffer) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ return vertex_buffer->SetData(offset, size, data) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+BufferSyncInterface::ParseError GAPIGL::GetVertexBufferData(ResourceID id,
+ unsigned int offset,
+ unsigned int size,
+ void *data) {
+ VertexBufferGL *vertex_buffer = vertex_buffers_.Get(id);
+ if (!vertex_buffer) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ return vertex_buffer->GetData(offset, size, data) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+BufferSyncInterface::ParseError GAPIGL::CreateIndexBuffer(ResourceID id,
+ unsigned int size,
+ unsigned int flags) {
+ IndexBufferGL *index_buffer = new IndexBufferGL(size, flags);
+ index_buffer->Create();
+ index_buffers_.Assign(id, index_buffer);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::DestroyIndexBuffer(ResourceID id) {
+ return vertex_buffers_.Destroy(id) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+BufferSyncInterface::ParseError GAPIGL::SetIndexBufferData(ResourceID id,
+ unsigned int offset,
+ unsigned int size,
+ const void *data) {
+ IndexBufferGL *index_buffer = index_buffers_.Get(id);
+ if (!index_buffer) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ return index_buffer->SetData(offset, size, data) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+BufferSyncInterface::ParseError GAPIGL::GetIndexBufferData(ResourceID id,
+ unsigned int offset,
+ unsigned int size,
+ void *data) {
+ IndexBufferGL *index_buffer = index_buffers_.Get(id);
+ if (!index_buffer) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ return index_buffer->GetData(offset, size, data) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+BufferSyncInterface::ParseError GAPIGL::CreateVertexStruct(
+ ResourceID id,
+ unsigned int input_count) {
+ if (id == current_vertex_struct_) validate_streams_ = true;
+ VertexStructGL *vertex_struct = new VertexStructGL(input_count);
+ vertex_structs_.Assign(id, vertex_struct);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::DestroyVertexStruct(ResourceID id) {
+ if (id == current_vertex_struct_) validate_streams_ = true;
+ return vertex_structs_.Destroy(id) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+BufferSyncInterface::ParseError GAPIGL::SetVertexInput(
+ ResourceID vertex_struct_id,
+ unsigned int input_index,
+ ResourceID vertex_buffer_id,
+ unsigned int offset,
+ unsigned int stride,
+ vertex_struct::Type type,
+ vertex_struct::Semantic semantic,
+ unsigned int semantic_index) {
+ switch (semantic) {
+ case vertex_struct::POSITION:
+ if (semantic_index != 0) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ break;
+ case vertex_struct::NORMAL:
+ if (semantic_index != 0) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ break;
+ case vertex_struct::COLOR:
+ if (semantic_index >= 2) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ break;
+ case vertex_struct::TEX_COORD:
+ if (semantic_index >= 8) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ break;
+ default:
+ DLOG(FATAL) << "Not reached.";
+ break;
+ }
+ if (vertex_buffer_id == current_vertex_struct_) validate_streams_ = true;
+ VertexStructGL *vertex_struct = vertex_structs_.Get(vertex_struct_id);
+ if (!vertex_struct || input_index >= vertex_struct->count())
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ vertex_struct->SetInput(input_index, vertex_buffer_id, offset, stride, type,
+ semantic, semantic_index);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::SetVertexStruct(ResourceID id) {
+ current_vertex_struct_ = id;
+ validate_streams_ = true;
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+bool GAPIGL::ValidateStreams() {
+ DCHECK(validate_streams_);
+ VertexStructGL *vertex_struct = vertex_structs_.Get(current_vertex_struct_);
+ if (!vertex_struct) {
+ LOG(ERROR) << "Drawing with invalid streams.";
+ return false;
+ }
+ max_vertices_ = vertex_struct->SetStreams(this);
+ validate_streams_ = false;
+ return max_vertices_ > 0;
+}
+
+namespace {
+
+void PrimitiveTypeToGL(GAPIInterface::PrimitiveType primitive_type,
+ GLenum *gl_mode,
+ unsigned int *count) {
+ switch (primitive_type) {
+ case GAPIInterface::POINTS:
+ *gl_mode = GL_POINTS;
+ break;
+ case GAPIInterface::LINES:
+ *gl_mode = GL_LINES;
+ *count *= 2;
+ break;
+ case GAPIInterface::LINE_STRIPS:
+ *gl_mode = GL_LINE_STRIP;
+ ++*count;
+ break;
+ case GAPIInterface::TRIANGLES:
+ *gl_mode = GL_TRIANGLES;
+ *count *= 3;
+ break;
+ case GAPIInterface::TRIANGLE_STRIPS:
+ *gl_mode = GL_TRIANGLE_STRIP;
+ *count += 2;
+ break;
+ case GAPIInterface::TRIANGLE_FANS:
+ *gl_mode = GL_TRIANGLE_FAN;
+ *count += 2;
+ break;
+ default:
+ LOG(FATAL) << "Invalid primitive type";
+ break;
+ }
+}
+
+} // anonymous namespace
+
+BufferSyncInterface::ParseError GAPIGL::Draw(PrimitiveType primitive_type,
+ unsigned int first,
+ unsigned int count) {
+ if (validate_effect_ && !ValidateEffect()) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ DCHECK(current_effect_);
+ if (validate_streams_ && !ValidateStreams()) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ GLenum gl_mode = GL_POINTS;
+ PrimitiveTypeToGL(primitive_type, &gl_mode, &count);
+ if (first + count > max_vertices_) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ glDrawArrays(gl_mode, first, count);
+ CHECK_GL_ERROR();
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::DrawIndexed(
+ PrimitiveType primitive_type,
+ ResourceID index_buffer_id,
+ unsigned int first,
+ unsigned int count,
+ unsigned int min_index,
+ unsigned int max_index) {
+ IndexBufferGL *index_buffer = index_buffers_.Get(index_buffer_id);
+ if (!index_buffer) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ if (validate_effect_ && !ValidateEffect()) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ DCHECK(current_effect_);
+ if (validate_streams_ && !ValidateStreams()) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ if ((min_index >= max_vertices_) || (max_index > max_vertices_)) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ GLenum gl_mode = GL_POINTS;
+ PrimitiveTypeToGL(primitive_type, &gl_mode, &count);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer->gl_buffer());
+ GLenum index_type = (index_buffer->flags() & index_buffer::INDEX_32BIT) ?
+ GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
+ GLuint index_size = (index_buffer->flags() & index_buffer::INDEX_32BIT) ?
+ sizeof(GLuint) : sizeof(GLushort); // NOLINT
+ GLuint offset = first * index_size;
+ if (offset + count * index_size > index_buffer->size()) {
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ }
+ glDrawRangeElements(gl_mode, min_index, max_index, count, index_type,
+ OffsetToPtr(offset));
+ CHECK_GL_ERROR();
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+} // namespace command_buffer
+} // namespace o3d
diff --git a/o3d/command_buffer/service/cross/gl/geometry_gl.h b/o3d/command_buffer/service/cross/gl/geometry_gl.h
new file mode 100644
index 0000000..580f14d
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/geometry_gl.h
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+
+// This file declares the VertexBufferGL, IndexBufferGL and VertexStructGL
+// classes.
+
+#ifndef O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_GEOMETRY_GL_H_
+#define O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_GEOMETRY_GL_H_
+
+#include "command_buffer/common/cross/gapi_interface.h"
+#include "command_buffer/service/cross/resource.h"
+#include "command_buffer/service/cross/gl/gl_utils.h"
+
+namespace o3d {
+namespace command_buffer {
+
+class GAPIGL;
+
+// GL version of VertexBuffer.
+class VertexBufferGL : public VertexBuffer {
+ public:
+ VertexBufferGL(unsigned int size, unsigned int flags)
+ : VertexBuffer(size, flags),
+ gl_buffer_(0) {}
+ virtual ~VertexBufferGL();
+
+ // Creates the GL vertex buffer.
+ void Create();
+
+ // Sets the data into the GL vertex buffer.
+ bool SetData(unsigned int offset, unsigned int size, const void *data);
+
+ // Gets the data from the GL vertex buffer.
+ bool GetData(unsigned int offset, unsigned int size, void *data);
+
+ // Gets the GL vertex buffer.
+ GLuint gl_buffer() const { return gl_buffer_; }
+
+ private:
+ GLuint gl_buffer_;
+ DISALLOW_COPY_AND_ASSIGN(VertexBufferGL);
+};
+
+// GL version of IndexBuffer.
+class IndexBufferGL : public IndexBuffer {
+ public:
+ IndexBufferGL(unsigned int size, unsigned int flags)
+ : IndexBuffer(size, flags),
+ gl_buffer_(0) {}
+ virtual ~IndexBufferGL();
+
+ // Creates the GL index buffer.
+ void Create();
+
+ // Sets the data into the GL index buffer.
+ bool SetData(unsigned int offset, unsigned int size, const void *data);
+
+ // Gets the data from the GL index buffer.
+ bool GetData(unsigned int offset, unsigned int size, void *data);
+
+ // Gets the GL index buffer.
+ GLuint gl_buffer() const { return gl_buffer_; }
+
+ private:
+ GLuint gl_buffer_;
+ DISALLOW_COPY_AND_ASSIGN(IndexBufferGL);
+};
+
+// GL version of VertexStruct.
+class VertexStructGL : public VertexStruct {
+ public:
+ explicit VertexStructGL(unsigned int count)
+ : VertexStruct(count),
+ dirty_(true) {}
+ virtual ~VertexStructGL() {}
+
+ // Adds an input to the vertex struct.
+ void SetInput(unsigned int input_index,
+ ResourceID vertex_buffer_id,
+ unsigned int offset,
+ unsigned int stride,
+ vertex_struct::Type type,
+ vertex_struct::Semantic semantic,
+ unsigned int semantic_index);
+
+ // Sets the input streams to GL.
+ unsigned int SetStreams(GAPIGL *gapi);
+
+ private:
+ static const unsigned int kMaxAttribs = 16;
+
+ // This struct describes the parameters that are passed to
+ // glVertexAttribPointer.
+ struct AttribDesc {
+ ResourceID vertex_buffer_id;
+ GLint size;
+ GLenum type;
+ GLboolean normalized;
+ GLsizei stride;
+ GLintptr offset;
+ };
+
+ // Compiles the vertex declaration into the attribute array.
+ void Compile();
+
+ bool dirty_;
+ AttribDesc attribs_[kMaxAttribs];
+ DISALLOW_COPY_AND_ASSIGN(VertexStructGL);
+};
+
+
+} // namespace command_buffer
+} // namespace o3d
+
+#endif // O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_GEOMETRY_GL_H_
diff --git a/o3d/command_buffer/service/cross/gl/gl_utils.h b/o3d/command_buffer/service/cross/gl/gl_utils.h
new file mode 100644
index 0000000..b41a4cf
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/gl_utils.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+
+// This file includes all the necessary GL/Cg headers and implement some useful
+// utilities.
+
+#ifndef O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_GL_UTILS_H_
+#define O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_GL_UTILS_H_
+
+#include <build/build_config.h>
+#define GL_GLEXT_PROTOTYPES
+#if defined(OS_WIN)
+#include <GL/gl.h>
+#elif defined(OS_MACOSX)
+#include <OpenGL/OpenGL.h>
+#include <AGL/agl.h>
+#elif defined(OS_LINUX)
+#include <GL/gl.h>
+#endif // defined(PLATFORM)
+#include <Cg/cg.h>
+#include <Cg/cgGL.h>
+
+// Define this for extra GL error debugging (slower).
+// #define GL_ERROR_DEBUGGING
+#ifdef GL_ERROR_DEBUGGING
+#define CHECK_GL_ERROR() do { \
+ GLenum gl_error = glGetError(); \
+ LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error :" << gl_error; \
+ } while (0)
+#else // GL_ERROR_DEBUGGING
+#define CHECK_GL_ERROR() void(0)
+#endif // GL_ERROR_DEBUGGING
+
+#endif // O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_GL_UTILS_H_
diff --git a/o3d/command_buffer/service/cross/gl/sampler_gl.cc b/o3d/command_buffer/service/cross/gl/sampler_gl.cc
new file mode 100644
index 0000000..2262e6c
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/sampler_gl.cc
@@ -0,0 +1,235 @@
+/*
+ * 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.
+ */
+
+
+// This file implements the sampler-related GAPI functions on GL.
+
+#include "command_buffer/service/cross/gl/gapi_gl.h"
+#include "command_buffer/service/cross/gl/sampler_gl.h"
+
+namespace o3d {
+namespace command_buffer {
+
+namespace {
+
+// Gets the GL enum corresponding to an addressing mode.
+GLenum GLAddressMode(sampler::AddressingMode o3d_mode) {
+ switch (o3d_mode) {
+ case sampler::WRAP:
+ return GL_REPEAT;
+ case sampler::MIRROR_REPEAT:
+ return GL_MIRRORED_REPEAT;
+ case sampler::CLAMP_TO_EDGE:
+ return GL_CLAMP_TO_EDGE;
+ case sampler::CLAMP_TO_BORDER:
+ return GL_CLAMP_TO_BORDER;
+ default:
+ DLOG(FATAL) << "Not Reached";
+ return GL_REPEAT;
+ }
+}
+
+// Gets the GL enum for the minification filter based on the command buffer min
+// and mip filtering modes.
+GLenum GLMinFilter(sampler::FilteringMode min_filter,
+ sampler::FilteringMode mip_filter) {
+ switch (min_filter) {
+ case sampler::POINT:
+ if (mip_filter == sampler::NONE)
+ return GL_NEAREST;
+ else if (mip_filter == sampler::POINT)
+ return GL_NEAREST_MIPMAP_NEAREST;
+ else if (mip_filter == sampler::LINEAR)
+ return GL_NEAREST_MIPMAP_LINEAR;
+ case sampler::LINEAR:
+ if (mip_filter == sampler::NONE)
+ return GL_LINEAR;
+ else if (mip_filter == sampler::POINT)
+ return GL_LINEAR_MIPMAP_NEAREST;
+ else if (mip_filter == sampler::LINEAR)
+ return GL_LINEAR_MIPMAP_LINEAR;
+ default:
+ DLOG(FATAL) << "Not Reached";
+ return GL_LINEAR_MIPMAP_NEAREST;
+ }
+}
+
+// Gets the GL enum for the magnification filter based on the command buffer mag
+// filtering mode.
+GLenum GLMagFilter(sampler::FilteringMode mag_filter) {
+ switch (mag_filter) {
+ case sampler::POINT:
+ return GL_NEAREST;
+ case sampler::LINEAR:
+ return GL_LINEAR;
+ default:
+ DLOG(FATAL) << "Not Reached";
+ return GL_LINEAR;
+ }
+}
+
+// Gets the GL enum representing the GL target based on the texture type.
+GLenum GLTextureTarget(texture::Type type) {
+ switch (type) {
+ case texture::TEXTURE_2D:
+ return GL_TEXTURE_2D;
+ case texture::TEXTURE_3D:
+ return GL_TEXTURE_3D;
+ case texture::TEXTURE_CUBE:
+ return GL_TEXTURE_CUBE_MAP;
+ }
+}
+
+} // anonymous namespace
+
+SamplerGL::SamplerGL()
+ : texture_id_(kInvalidResource),
+ gl_texture_(0) {
+ SetStates(sampler::CLAMP_TO_EDGE,
+ sampler::CLAMP_TO_EDGE,
+ sampler::CLAMP_TO_EDGE,
+ sampler::LINEAR,
+ sampler::LINEAR,
+ sampler::POINT,
+ 1);
+ RGBA black = {0, 0, 0, 1};
+ SetBorderColor(black);
+}
+
+bool SamplerGL::ApplyStates(GAPIGL *gapi) {
+ DCHECK(gapi);
+ TextureGL *texture = gapi->GetTexture(texture_id_);
+ if (!texture) {
+ gl_texture_ = 0;
+ return false;
+ }
+ GLenum target = GLTextureTarget(texture->type());
+ gl_texture_ = texture->gl_texture();
+ glBindTexture(target, gl_texture_);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, gl_wrap_s_);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, gl_wrap_t_);
+ glTexParameteri(target, GL_TEXTURE_WRAP_R, gl_wrap_r_);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, gl_min_filter_);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, gl_mag_filter_);
+ glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_max_anisotropy_);
+ glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, gl_border_color_);
+ return true;
+}
+
+void SamplerGL::SetStates(sampler::AddressingMode addressing_u,
+ sampler::AddressingMode addressing_v,
+ sampler::AddressingMode addressing_w,
+ sampler::FilteringMode mag_filter,
+ sampler::FilteringMode min_filter,
+ sampler::FilteringMode mip_filter,
+ unsigned int max_anisotropy) {
+ // These are validated in GAPIDecoder.cc
+ DCHECK_NE(mag_filter, sampler::NONE);
+ DCHECK_NE(min_filter, sampler::NONE);
+ DCHECK_GT(max_anisotropy, 0);
+ gl_wrap_s_ = GLAddressMode(addressing_u);
+ gl_wrap_t_ = GLAddressMode(addressing_v);
+ gl_wrap_r_ = GLAddressMode(addressing_w);
+ gl_mag_filter_ = GLMagFilter(mag_filter);
+ gl_min_filter_ = GLMinFilter(min_filter, mip_filter);
+ gl_max_anisotropy_ = max_anisotropy;
+}
+
+void SamplerGL::SetBorderColor(const RGBA &color) {
+ gl_border_color_[0] = color.red;
+ gl_border_color_[1] = color.green;
+ gl_border_color_[2] = color.blue;
+ gl_border_color_[3] = color.alpha;
+}
+
+BufferSyncInterface::ParseError GAPIGL::CreateSampler(
+ ResourceID id) {
+ // Dirty effect, because this sampler id may be used.
+ DirtyEffect();
+ samplers_.Assign(id, new SamplerGL());
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+// Destroys the Sampler resource.
+BufferSyncInterface::ParseError GAPIGL::DestroySampler(ResourceID id) {
+ // Dirty effect, because this sampler id may be used.
+ DirtyEffect();
+ return samplers_.Destroy(id) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+BufferSyncInterface::ParseError GAPIGL::SetSamplerStates(
+ ResourceID id,
+ sampler::AddressingMode addressing_u,
+ sampler::AddressingMode addressing_v,
+ sampler::AddressingMode addressing_w,
+ sampler::FilteringMode mag_filter,
+ sampler::FilteringMode min_filter,
+ sampler::FilteringMode mip_filter,
+ unsigned int max_anisotropy) {
+ SamplerGL *sampler = samplers_.Get(id);
+ if (!sampler)
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ // Dirty effect, because this sampler id may be used.
+ DirtyEffect();
+ sampler->SetStates(addressing_u, addressing_v, addressing_w,
+ mag_filter, min_filter, mip_filter, max_anisotropy);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::SetSamplerBorderColor(
+ ResourceID id,
+ const RGBA &color) {
+ SamplerGL *sampler = samplers_.Get(id);
+ if (!sampler)
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ // Dirty effect, because this sampler id may be used.
+ DirtyEffect();
+ sampler->SetBorderColor(color);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+BufferSyncInterface::ParseError GAPIGL::SetSamplerTexture(
+ ResourceID id,
+ ResourceID texture_id) {
+ SamplerGL *sampler = samplers_.Get(id);
+ if (!sampler)
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ // Dirty effect, because this sampler id may be used.
+ DirtyEffect();
+ sampler->SetTexture(texture_id);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+
+} // namespace command_buffer
+} // namespace o3d
diff --git a/o3d/command_buffer/service/cross/gl/sampler_gl.h b/o3d/command_buffer/service/cross/gl/sampler_gl.h
new file mode 100644
index 0000000..dc84b4f
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/sampler_gl.h
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+
+// This file declares the SamplerGL class.
+
+#ifndef O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_SAMPLER_GL_H_
+#define O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_SAMPLER_GL_H_
+
+#include "command_buffer/common/cross/gapi_interface.h"
+#include "command_buffer/service/cross/gl/gl_utils.h"
+#include "command_buffer/service/cross/resource.h"
+
+namespace o3d {
+namespace command_buffer {
+
+class GAPIGL;
+
+// GL version of Sampler.
+class SamplerGL : public Sampler {
+ public:
+ SamplerGL();
+
+ // Applies sampler states to GL.
+ bool ApplyStates(GAPIGL *gapi);
+
+ // Sets sampler states.
+ void SetStates(sampler::AddressingMode addressing_u,
+ sampler::AddressingMode addressing_v,
+ sampler::AddressingMode addressing_w,
+ sampler::FilteringMode mag_filter,
+ sampler::FilteringMode min_filter,
+ sampler::FilteringMode mip_filter,
+ unsigned int max_anisotropy);
+
+ // Sets the border color states.
+ void SetBorderColor(const RGBA &color);
+
+ // Sets the texture.
+ void SetTexture(ResourceID texture) { texture_id_ = texture; }
+
+ GLuint gl_texture() const { return gl_texture_; }
+
+ private:
+ GLenum gl_wrap_s_;
+ GLenum gl_wrap_t_;
+ GLenum gl_wrap_r_;
+ GLenum gl_mag_filter_;
+ GLenum gl_min_filter_;
+ GLuint gl_max_anisotropy_;
+ GLfloat gl_border_color_[4];
+ GLuint gl_texture_;
+ ResourceID texture_id_;
+};
+
+} // namespace command_buffer
+} // namespace o3d
+
+#endif // O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_SAMPLER_GL_H_
diff --git a/o3d/command_buffer/service/cross/gl/states_gl.cc b/o3d/command_buffer/service/cross/gl/states_gl.cc
new file mode 100644
index 0000000..4acc96c
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/states_gl.cc
@@ -0,0 +1,342 @@
+/*
+ * 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.
+ */
+
+
+// This file implements the render state-related GAPI functions on GL.
+
+#include "command_buffer/common/cross/cmd_buffer_format.h"
+#include "command_buffer/service/cross/gl/gapi_gl.h"
+
+namespace o3d {
+namespace command_buffer {
+
+namespace {
+
+GLenum kGLPolygonModes[] = {
+ GL_POINT,
+ GL_LINE,
+ GL_FILL,
+};
+COMPILE_ASSERT(GAPIInterface::NUM_POLYGON_MODE == arraysize(kGLPolygonModes),
+ kGLPolygonModes_does_not_match_GAPIInterface_PolygonMode);
+
+GLenum kGLComparison[] = {
+ GL_NEVER,
+ GL_LESS,
+ GL_EQUAL,
+ GL_LEQUAL,
+ GL_GREATER,
+ GL_NOTEQUAL,
+ GL_GEQUAL,
+ GL_ALWAYS,
+};
+COMPILE_ASSERT(GAPIInterface::NUM_COMPARISON == arraysize(kGLComparison),
+ kGLComparison_does_not_match_GAPIInterface_Comparison);
+
+GLenum kGLBlendFunc[] = {
+ GL_ZERO,
+ GL_ONE,
+ GL_SRC_COLOR,
+ GL_ONE_MINUS_SRC_COLOR,
+ GL_SRC_ALPHA,
+ GL_ONE_MINUS_SRC_ALPHA,
+ GL_DST_ALPHA,
+ GL_ONE_MINUS_DST_ALPHA,
+ GL_DST_COLOR,
+ GL_ONE_MINUS_DST_COLOR,
+ GL_SRC_ALPHA_SATURATE,
+ GL_CONSTANT_COLOR,
+ GL_ONE_MINUS_CONSTANT_COLOR,
+};
+COMPILE_ASSERT(GAPIInterface::NUM_BLEND_FUNC == arraysize(kGLBlendFunc),
+ kGLBlendFunc_does_not_match_GAPIInterface_BlendFunc);
+
+GLenum kGLBlendEq[] = {
+ GL_FUNC_ADD,
+ GL_FUNC_SUBTRACT,
+ GL_FUNC_REVERSE_SUBTRACT,
+ GL_MIN,
+ GL_MAX,
+};
+COMPILE_ASSERT(GAPIInterface::NUM_BLEND_EQ == arraysize(kGLBlendEq),
+ kGLBlendEq_does_not_match_GAPIInterface_BlendEq);
+
+GLenum kGLStencilOp[] = {
+ GL_KEEP,
+ GL_ZERO,
+ GL_REPLACE,
+ GL_INCR,
+ GL_DECR,
+ GL_INVERT,
+ GL_INCR_WRAP,
+ GL_DECR_WRAP,
+};
+COMPILE_ASSERT(GAPIInterface::NUM_STENCIL_OP == arraysize(kGLStencilOp),
+ kGLStencilOp_does_not_match_GAPIInterface_StencilOp);
+
+// Check that the definition of the counter-clockwise func/ops match the
+// clockwise ones, just shifted by 16 bits, so that we can use
+// DecodeStencilFuncOps on both of them.
+#define CHECK_CCW_MATCHES_CW(FIELD) \
+ COMPILE_ASSERT(set_stencil_test::CW ## FIELD::kLength == \
+ set_stencil_test::CCW ## FIELD::kLength, \
+ CCW ## FIELD ## _length_does_not_match_ ## CW ## FIELD); \
+ COMPILE_ASSERT(set_stencil_test::CW ## FIELD::kShift + 16 == \
+ set_stencil_test::CCW ## FIELD::kShift, \
+ CCW ## FIELD ## _shift_does_not_match_ ## CW ## FIELD)
+
+CHECK_CCW_MATCHES_CW(Func);
+CHECK_CCW_MATCHES_CW(PassOp);
+CHECK_CCW_MATCHES_CW(FailOp);
+CHECK_CCW_MATCHES_CW(ZFailOp);
+
+#undef CHECK_CCW_MATCHES_CW
+
+// Decodes stencil test function and operations from the bitfield.
+void DecodeStencilFuncOps(Uint32 params,
+ GLenum *func,
+ GLenum *pass,
+ GLenum *fail,
+ GLenum *zfail) {
+ namespace cmd = set_stencil_test;
+ // Sanity check. The value has already been tested in
+ // GAPIDecoder::DecodeSetStencilTest in gapi_decoder.cc.
+ DCHECK_EQ(cmd::Unused1::Get(params), 0);
+ // Check that the bitmask get cannot generate values outside of the allowed
+ // range.
+ COMPILE_ASSERT(cmd::CWFunc::kMask < GAPIInterface::NUM_COMPARISON,
+ set_stencil_test_CWFunc_may_produce_invalid_values);
+ *func = kGLComparison[cmd::CWFunc::Get(params)];
+
+ COMPILE_ASSERT(cmd::CWPassOp::kMask < GAPIInterface::NUM_STENCIL_OP,
+ set_stencil_test_CWPassOp_may_produce_invalid_values);
+ *pass = kGLStencilOp[cmd::CWPassOp::Get(params)];
+
+ COMPILE_ASSERT(cmd::CWFailOp::kMask < GAPIInterface::NUM_STENCIL_OP,
+ set_stencil_test_CWFailOp_may_produce_invalid_values);
+ *fail = kGLStencilOp[cmd::CWFailOp::Get(params)];
+
+ COMPILE_ASSERT(cmd::CWZFailOp::kMask < GAPIInterface::NUM_STENCIL_OP,
+ set_stencil_test_CWZFailOp_may_produce_invalid_values);
+ *zfail = kGLStencilOp[cmd::CWZFailOp::Get(params)];
+}
+
+} // anonymous namespace
+
+void GAPIGL::SetViewport(unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height,
+ float z_min,
+ float z_max) {
+ glViewport(x, y, width, height);
+ glDepthRange(z_min, z_max);
+ // Update the helper constant used for the D3D -> GL remapping.
+ // See effect_gl.cc for details.
+ glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 0,
+ 1.f / width, 1.f / height, 2.f, 0.f);
+ CHECK_GL_ERROR();
+}
+
+void GAPIGL::SetScissor(bool enable,
+ unsigned int x,
+ unsigned int y,
+ unsigned int width,
+ unsigned int height) {
+ if (enable) {
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(x, y, width, height);
+ } else {
+ glDisable(GL_SCISSOR_TEST);
+ }
+}
+
+void GAPIGL::SetPointLineRaster(bool line_smooth,
+ bool point_sprite,
+ float point_size) {
+ if (line_smooth) {
+ glEnable(GL_LINE_SMOOTH);
+ } else {
+ glDisable(GL_LINE_SMOOTH);
+ }
+ if (point_sprite) {
+ glEnable(GL_POINT_SPRITE);
+ // TODO: check which TC gets affected by point sprites in D3D.
+ glActiveTextureARB(GL_TEXTURE0);
+ glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
+ } else {
+ glActiveTextureARB(GL_TEXTURE0);
+ glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_FALSE);
+ glDisable(GL_POINT_SPRITE);
+ }
+ glPointSize(point_size);
+}
+
+void GAPIGL::SetPolygonOffset(float slope_factor, float units) {
+ glPolygonOffset(slope_factor, units);
+}
+
+void GAPIGL::SetPolygonRaster(PolygonMode fill_mode,
+ FaceCullMode cull_mode) {
+ DCHECK_LT(fill_mode, NUM_POLYGON_MODE);
+ glPolygonMode(GL_FRONT_AND_BACK, kGLPolygonModes[fill_mode]);
+ DCHECK_LT(cull_mode, NUM_FACE_CULL_MODE);
+ switch (cull_mode) {
+ case CULL_CW:
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ break;
+ case CULL_CCW:
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+ break;
+ default:
+ glDisable(GL_CULL_FACE);
+ break;
+ }
+}
+
+void GAPIGL::SetAlphaTest(bool enable,
+ float reference,
+ Comparison comp) {
+ DCHECK_LT(comp, NUM_COMPARISON);
+ if (enable) {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(kGLComparison[comp], reference);
+ } else {
+ glDisable(GL_ALPHA_TEST);
+ }
+}
+
+void GAPIGL::SetDepthTest(bool enable,
+ bool write_enable,
+ Comparison comp) {
+ DCHECK_LT(comp, NUM_COMPARISON);
+ if (enable) {
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(kGLComparison[comp]);
+ } else {
+ glDisable(GL_DEPTH_TEST);
+ }
+ glDepthMask(write_enable);
+}
+
+void GAPIGL::SetStencilTest(bool enable,
+ bool separate_ccw,
+ unsigned int write_mask,
+ unsigned int compare_mask,
+ unsigned int ref,
+ Uint32 func_ops) {
+ if (enable) {
+ glEnable(GL_STENCIL_TEST);
+ glStencilMask(write_mask);
+
+ GLenum func;
+ GLenum pass;
+ GLenum fail;
+ GLenum zfail;
+ DecodeStencilFuncOps(func_ops, &func, &pass, &fail, &zfail);
+ if (separate_ccw) {
+ glStencilFuncSeparate(GL_FRONT, func, ref, compare_mask);
+ glStencilOpSeparate(GL_FRONT, pass, fail, zfail);
+ // Extract upper 16 bits.
+ Uint32 ccw_func_ops = BitField<16, 16>::Get(func_ops);
+ GLenum ccw_func;
+ GLenum ccw_pass;
+ GLenum ccw_fail;
+ GLenum ccw_zfail;
+ DecodeStencilFuncOps(ccw_func_ops, &ccw_func, &ccw_pass, &ccw_fail,
+ &ccw_zfail);
+ glStencilFuncSeparate(GL_BACK, ccw_func, ref, compare_mask);
+ glStencilOpSeparate(GL_BACK, ccw_pass, ccw_fail, ccw_zfail);
+ } else {
+ glStencilFunc(func, ref, compare_mask);
+ glStencilOp(pass, fail, zfail);
+ }
+ } else {
+ glDisable(GL_STENCIL_TEST);
+ }
+}
+
+void GAPIGL::SetColorWrite(bool red,
+ bool green,
+ bool blue,
+ bool alpha,
+ bool dither) {
+ glColorMask(red, green, blue, alpha);
+ if (dither) {
+ glEnable(GL_DITHER);
+ } else {
+ glDisable(GL_DITHER);
+ }
+}
+
+void GAPIGL::SetBlending(bool enable,
+ bool separate_alpha,
+ BlendEq color_eq,
+ BlendFunc color_src_func,
+ BlendFunc color_dst_func,
+ BlendEq alpha_eq,
+ BlendFunc alpha_src_func,
+ BlendFunc alpha_dst_func) {
+ DCHECK_LT(color_eq, NUM_BLEND_EQ);
+ DCHECK_LT(color_src_func, NUM_BLEND_FUNC);
+ DCHECK_LT(color_dst_func, NUM_BLEND_FUNC);
+ DCHECK_LT(alpha_eq, NUM_BLEND_EQ);
+ DCHECK_LT(alpha_src_func, NUM_BLEND_FUNC);
+ DCHECK_LT(alpha_dst_func, NUM_BLEND_FUNC);
+ if (enable) {
+ glEnable(GL_BLEND);
+ GLenum gl_color_eq = kGLBlendEq[color_eq];
+ GLenum gl_color_src_func = kGLBlendFunc[color_src_func];
+ GLenum gl_color_dst_func = kGLBlendFunc[color_dst_func];
+ if (separate_alpha) {
+ GLenum gl_alpha_eq = kGLBlendEq[alpha_eq];
+ GLenum gl_alpha_src_func = kGLBlendFunc[alpha_src_func];
+ GLenum gl_alpha_dst_func = kGLBlendFunc[alpha_dst_func];
+ glBlendFuncSeparate(gl_color_src_func, gl_color_dst_func,
+ gl_alpha_src_func, gl_alpha_dst_func);
+ glBlendEquationSeparate(gl_color_eq, gl_alpha_eq);
+ } else {
+ glBlendFunc(gl_color_src_func, gl_color_dst_func);
+ glBlendEquation(gl_color_eq);
+ }
+ } else {
+ glDisable(GL_BLEND);
+ }
+}
+
+void GAPIGL::SetBlendingColor(const RGBA &color) {
+ glBlendColor(color.red, color.green, color.blue, color.alpha);
+}
+
+} // namespace command_buffer
+} // namespace o3d
diff --git a/o3d/command_buffer/service/cross/gl/texture_gl.cc b/o3d/command_buffer/service/cross/gl/texture_gl.cc
new file mode 100644
index 0000000..9155dcc
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/texture_gl.cc
@@ -0,0 +1,678 @@
+/*
+ * 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.
+ */
+
+
+// This file implements the texture-related GAPI functions on GL.
+
+#include "command_buffer/service/cross/gl/gapi_gl.h"
+#include "command_buffer/service/cross/gl/texture_gl.h"
+
+namespace o3d {
+namespace command_buffer {
+
+namespace {
+
+// Gets the GL internal format, format and type corresponding to a command
+// buffer texture format.
+bool GetGLFormatType(texture::Format format,
+ GLenum *internal_format,
+ GLenum *gl_format,
+ GLenum *gl_type) {
+ switch (format) {
+ case texture::XRGB8:
+ *internal_format = GL_RGB;
+ *gl_format = GL_BGRA;
+ *gl_type = GL_UNSIGNED_BYTE;
+ return true;
+ case texture::ARGB8:
+ *internal_format = GL_RGBA;
+ *gl_format = GL_BGRA;
+ *gl_type = GL_UNSIGNED_BYTE;
+ return true;
+ case texture::ABGR16F:
+ *internal_format = GL_RGBA16F_ARB;
+ *gl_format = GL_RGBA;
+ *gl_type = GL_HALF_FLOAT_ARB;
+ return true;
+ case texture::DXT1:
+ *internal_format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ *gl_format = 0;
+ *gl_type = 0;
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Helper class used to prepare image data to match the layout that
+// glTexImage* and glCompressedTexImage* expect.
+class SetImageHelper {
+ public:
+ SetImageHelper()
+ : buffer_(NULL),
+ image_data_(NULL),
+ image_size_(0) {
+ }
+
+ // Initializes the helper with the input data, re-using the input buffer if
+ // possible, or copying it into a temporary one.
+ bool Initialize(const MipLevelInfo &mip_info,
+ const Volume& volume,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int src_size,
+ const void *data) {
+ TransferInfo src_transfer_info;
+ MakeTransferInfo(&src_transfer_info, mip_info, volume, row_pitch,
+ slice_pitch);
+ if (!CheckVolume(mip_info, volume) ||
+ src_size < src_transfer_info.total_size)
+ return false;
+ if (!src_transfer_info.packed) {
+ TransferInfo dst_transfer_info;
+ MakePackedTransferInfo(&dst_transfer_info, mip_info, volume);
+ buffer_.reset(new unsigned char[dst_transfer_info.total_size]);
+ TransferVolume(volume, mip_info, dst_transfer_info, buffer_.get(),
+ src_transfer_info, data);
+ image_data_ = buffer_.get();
+ image_size_ = dst_transfer_info.total_size;
+ } else {
+ image_data_ = data;
+ image_size_ = src_transfer_info.total_size;
+ }
+ return true;
+ }
+
+ // Gets the buffer that contains the data in the GL format.
+ const void *image_data() { return image_data_; }
+ // Gets the size of the buffer as GL expects it.
+ unsigned int image_size() { return image_size_; }
+
+ private:
+ scoped_array<unsigned char> buffer_;
+ const void *image_data_;
+ unsigned int image_size_;
+ DISALLOW_COPY_AND_ASSIGN(SetImageHelper);
+};
+
+// Helper class used to retrieve image data to match the layout that
+// glGetTexImage and glGetCompressedTexImage expect.
+class GetImageHelper {
+ public:
+ GetImageHelper()
+ : dst_data_(NULL),
+ buffer_(NULL),
+ image_data_(NULL) {
+ memset(&mip_info_, 0, sizeof(mip_info_));
+ memset(&volume_, 0, sizeof(volume_));
+ memset(&dst_transfer_info_, 0, sizeof(dst_transfer_info_));
+ memset(&src_transfer_info_, 0, sizeof(src_transfer_info_));
+ }
+
+ // Initialize the helper to make available a buffer to get the data from GL.
+ // It will re-use the passed in buffer if the layout matches GL, or allocate
+ // a temporary one.
+ bool Initialize(const MipLevelInfo &mip_info,
+ const Volume& volume,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int dst_size,
+ void *dst_data) {
+ mip_info_ = mip_info;
+ volume_ = volume;
+ dst_data_ = dst_data;
+ MakeTransferInfo(&dst_transfer_info_, mip_info, volume, row_pitch,
+ slice_pitch);
+ if (!CheckVolume(mip_info, volume) ||
+ dst_size < dst_transfer_info_.total_size)
+ return false;
+
+ if (!IsFullVolume(mip_info, volume) || !dst_transfer_info_.packed) {
+ // We can only retrieve the full image from GL.
+ Volume full_volume = {
+ 0, 0, 0,
+ mip_info.width, mip_info.height, mip_info.depth
+ };
+ MakePackedTransferInfo(&src_transfer_info_, mip_info, full_volume);
+ buffer_.reset(new unsigned char[src_transfer_info_.total_size]);
+ image_data_ = buffer_.get();
+ } else {
+ image_data_ = dst_data;
+ }
+ return true;
+ }
+
+ // Finalize the helper, copying the data into the final buffer if needed.
+ void Finalize() {
+ if (!buffer_.get()) return;
+ unsigned int offset =
+ volume_.x / mip_info_.block_size_x * mip_info_.block_bpp +
+ volume_.y / mip_info_.block_size_y * src_transfer_info_.row_pitch +
+ volume_.z * src_transfer_info_.slice_pitch;
+ src_transfer_info_.row_size = dst_transfer_info_.row_size;
+ TransferVolume(volume_, mip_info_, dst_transfer_info_, dst_data_,
+ src_transfer_info_, buffer_.get() + offset);
+ }
+
+ // Gets the buffer that can receive the data from GL.
+ void *image_data() { return image_data_; }
+
+ private:
+ MipLevelInfo mip_info_;
+ Volume volume_;
+ TransferInfo dst_transfer_info_;
+ TransferInfo src_transfer_info_;
+ void *dst_data_;
+ scoped_array<unsigned char> buffer_;
+ void *image_data_;
+ DISALLOW_COPY_AND_ASSIGN(GetImageHelper);
+};
+
+} // anonymous namespace
+
+TextureGL::~TextureGL() {
+ glDeleteTextures(1, &gl_texture_);
+ CHECK_GL_ERROR();
+}
+
+Texture2DGL *Texture2DGL::Create(unsigned int width,
+ unsigned int height,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags) {
+ DCHECK_GT(width, 0);
+ DCHECK_GT(height, 0);
+ DCHECK_GT(levels, 0);
+ GLenum gl_internal_format = 0;
+ GLenum gl_format = 0;
+ GLenum gl_type = 0;
+ bool r = GetGLFormatType(format, &gl_internal_format, &gl_format, &gl_type);
+ DCHECK(r); // Was checked in the decoder.
+ GLuint gl_texture = 0;
+ glGenTextures(1, &gl_texture);
+ glBindTexture(GL_TEXTURE_2D, gl_texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels - 1);
+ // glCompressedTexImage2D does't accept NULL as a parameter, so we need
+ // to pass in some data.
+ scoped_array<unsigned char> buffer;
+ if (!gl_format) {
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format, width, height, 1, 0);
+ unsigned int size = GetMipLevelSize(mip_info);
+ buffer.reset(new unsigned char[size]);
+ }
+ unsigned int mip_width = width;
+ unsigned int mip_height = height;
+ for (unsigned int i = 0; i < levels; ++i) {
+ if (gl_format) {
+ glTexImage2D(GL_TEXTURE_2D, i, gl_internal_format, mip_width, mip_height,
+ 0, gl_format, gl_type, NULL);
+ } else {
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format, width, height, 1, i);
+ unsigned int size = GetMipLevelSize(mip_info);
+ glCompressedTexImage2D(GL_TEXTURE_2D, i, gl_internal_format, mip_width,
+ mip_height, 0, size, buffer.get());
+ }
+ mip_width = std::max(1U, mip_width >> 1);
+ mip_height = std::max(1U, mip_height >> 1);
+ }
+ return new Texture2DGL(levels, format, flags, width, height, gl_texture);
+}
+
+// Sets data into a 2D texture resource.
+bool Texture2DGL::SetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ const void *data) {
+ if (level >= levels())
+ return false;
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format(), width_, height_, 1, level);
+ SetImageHelper helper;
+ if (!helper.Initialize(mip_info, volume, row_pitch, slice_pitch, size, data))
+ return false;
+
+ GLenum gl_internal_format = 0;
+ GLenum gl_format = 0;
+ GLenum gl_type = 0;
+ bool r = GetGLFormatType(format(), &gl_internal_format, &gl_format, &gl_type);
+ DCHECK(r);
+ glBindTexture(GL_TEXTURE_2D, gl_texture_);
+ if (gl_format) {
+ glTexSubImage2D(GL_TEXTURE_2D, level, volume.x, volume.y, volume.width,
+ volume.height, gl_format, gl_type, helper.image_data());
+ } else {
+ glCompressedTexSubImage2D(GL_TEXTURE_2D, level, volume.x, volume.y,
+ volume.width, volume.height, gl_internal_format,
+ helper.image_size(), helper.image_data());
+ }
+ return true;
+}
+
+bool Texture2DGL::GetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ void *data) {
+ if (level >= levels())
+ return false;
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format(), width_, height_, 1, level);
+ GetImageHelper helper;
+ if (!helper.Initialize(mip_info, volume, row_pitch, slice_pitch, size, data))
+ return false;
+
+ GLenum gl_internal_format = 0;
+ GLenum gl_format = 0;
+ GLenum gl_type = 0;
+ bool r = GetGLFormatType(format(), &gl_internal_format, &gl_format, &gl_type);
+ DCHECK(r);
+ glBindTexture(GL_TEXTURE_2D, gl_texture_);
+ if (gl_format) {
+ glGetTexImage(GL_TEXTURE_2D, level, gl_format, gl_type,
+ helper.image_data());
+ } else {
+ glGetCompressedTexImage(GL_TEXTURE_2D, level, helper.image_data());
+ }
+
+ helper.Finalize();
+ return true;
+}
+
+Texture3DGL *Texture3DGL::Create(unsigned int width,
+ unsigned int height,
+ unsigned int depth,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags) {
+ DCHECK_GT(width, 0);
+ DCHECK_GT(height, 0);
+ DCHECK_GT(depth, 0);
+ DCHECK_GT(levels, 0);
+ GLenum gl_internal_format = 0;
+ GLenum gl_format = 0;
+ GLenum gl_type = 0;
+ bool r = GetGLFormatType(format, &gl_internal_format, &gl_format, &gl_type);
+ DCHECK(r); // Was checked in the decoder.
+ GLuint gl_texture = 0;
+ glGenTextures(1, &gl_texture);
+ glBindTexture(GL_TEXTURE_3D, gl_texture);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, levels - 1);
+ // glCompressedTexImage3D does't accept NULL as a parameter, so we need
+ // to pass in some data.
+ scoped_array<unsigned char> buffer;
+ if (!gl_format) {
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format, width, height, depth, 0);
+ unsigned int size = GetMipLevelSize(mip_info);
+ buffer.reset(new unsigned char[size]);
+ }
+ unsigned int mip_width = width;
+ unsigned int mip_height = height;
+ unsigned int mip_depth = depth;
+ for (unsigned int i = 0; i < levels; ++i) {
+ if (gl_format) {
+ glTexImage3D(GL_TEXTURE_3D, i, gl_internal_format, mip_width, mip_height,
+ mip_depth, 0, gl_format, gl_type, NULL);
+ } else {
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format, width, height, depth, i);
+ unsigned int size = GetMipLevelSize(mip_info);
+ glCompressedTexImage3D(GL_TEXTURE_3D, i, gl_internal_format, mip_width,
+ mip_height, mip_depth, 0, size, buffer.get());
+ }
+ mip_width = std::max(1U, mip_width >> 1);
+ mip_height = std::max(1U, mip_height >> 1);
+ mip_depth = std::max(1U, mip_depth >> 1);
+ }
+ return new Texture3DGL(levels, format, flags, width, height, depth,
+ gl_texture);
+}
+
+bool Texture3DGL::SetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ const void *data) {
+ if (level >= levels())
+ return false;
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format(), width_, height_, depth_, level);
+ SetImageHelper helper;
+ if (!helper.Initialize(mip_info, volume, row_pitch, slice_pitch, size, data))
+ return false;
+
+ GLenum gl_internal_format = 0;
+ GLenum gl_format = 0;
+ GLenum gl_type = 0;
+ bool r = GetGLFormatType(format(), &gl_internal_format, &gl_format, &gl_type);
+ DCHECK(r);
+ glBindTexture(GL_TEXTURE_3D, gl_texture_);
+ if (gl_format) {
+ glTexSubImage3D(GL_TEXTURE_3D, level, volume.x, volume.y, volume.z,
+ volume.width, volume.height, volume.depth,
+ gl_format, gl_type, helper.image_data());
+ } else {
+ glCompressedTexSubImage3D(GL_TEXTURE_3D, level, volume.x, volume.y,
+ volume.z, volume.width, volume.height,
+ volume.depth, gl_internal_format,
+ helper.image_size(), helper.image_data());
+ }
+ return true;
+}
+
+bool Texture3DGL::GetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ void *data) {
+ if (level >= levels())
+ return false;
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format(), width_, height_, depth_, level);
+ GetImageHelper helper;
+ if (!helper.Initialize(mip_info, volume, row_pitch, slice_pitch, size, data))
+ return false;
+
+ GLenum gl_internal_format = 0;
+ GLenum gl_format = 0;
+ GLenum gl_type = 0;
+ bool r = GetGLFormatType(format(), &gl_internal_format, &gl_format, &gl_type);
+ DCHECK(r);
+ glBindTexture(GL_TEXTURE_3D, gl_texture_);
+ if (gl_format) {
+ glGetTexImage(GL_TEXTURE_3D, level, gl_format, gl_type,
+ helper.image_data());
+ } else {
+ glGetCompressedTexImage(GL_TEXTURE_3D, level, helper.image_data());
+ }
+
+ helper.Finalize();
+ return true;
+}
+
+TextureCubeGL *TextureCubeGL::Create(unsigned int side,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags) {
+ DCHECK_GT(side, 0);
+ DCHECK_GT(levels, 0);
+ GLenum gl_internal_format = 0;
+ GLenum gl_format = 0;
+ GLenum gl_type = 0;
+ bool r = GetGLFormatType(format, &gl_internal_format, &gl_format, &gl_type);
+ DCHECK(r); // Was checked in the decoder.
+ GLuint gl_texture = 0;
+ glGenTextures(1, &gl_texture);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, gl_texture);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL,
+ levels-1);
+ // glCompressedTexImage2D does't accept NULL as a parameter, so we need
+ // to pass in some data.
+ scoped_array<unsigned char> buffer;
+ if (!gl_format) {
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format, side, side, 1, 0);
+ unsigned int size = GetMipLevelSize(mip_info);
+ buffer.reset(new unsigned char[size]);
+ }
+ unsigned int mip_side = side;
+ for (unsigned int i = 0; i < levels; ++i) {
+ if (gl_format) {
+ for (unsigned int face = 0; face < 6; ++face) {
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i,
+ gl_internal_format, mip_side, mip_side,
+ 0, gl_format, gl_type, NULL);
+ }
+ } else {
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format, side, side, 1, i);
+ unsigned int size = GetMipLevelSize(mip_info);
+ for (unsigned int face = 0; face < 6; ++face) {
+ glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i,
+ gl_internal_format, mip_side, mip_side, 0, size,
+ buffer.get());
+ }
+ }
+ mip_side = std::max(1U, mip_side >> 1);
+ }
+ return new TextureCubeGL(levels, format, flags, side, gl_texture);
+}
+
+// Check that GL_TEXTURE_CUBE_MAP_POSITIVE_X + face yields the correct GLenum.
+COMPILE_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_X + texture::FACE_POSITIVE_X ==
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X, POSITIVE_X_ENUMS_DO_NOT_MATCH);
+COMPILE_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_X + texture::FACE_NEGATIVE_X ==
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X, NEGATIVE_X_ENUMS_DO_NOT_MATCH);
+COMPILE_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_X + texture::FACE_POSITIVE_Y ==
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y, POSITIVE_Y_ENUMS_DO_NOT_MATCH);
+COMPILE_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_X + texture::FACE_NEGATIVE_Y ==
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, NEGATIVE_Y_ENUMS_DO_NOT_MATCH);
+COMPILE_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_X + texture::FACE_POSITIVE_Z ==
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z, POSITIVE_Z_ENUMS_DO_NOT_MATCH);
+COMPILE_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_X + texture::FACE_NEGATIVE_Z ==
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, NEGATIVE_Z_ENUMS_DO_NOT_MATCH);
+
+bool TextureCubeGL::SetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ const void *data) {
+ if (level >= levels())
+ return false;
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format(), side_, side_, 1, level);
+ SetImageHelper helper;
+ if (!helper.Initialize(mip_info, volume, row_pitch, slice_pitch, size, data))
+ return false;
+
+ GLenum gl_internal_format = 0;
+ GLenum gl_format = 0;
+ GLenum gl_type = 0;
+ bool r = GetGLFormatType(format(), &gl_internal_format, &gl_format, &gl_type);
+ DCHECK(r);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, gl_texture_);
+ GLenum face_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
+ if (gl_format) {
+ glTexSubImage2D(face_target, level, volume.x, volume.y, volume.width,
+ volume.height, gl_format, gl_type, helper.image_data());
+ } else {
+ glCompressedTexSubImage2D(face_target, level, volume.x, volume.y,
+ volume.width, volume.height, gl_internal_format,
+ helper.image_size(), helper.image_data());
+ }
+ return true;
+}
+
+bool TextureCubeGL::GetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ void *data) {
+ if (level >= levels())
+ return false;
+ MipLevelInfo mip_info;
+ MakeMipLevelInfo(&mip_info, format(), side_, side_, 1, level);
+ GetImageHelper helper;
+ if (!helper.Initialize(mip_info, volume, row_pitch, slice_pitch, size, data))
+ return false;
+
+ GLenum gl_internal_format = 0;
+ GLenum gl_format = 0;
+ GLenum gl_type = 0;
+ bool r = GetGLFormatType(format(), &gl_internal_format, &gl_format, &gl_type);
+ DCHECK(r);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, gl_texture_);
+ GLenum face_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
+ if (gl_format) {
+ glGetTexImage(face_target, level, gl_format, gl_type,
+ helper.image_data());
+ } else {
+ glGetCompressedTexImage(face_target, level, helper.image_data());
+ }
+
+ helper.Finalize();
+ return true;
+}
+
+// GAPIGL functions.
+
+// Destroys a texture resource.
+BufferSyncInterface::ParseError GAPIGL::DestroyTexture(ResourceID id) {
+ // Dirty effect, because this texture id may be used.
+ DirtyEffect();
+ return textures_.Destroy(id) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+// Creates a 2D texture resource.
+BufferSyncInterface::ParseError GAPIGL::CreateTexture2D(
+ ResourceID id,
+ unsigned int width,
+ unsigned int height,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags) {
+ Texture2DGL *texture = Texture2DGL::Create(width, height, levels, format,
+ flags);
+ if (!texture) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ // Dirty effect, because this texture id may be used.
+ DirtyEffect();
+ textures_.Assign(id, texture);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+// Creates a 3D texture resource.
+BufferSyncInterface::ParseError GAPIGL::CreateTexture3D(
+ ResourceID id,
+ unsigned int width,
+ unsigned int height,
+ unsigned int depth,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags) {
+ Texture3DGL *texture = Texture3DGL::Create(width, height, depth, levels,
+ format, flags);
+ if (!texture) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ // Dirty effect, because this texture id may be used.
+ DirtyEffect();
+ textures_.Assign(id, texture);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+// Creates a cube map texture resource.
+BufferSyncInterface::ParseError GAPIGL::CreateTextureCube(
+ ResourceID id,
+ unsigned int side,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags) {
+ TextureCubeGL *texture = TextureCubeGL::Create(side, levels, format, flags);
+ if (!texture) return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ // Dirty effect, because this texture id may be used.
+ DirtyEffect();
+ textures_.Assign(id, texture);
+ return BufferSyncInterface::PARSE_NO_ERROR;
+}
+
+// Copies the data into a texture resource.
+BufferSyncInterface::ParseError GAPIGL::SetTextureData(
+ ResourceID id,
+ unsigned int x,
+ unsigned int y,
+ unsigned int z,
+ unsigned int width,
+ unsigned int height,
+ unsigned int depth,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ const void *data) {
+ TextureGL *texture = textures_.Get(id);
+ if (!texture)
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ Volume volume = {x, y, z, width, height, depth};
+ // Dirty effect: SetData may need to call glBindTexture which will mess up the
+ // sampler parameters.
+ DirtyEffect();
+ return texture->SetData(volume, level, face, row_pitch, slice_pitch,
+ size, data) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+// Copies the data from a texture resource.
+BufferSyncInterface::ParseError GAPIGL::GetTextureData(
+ ResourceID id,
+ unsigned int x,
+ unsigned int y,
+ unsigned int z,
+ unsigned int width,
+ unsigned int height,
+ unsigned int depth,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ void *data) {
+ TextureGL *texture = textures_.Get(id);
+ if (!texture)
+ return BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+ Volume volume = {x, y, z, width, height, depth};
+ // Dirty effect: GetData may need to call glBindTexture which will mess up the
+ // sampler parameters.
+ DirtyEffect();
+ return texture->GetData(volume, level, face, row_pitch, slice_pitch,
+ size, data) ?
+ BufferSyncInterface::PARSE_NO_ERROR :
+ BufferSyncInterface::PARSE_INVALID_ARGUMENTS;
+}
+
+} // namespace command_buffer
+} // namespace o3d
diff --git a/o3d/command_buffer/service/cross/gl/texture_gl.h b/o3d/command_buffer/service/cross/gl/texture_gl.h
new file mode 100644
index 0000000..bc6d9c2
--- /dev/null
+++ b/o3d/command_buffer/service/cross/gl/texture_gl.h
@@ -0,0 +1,223 @@
+/*
+ * 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.
+ */
+
+
+// This file declares the TextureGL, Texture2DGL, Texture3DGL and TextureCubeGL
+// classes.
+
+#ifndef O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_TEXTURE_GL_H_
+#define O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_TEXTURE_GL_H_
+
+#include "command_buffer/common/cross/gapi_interface.h"
+#include "command_buffer/service/cross/gl/gl_utils.h"
+#include "command_buffer/service/cross/resource.h"
+#include "command_buffer/service/cross/texture_utils.h"
+
+namespace o3d {
+namespace command_buffer {
+
+// The base class for a GL texture resource, providing access to the base GL
+// texture that can be assigned to an effect parameter or a sampler unit.
+class TextureGL : public Texture {
+ public:
+ TextureGL(texture::Type type,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags,
+ GLuint gl_texture)
+ : Texture(type, levels, format, flags),
+ gl_texture_(gl_texture) {}
+ virtual ~TextureGL();
+
+ // Gets the GL texture object.
+ GLuint gl_texture() const { return gl_texture_; }
+
+ // Sets data into a texture resource.
+ virtual bool SetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ const void *data) = 0;
+
+ // Gets data from a texture resource.
+ virtual bool GetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ void *data) = 0;
+
+ protected:
+ const GLuint gl_texture_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureGL);
+};
+
+// A 2D texture resource for GL.
+class Texture2DGL : public TextureGL {
+ public:
+ Texture2DGL(unsigned int levels,
+ texture::Format format,
+ unsigned int flags,
+ unsigned int width,
+ unsigned int height,
+ GLuint gl_texture)
+ : TextureGL(texture::TEXTURE_2D, levels, format, flags, gl_texture),
+ width_(width),
+ height_(height) {}
+
+ // Creates a 2D texture resource.
+ static Texture2DGL *Create(unsigned int width,
+ unsigned int height,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags);
+
+ // Sets data into a 2D texture resource.
+ virtual bool SetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ const void *data);
+
+ // Gets data from a 2D texture resource.
+ virtual bool GetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ void *data);
+
+ private:
+ unsigned int width_;
+ unsigned int height_;
+ DISALLOW_COPY_AND_ASSIGN(Texture2DGL);
+};
+
+// A 3D texture resource for GL.
+class Texture3DGL : public TextureGL {
+ public:
+ Texture3DGL(unsigned int levels,
+ texture::Format format,
+ unsigned int flags,
+ unsigned int width,
+ unsigned int height,
+ unsigned int depth,
+ GLuint gl_texture)
+ : TextureGL(texture::TEXTURE_2D, levels, format, flags, gl_texture),
+ width_(width),
+ height_(height),
+ depth_(depth) {}
+
+ // Creates a 3D texture resource.
+ static Texture3DGL *Create(unsigned int width,
+ unsigned int height,
+ unsigned int depth,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags);
+
+ // Sets data into a 3D texture resource.
+ virtual bool SetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ const void *data);
+
+ // Gets data from a 3D texture resource.
+ virtual bool GetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ void *data);
+
+ private:
+ unsigned int width_;
+ unsigned int height_;
+ unsigned int depth_;
+ DISALLOW_COPY_AND_ASSIGN(Texture3DGL);
+};
+
+// A cube map texture resource for GL.
+class TextureCubeGL : public TextureGL {
+ public:
+ TextureCubeGL(unsigned int levels,
+ texture::Format format,
+ unsigned int flags,
+ unsigned int side,
+ GLuint gl_texture)
+ : TextureGL(texture::TEXTURE_CUBE, levels, format, flags, gl_texture),
+ side_(side) {}
+
+ // Creates a cube map texture resource.
+ static TextureCubeGL *Create(unsigned int side,
+ unsigned int levels,
+ texture::Format format,
+ unsigned int flags);
+
+ // Sets data into a cube map texture resource.
+ virtual bool SetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ const void *data);
+
+ // Gets data from a cube map texture resource.
+ virtual bool GetData(const Volume& volume,
+ unsigned int level,
+ texture::Face face,
+ unsigned int row_pitch,
+ unsigned int slice_pitch,
+ unsigned int size,
+ void *data);
+
+ private:
+ unsigned int side_;
+ DISALLOW_COPY_AND_ASSIGN(TextureCubeGL);
+};
+
+} // namespace command_buffer
+} // namespace o3d
+
+#endif // O3D_COMMAND_BUFFER_SERVICE_CROSS_GL_TEXTURE_GL_H_