blob: 441ffa1ae80a31612025b77e9731c17384096fe4 [file] [log] [blame]
[email protected]1bee3982009-12-17 23:15:281// Copyright (c) 2009 The Chromium Authors. All rights reserved.
[email protected]96449d2c2009-11-25 00:01:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]8a837bb2010-01-05 00:21:245#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
[email protected]74470702010-01-06 18:51:166
7#include <stdio.h>
8
[email protected]1aef98132010-02-23 18:00:079#include <algorithm>
[email protected]96449d2c2009-11-25 00:01:3210#include <vector>
11#include <string>
12#include <map>
[email protected]0bfd9882010-02-05 23:02:2513#include <build/build_config.h> // NOLINT
[email protected]2041cf342010-02-19 03:15:5914#include "base/callback.h"
[email protected]a93bb842010-02-16 23:03:4715#include "base/linked_ptr.h"
[email protected]96449d2c2009-11-25 00:01:3216#include "base/scoped_ptr.h"
17#define GLES2_GPU_SERVICE 1
18#include "gpu/command_buffer/common/gles2_cmd_format.h"
19#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]3916c97e2010-02-25 03:20:5020#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3221#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5022#include "gpu/command_buffer/service/context_group.h"
[email protected]96449d2c2009-11-25 00:01:3223#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4624#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4725#include "gpu/command_buffer/service/id_manager.h"
26#include "gpu/command_buffer/service/program_manager.h"
27#include "gpu/command_buffer/service/shader_manager.h"
28#include "gpu/command_buffer/service/texture_manager.h"
[email protected]43f28f832010-02-03 02:28:4829#if defined(UNIT_TEST)
30#elif defined(OS_LINUX)
[email protected]872fe722010-02-02 16:03:3331// XWindowWrapper is stubbed out for unit-tests.
[email protected]be4f1882010-01-06 04:38:5532#include "gpu/command_buffer/service/x_utils.h"
[email protected]43f28f832010-02-03 02:28:4833#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:3534#include "chrome/common/accelerated_surface_mac.h"
[email protected]be4f1882010-01-06 04:38:5535#endif
[email protected]96449d2c2009-11-25 00:01:3236
[email protected]a7a27ace2009-12-12 00:11:2537namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3238namespace gles2 {
39
[email protected]07f54fcc2009-12-22 02:46:3040// Check that certain assumptions the code makes are true. There are places in
41// the code where shared memory is passed direclty to GL. Example, glUniformiv,
42// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
43// a few others) are 32bits. If they are not 32bits the code will have to change
44// to call those GL functions with service side memory and then copy the results
45// to shared memory, converting the sizes.
46COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
47 GLint_not_same_size_as_uint32);
48COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
49 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3750COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
51 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3052
[email protected]43f28f832010-02-03 02:28:4853// TODO(kbr): the use of this anonymous namespace core dumps the
54// linker on Mac OS X 10.6 when the symbol ordering file is used
55// namespace {
[email protected]96449d2c2009-11-25 00:01:3256
57// Returns the address of the first byte after a struct.
58template <typename T>
59const void* AddressAfterStruct(const T& pod) {
60 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
61}
62
[email protected]07f54fcc2009-12-22 02:46:3063// Returns the address of the frst byte after the struct or NULL if size >
64// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3265template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3066RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
67 uint32 size,
68 uint32 immediate_data_size) {
69 return (size <= immediate_data_size) ?
70 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
71 NULL;
[email protected]96449d2c2009-11-25 00:01:3272}
73
[email protected]07f54fcc2009-12-22 02:46:3074// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1875bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3276 GLuint count,
77 size_t size,
[email protected]a76b0052010-03-05 00:33:1878 unsigned int elements_per_unit,
79 uint32* dst) {
80 uint32 value;
81 if (!SafeMultiplyUint32(count, size, &value)) {
82 return false;
83 }
84 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
85 return false;
86 }
87 *dst = value;
88 return true;
[email protected]96449d2c2009-11-25 00:01:3289}
90
91// A struct to hold info about each command.
92struct CommandInfo {
93 int arg_flags; // How to handle the arguments for this command
94 int arg_count; // How many arguments are expected for this command.
95};
96
97// A table of CommandInfo for all the commands.
98const CommandInfo g_command_info[] = {
99 #define GLES2_CMD_OP(name) { \
100 name::kArgFlags, \
101 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
102
103 GLES2_COMMAND_LIST(GLES2_CMD_OP)
104
105 #undef GLES2_CMD_OP
106};
107
[email protected]43f28f832010-02-03 02:28:48108// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32109
[email protected]3916c97e2010-02-25 03:20:50110GLES2Decoder::GLES2Decoder(ContextGroup* group)
111 : group_(group),
[email protected]69d80ae2009-12-23 08:57:42112#if defined(UNIT_TEST)
[email protected]3916c97e2010-02-25 03:20:50113 debug_(false) {
[email protected]69d80ae2009-12-23 08:57:42114#elif defined(OS_LINUX)
[email protected]3916c97e2010-02-25 03:20:50115 debug_(false),
[email protected]b9849abf2009-11-25 19:13:19116 window_(NULL) {
117#elif defined(OS_WIN)
[email protected]3916c97e2010-02-25 03:20:50118 debug_(false),
[email protected]b9849abf2009-11-25 19:13:19119 hwnd_(NULL) {
120#else
[email protected]3916c97e2010-02-25 03:20:50121 debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32122#endif
123}
124
[email protected]3916c97e2010-02-25 03:20:50125GLES2Decoder::~GLES2Decoder() {
126}
127
[email protected]96449d2c2009-11-25 00:01:32128// This class implements GLES2Decoder so we don't have to expose all the GLES2
129// cmd stuff to outside this class.
130class GLES2DecoderImpl : public GLES2Decoder {
131 public:
[email protected]3916c97e2010-02-25 03:20:50132 explicit GLES2DecoderImpl(ContextGroup* group);
133
[email protected]07f54fcc2009-12-22 02:46:30134 // Info about Vertex Attributes. This is used to track what the user currently
135 // has bound on each Vertex Attribute so that checking can be done at
136 // glDrawXXX time.
137 class VertexAttribInfo {
138 public:
139 VertexAttribInfo()
140 : enabled_(false),
141 size_(0),
142 type_(0),
143 offset_(0),
[email protected]3916c97e2010-02-25 03:20:50144 real_stride_(0) {
[email protected]07f54fcc2009-12-22 02:46:30145 }
[email protected]3916c97e2010-02-25 03:20:50146
[email protected]07f54fcc2009-12-22 02:46:30147 // Returns true if this VertexAttrib can access index.
148 bool CanAccess(GLuint index);
149
150 void set_enabled(bool enabled) {
151 enabled_ = enabled;
152 }
153
[email protected]3916c97e2010-02-25 03:20:50154 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30155 return buffer_;
156 }
157
[email protected]8bf5a3e2010-01-29 04:21:36158 GLsizei offset() const {
159 return offset_;
160 }
161
[email protected]07f54fcc2009-12-22 02:46:30162 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50163 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30164 GLint size,
165 GLenum type,
166 GLsizei real_stride,
167 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24168 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30169 buffer_ = buffer;
170 size_ = size;
171 type_ = type;
172 real_stride_ = real_stride;
173 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50174 }
175
176 void ClearBuffer() {
177 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30178 }
179
180 private:
181 // Whether or not this attribute is enabled.
182 bool enabled_;
183
184 // number of components (1, 2, 3, 4)
185 GLint size_;
186
187 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
188 GLenum type_;
189
190 // The offset into the buffer.
191 GLsizei offset_;
192
193 // The stride that will be used to access the buffer. This is the actual
194 // stide, NOT the GL bogus stride. In other words there is never a stride
195 // of 0.
196 GLsizei real_stride_;
197
[email protected]3916c97e2010-02-25 03:20:50198 // The buffer bound to this attribute.
199 BufferManager::BufferInfo::Ref buffer_;
[email protected]07f54fcc2009-12-22 02:46:30200 };
201
[email protected]96449d2c2009-11-25 00:01:32202 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14203 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50204 unsigned int arg_count,
205 const void* args);
[email protected]96449d2c2009-11-25 00:01:32206
207 // Overridden from AsyncAPIInterface.
208 virtual const char* GetCommandName(unsigned int command_id) const;
209
210 // Overridden from GLES2Decoder.
211 virtual bool Initialize();
[email protected]96449d2c2009-11-25 00:01:32212 virtual void Destroy();
[email protected]eb54a562010-01-20 21:55:18213 virtual bool MakeCurrent();
[email protected]8a837bb2010-01-05 00:21:24214 virtual uint32 GetServiceIdForTesting(uint32 client_id);
[email protected]56ac89b2010-03-17 21:16:55215 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]8a837bb2010-01-05 00:21:24216
[email protected]6098b712010-02-09 17:59:34217#if defined(OS_MACOSX)
[email protected]43f28f832010-02-03 02:28:48218 // Overridden from GLES2Decoder.
[email protected]1aef98132010-02-23 18:00:07219
220 // The recommended usage is to call SetWindowSizeForIOSurface() first, and if
221 // that returns 0, try calling SetWindowSizeForTransportDIB(). A return value
222 // of 0 from SetWindowSizeForIOSurface() might mean the IOSurface API is not
223 // available, which is true if you are not running on Max OS X 10.6 or later.
224 // If SetWindowSizeForTransportDIB() also returns a NULL handle, then an
225 // error has occured.
226 virtual uint64 SetWindowSizeForIOSurface(int32 width, int32 height);
227 virtual TransportDIB::Handle SetWindowSizeForTransportDIB(int32 width,
228 int32 height);
229 // |allocator| sends a message to the renderer asking for a new
230 // TransportDIB big enough to hold the rendered bits. The parameters to the
231 // call back are the size of the DIB and the handle (filled in on return).
232 virtual void SetTransportDIBAllocAndFree(
233 Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
234 Callback1<TransportDIB::Id>::Type* deallocator);
[email protected]43f28f832010-02-03 02:28:48235#endif
236
237 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
238
[email protected]96449d2c2009-11-25 00:01:32239 private:
[email protected]3916c97e2010-02-25 03:20:50240 // State associated with each texture unit.
241 struct TextureUnit {
242 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
243
244 // The last target that was bound to this texture unit.
245 GLenum bind_target;
246
247 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
248 TextureManager::TextureInfo::Ref bound_texture_2d;
249
250 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
251 // glBindTexture
252 TextureManager::TextureInfo::Ref bound_texture_cube_map;
253 };
254
[email protected]a93bb842010-02-16 23:03:47255 friend void GLGenTexturesHelper(
256 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
257 friend void GLDeleteTexturesHelper(
258 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
259 friend void GLGenBuffersHelper(
260 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
261 friend void GLDeleteBuffersHelper(
262 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
263
[email protected]3916c97e2010-02-25 03:20:50264 // TODO(gman): Cache these pointers?
265 IdManager* id_manager() {
266 return group_->id_manager();
267 }
268
269 BufferManager* buffer_manager() {
270 return group_->buffer_manager();
271 }
272
273 ProgramManager* program_manager() {
274 return group_->program_manager();
275 }
276
277 ShaderManager* shader_manager() {
278 return group_->shader_manager();
279 }
280
281 TextureManager* texture_manager() {
282 return group_->texture_manager();
283 }
284
[email protected]246a70452010-03-05 21:53:50285#if defined(OS_WIN)
286 static bool InitializeOneOff(bool anti_aliased);
287#endif
288
289
[email protected]96449d2c2009-11-25 00:01:32290 bool InitPlatformSpecific();
[email protected]246a70452010-03-05 21:53:50291 static bool InitGlew();
292 void DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:32293
[email protected]96449d2c2009-11-25 00:01:32294 // Template to help call glGenXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30295 template <void gl_gen_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32296 bool GenGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12297 DCHECK_GE(n, 0);
[email protected]8a837bb2010-01-05 00:21:24298 if (!ValidateIdsAreUnused(n, client_ids)) {
299 return false;
300 }
[email protected]96449d2c2009-11-25 00:01:32301 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30302 gl_gen_function(this, n, temp.get());
[email protected]07f54fcc2009-12-22 02:46:30303 return RegisterObjects(n, client_ids, temp.get());
[email protected]96449d2c2009-11-25 00:01:32304 }
305
306 // Template to help call glDeleteXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30307 template <void gl_delete_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32308 bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12309 DCHECK_GE(n, 0);
[email protected]96449d2c2009-11-25 00:01:32310 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30311 UnregisterObjects(n, client_ids, temp.get());
312 gl_delete_function(this, n, temp.get());
[email protected]96449d2c2009-11-25 00:01:32313 return true;
314 }
315
[email protected]8a837bb2010-01-05 00:21:24316 // Check that the given ids are not used.
317 bool ValidateIdsAreUnused(GLsizei n, const GLuint* client_ids);
318
[email protected]07f54fcc2009-12-22 02:46:30319 // Register client ids with generated service ids.
320 bool RegisterObjects(
321 GLsizei n, const GLuint* client_ids, const GLuint* service_ids);
322
323 // Unregisters client ids with service ids.
324 void UnregisterObjects(
325 GLsizei n, const GLuint* client_ids, GLuint* service_ids);
326
[email protected]a93bb842010-02-16 23:03:47327 // Creates a TextureInfo for the given texture.
328 void CreateTextureInfo(GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:50329 texture_manager()->CreateTextureInfo(texture);
[email protected]a93bb842010-02-16 23:03:47330 }
331
332 // Gets the texture info for the given texture. Returns NULL if none exists.
333 TextureManager::TextureInfo* GetTextureInfo(GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:50334 TextureManager::TextureInfo* info =
335 texture_manager()->GetTextureInfo(texture);
336 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47337 }
338
339 // Deletes the texture info for the given texture.
[email protected]3916c97e2010-02-25 03:20:50340 void RemoveTextureInfo(GLuint texture) {
341 texture_manager()->RemoveTextureInfo(texture);
342 }
[email protected]a93bb842010-02-16 23:03:47343
344 // Wrapper for CompressedTexImage2D commands.
345 error::Error DoCompressedTexImage2D(
346 GLenum target,
347 GLint level,
348 GLenum internal_format,
349 GLsizei width,
350 GLsizei height,
351 GLint border,
352 GLsizei image_size,
353 const void* data);
354
355 // Wrapper for TexImage2D commands.
356 error::Error DoTexImage2D(
357 GLenum target,
358 GLint level,
359 GLenum internal_format,
360 GLsizei width,
361 GLsizei height,
362 GLint border,
363 GLenum format,
364 GLenum type,
365 const void* pixels,
366 uint32 pixels_size);
367
368 // Creates a ProgramInfo for the given program.
369 void CreateProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50370 program_manager()->CreateProgramInfo(program);
[email protected]a93bb842010-02-16 23:03:47371 }
372
[email protected]07f54fcc2009-12-22 02:46:30373 // Gets the program info for the given program. Returns NULL if none exists.
374 // Programs that have no had glLinkProgram succesfully called on them will
375 // not exist.
[email protected]1d32bc82010-01-13 22:06:46376 ProgramManager::ProgramInfo* GetProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50377 ProgramManager::ProgramInfo* info =
378 program_manager()->GetProgramInfo(program);
379 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46380 }
[email protected]07f54fcc2009-12-22 02:46:30381
[email protected]07f54fcc2009-12-22 02:46:30382 // Deletes the program info for the given program.
[email protected]1d32bc82010-01-13 22:06:46383 void RemoveProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50384 program_manager()->RemoveProgramInfo(program);
[email protected]1d32bc82010-01-13 22:06:46385 }
[email protected]07f54fcc2009-12-22 02:46:30386
[email protected]45bf5152010-02-12 00:11:31387 // Creates a ShaderInfo for the given shader.
388 void CreateShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50389 shader_manager()->CreateShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31390 }
391
392 // Gets the shader info for the given shader. Returns NULL if none exists.
393 ShaderManager::ShaderInfo* GetShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50394 ShaderManager::ShaderInfo* info = shader_manager()->GetShaderInfo(shader);
395 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]45bf5152010-02-12 00:11:31396 }
397
398 // Deletes the shader info for the given shader.
399 void RemoveShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50400 shader_manager()->RemoveShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31401 }
402
[email protected]a93bb842010-02-16 23:03:47403 // Creates a buffer info for the given buffer.
404 void CreateBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50405 return buffer_manager()->CreateBufferInfo(buffer);
[email protected]a93bb842010-02-16 23:03:47406 }
407
[email protected]07f54fcc2009-12-22 02:46:30408 // Gets the buffer info for the given buffer.
[email protected]1d32bc82010-01-13 22:06:46409 BufferManager::BufferInfo* GetBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50410 BufferManager::BufferInfo* info = buffer_manager()->GetBufferInfo(buffer);
411 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46412 }
[email protected]07f54fcc2009-12-22 02:46:30413
[email protected]a93bb842010-02-16 23:03:47414 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
415 // on glDeleteBuffers so we can make sure the user does not try to render
416 // with deleted buffers.
417 void RemoveBufferInfo(GLuint buffer_id);
418
[email protected]3916c97e2010-02-25 03:20:50419 // Helper for glShaderSource.
420 error::Error ShaderSourceHelper(
421 GLuint shader, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30422
[email protected]96449d2c2009-11-25 00:01:32423 // Wrapper for glCreateProgram
424 void CreateProgramHelper(GLuint client_id);
425
426 // Wrapper for glCreateShader
427 void CreateShaderHelper(GLenum type, GLuint client_id);
428
[email protected]3916c97e2010-02-25 03:20:50429 // Wrapper for glActiveTexture
430 void DoActiveTexture(GLenum texture_unit);
431
[email protected]96449d2c2009-11-25 00:01:32432 // Wrapper for glBindBuffer since we need to track the current targets.
433 void DoBindBuffer(GLenum target, GLuint buffer);
434
[email protected]86093972010-03-11 00:13:56435 // Wrapper for glBindFramebuffer since we need to track the current targets.
436 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
437
438 // Wrapper for glBindRenderbuffer since we need to track the current targets.
439 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
440
[email protected]a93bb842010-02-16 23:03:47441 // Wrapper for glBindTexture since we need to track the current targets.
442 void DoBindTexture(GLenum target, GLuint texture);
443
[email protected]36cef8ce2010-03-16 07:34:45444 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11445 void DoBufferData(
446 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
447
[email protected]36cef8ce2010-03-16 07:34:45448 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11449 void DoBufferSubData(
450 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
451
[email protected]36cef8ce2010-03-16 07:34:45452 // Wrapper for glCheckFramebufferStatus
453 GLenum DoCheckFramebufferStatus(GLenum target);
454
[email protected]45bf5152010-02-12 00:11:31455 // Wrapper for glCompileShader.
456 void DoCompileShader(GLuint shader);
457
[email protected]07f54fcc2009-12-22 02:46:30458 // Wrapper for glDrawArrays.
459 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
460
461 // Wrapper for glDisableVertexAttribArray.
462 void DoDisableVertexAttribArray(GLuint index);
463
464 // Wrapper for glEnableVertexAttribArray.
465 void DoEnableVertexAttribArray(GLuint index);
466
[email protected]36cef8ce2010-03-16 07:34:45467 // Wrapper for glFramebufferRenderbufffer.
468 void DoFramebufferRenderbuffer(
469 GLenum target, GLenum attachment, GLenum renderbuffertarget,
470 GLuint renderbuffer);
471
472 // Wrapper for glFramebufferTexture2D.
473 void DoFramebufferTexture2D(
474 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
475 GLint level);
476
[email protected]a93bb842010-02-16 23:03:47477 // Wrapper for glGenerateMipmap
478 void DoGenerateMipmap(GLenum target);
479
[email protected]36cef8ce2010-03-16 07:34:45480 // Wrapper for glGetFramebufferAttachmentParameteriv.
481 void DoGetFramebufferAttachmentParameteriv(
482 GLenum target, GLenum attachment, GLenum pname, GLint* params);
483
484 // Wrapper for glRenderbufferParameteriv.
485 void DoGetRenderbufferParameteriv(
486 GLenum target, GLenum pname, GLint* params);
487
[email protected]ddd968b82010-03-02 00:44:29488 // Wrapper for glGetShaderiv
489 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
490
[email protected]45bf5152010-02-12 00:11:31491 // Wrapper for glGetShaderSource.
492 void DoGetShaderSource(
493 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst);
494
[email protected]07f54fcc2009-12-22 02:46:30495 // Wrapper for glLinkProgram
496 void DoLinkProgram(GLuint program);
497
[email protected]36cef8ce2010-03-16 07:34:45498 // Wrapper for glRenderbufferStorage.
499 void DoRenderbufferStorage(
500 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
501
[email protected]96449d2c2009-11-25 00:01:32502 // Swaps the buffers (copies/renders to the current window).
503 void DoSwapBuffers();
504
[email protected]3916c97e2010-02-25 03:20:50505 // Wrappers for glTexParameter functions.
506 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
507 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
508 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
509 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
510
511 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
512 // spec only these 2 functions can be used to set sampler uniforms.
513 void DoUniform1i(GLint location, GLint v0);
514 void DoUniform1iv(GLint location, GLsizei count, const GLint *value);
515
[email protected]07f54fcc2009-12-22 02:46:30516 // Wrapper for glUseProgram
517 void DoUseProgram(GLuint program);
518
[email protected]96449d2c2009-11-25 00:01:32519 // Gets the GLError through our wrapper.
520 GLenum GetGLError();
521
522 // Sets our wrapper for the GLError.
523 void SetGLError(GLenum error);
524
[email protected]07f54fcc2009-12-22 02:46:30525 // Copies the real GL errors to the wrapper. This is so we can
526 // make sure there are no native GL errors before calling some GL function
527 // so that on return we know any error generated was for that specific
528 // command.
529 void CopyRealGLErrorsToWrapper();
530
531 // Checks if the current program and vertex attributes are valid for drawing.
532 bool IsDrawValid(GLuint max_vertex_accessed);
533
[email protected]3916c97e2010-02-25 03:20:50534 void SetBlackTextureForNonRenderableTextures(
535 bool* has_non_renderable_textures);
536 void RestoreStateForNonRenderableTextures();
537
[email protected]07f54fcc2009-12-22 02:46:30538 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:50539 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:30540 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:50541 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
542 bound_array_buffer_ : bound_element_array_buffer_;
543 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:30544 }
545
[email protected]a93bb842010-02-16 23:03:47546 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:50547 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
548 TextureUnit& unit = texture_units_[active_texture_unit_];
549 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:47550 switch (target) {
551 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:50552 info = unit.bound_texture_2d;
553 break;
[email protected]a93bb842010-02-16 23:03:47554 case GL_TEXTURE_CUBE_MAP:
555 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
556 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
557 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
558 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
559 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
560 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:50561 info = unit.bound_texture_cube_map;
562 break;
[email protected]1aef98132010-02-23 18:00:07563 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
564 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
565 // because |texture_| is used by the FBO rendering mechanism for readback
566 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:47567 default:
568 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:50569 return NULL;
[email protected]a93bb842010-02-16 23:03:47570 }
[email protected]3916c97e2010-02-25 03:20:50571 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47572 }
573
[email protected]f7b85372010-02-03 01:11:37574 // Validates the program and location for a glGetUniform call and returns
575 // a SizeResult setup to receive the result. Returns true if glGetUniform
576 // should be called.
577 bool GetUniformSetup(
578 GLuint program, GLint location,
579 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:25580 error::Error* error, GLuint* service_id, void** result);
[email protected]f7b85372010-02-03 01:11:37581
[email protected]86093972010-03-11 00:13:56582 bool ValidateGLenumCompressedTextureInternalFormat(GLenum format);
583
[email protected]96449d2c2009-11-25 00:01:32584 // Generate a member function prototype for each command in an automated and
585 // typesafe way.
586 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:14587 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:19588 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:32589 const gles2::name& args); \
590
591 GLES2_COMMAND_LIST(GLES2_CMD_OP)
592
593 #undef GLES2_CMD_OP
594
[email protected]96449d2c2009-11-25 00:01:32595 // Current GL error bits.
596 uint32 error_bits_;
597
[email protected]96449d2c2009-11-25 00:01:32598 // Util to help with GL.
599 GLES2Util util_;
600
601 // pack alignment as last set by glPixelStorei
602 GLint pack_alignment_;
603
604 // unpack alignment as last set by glPixelStorei
605 GLint unpack_alignment_;
606
607 // The currently bound array buffer. If this is 0 it is illegal to call
608 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:50609 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:32610
611 // The currently bound element array buffer. If this is 0 it is illegal
612 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:50613 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:30614
615 // Info for each vertex attribute saved so we can check at glDrawXXX time
616 // if it is safe to draw.
617 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
618
[email protected]3916c97e2010-02-25 03:20:50619 // Current active texture by 0 - n index.
620 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
621 // be 2.
622 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:30623
[email protected]3916c97e2010-02-25 03:20:50624 // Which textures are bound to texture units through glActiveTexture.
625 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:47626
[email protected]3916c97e2010-02-25 03:20:50627 // Black (0,0,0,0) textures for when non-renderable textures are used.
628 // NOTE: There is no corresponding TextureInfo for these textures.
629 // TextureInfos are only for textures the client side can access.
630 GLuint black_2d_texture_id_;
631 GLuint black_cube_texture_id_;
[email protected]45bf5152010-02-12 00:11:31632
[email protected]1d32bc82010-01-13 22:06:46633 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:50634 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:30635
[email protected]86093972010-03-11 00:13:56636 // The currently bound framebuffer
637 GLuint bound_framebuffer_;
638
639 // The currently bound renderbuffer
640 GLuint bound_renderbuffer_;
641
[email protected]69d80ae2009-12-23 08:57:42642#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59643#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:42644#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:50645 static int pixel_format_;
646 HDC gl_device_context_;
[email protected]96449d2c2009-11-25 00:01:32647 HGLRC gl_context_;
[email protected]246a70452010-03-05 21:53:50648 HPBUFFERARB pbuffer_;
[email protected]43f28f832010-02-03 02:28:48649#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:35650 AcceleratedSurface surface_;
[email protected]96449d2c2009-11-25 00:01:32651#endif
652
653 bool anti_aliased_;
654
[email protected]43f28f832010-02-03 02:28:48655 scoped_ptr<Callback0::Type> swap_buffers_callback_;
656
[email protected]96449d2c2009-11-25 00:01:32657 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
658};
659
[email protected]3916c97e2010-02-25 03:20:50660GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
661 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:32662}
663
[email protected]246a70452010-03-05 21:53:50664#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59665#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]246a70452010-03-05 21:53:50666#elif defined(OS_WIN)
667int GLES2DecoderImpl::pixel_format_;
668#endif
669
[email protected]3916c97e2010-02-25 03:20:50670GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
671 : GLES2Decoder(group),
[email protected]96449d2c2009-11-25 00:01:32672 error_bits_(0),
673 util_(0), // TODO(gman): Set to actual num compress texture formats.
674 pack_alignment_(4),
675 unpack_alignment_(4),
[email protected]3916c97e2010-02-25 03:20:50676 active_texture_unit_(0),
677 black_2d_texture_id_(0),
678 black_cube_texture_id_(0),
[email protected]86093972010-03-11 00:13:56679 bound_framebuffer_(0),
680 bound_renderbuffer_(0),
[email protected]69d80ae2009-12-23 08:57:42681#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59682#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:42683#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:50684 gl_device_context_(NULL),
[email protected]96449d2c2009-11-25 00:01:32685 gl_context_(NULL),
[email protected]246a70452010-03-05 21:53:50686 pbuffer_(NULL),
[email protected]96449d2c2009-11-25 00:01:32687#endif
688 anti_aliased_(false) {
689}
690
691bool GLES2DecoderImpl::Initialize() {
[email protected]246a70452010-03-05 21:53:50692 if (!InitPlatformSpecific()) {
693 Destroy();
694 return false;
695 }
696 if (!MakeCurrent()) {
697 Destroy();
698 return false;
[email protected]eb54a562010-01-20 21:55:18699 }
700
[email protected]246a70452010-03-05 21:53:50701 // This happens in InitializeOneOff in windows. TODO(apatrick): generalize to
702 // other platforms.
703#if !defined(OS_WIN)
704 if (!InitGlew()) {
705 Destroy();
706 return false;
707 }
708#endif
709
710 CHECK_GL_ERROR();
711
712 if (!group_->Initialize()) {
713 Destroy();
714 return false;
715 }
716
717 vertex_attrib_infos_.reset(
718 new VertexAttribInfo[group_->max_vertex_attribs()]);
719 texture_units_.reset(
720 new TextureUnit[group_->max_texture_units()]);
721 GLuint ids[2];
722 glGenTextures(2, ids);
723 // Make black textures for replacing non-renderable textures.
724 black_2d_texture_id_ = ids[0];
725 black_cube_texture_id_ = ids[1];
726 static int8 black[] = {0, 0, 0, 0};
727 glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
728 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
729 GL_UNSIGNED_BYTE, black);
730 glBindTexture(GL_TEXTURE_2D, 0);
731 glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
732 static GLenum faces[] = {
733 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
734 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
735 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
736 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
737 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
738 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
739 };
740 for (size_t ii = 0; ii < arraysize(faces); ++ii) {
741 glTexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA,
742 GL_UNSIGNED_BYTE, black);
743 }
744 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
745 CHECK_GL_ERROR();
746
747 return true;
[email protected]96449d2c2009-11-25 00:01:32748}
749
[email protected]43f28f832010-02-03 02:28:48750// TODO(kbr): the use of this anonymous namespace core dumps the
751// linker on Mac OS X 10.6 when the symbol ordering file is used
752// namespace {
[email protected]96449d2c2009-11-25 00:01:32753
[email protected]69d80ae2009-12-23 08:57:42754#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59755#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:42756#elif defined(OS_WIN)
757
[email protected]96449d2c2009-11-25 00:01:32758const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
759 sizeof(kPixelFormatDescriptor), // Size of structure.
760 1, // Default version.
761 PFD_DRAW_TO_WINDOW | // Window drawing support.
762 PFD_SUPPORT_OPENGL | // OpenGL support.
763 PFD_DOUBLEBUFFER, // Double buffering support (not stereo).
764 PFD_TYPE_RGBA, // RGBA color mode (not indexed).
765 24, // 24 bit color mode.
766 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts.
767 8, 0, // 8 bit alpha
768 0, // No accumulation buffer.
769 0, 0, 0, 0, // Ignore accumulation bits.
770 24, // 24 bit z-buffer size.
771 8, // 8-bit stencil buffer.
772 0, // No aux buffer.
773 PFD_MAIN_PLANE, // Main drawing plane (not overlay).
774 0, // Reserved.
775 0, 0, 0, // Layer masks ignored.
776};
777
778LRESULT CALLBACK IntermediateWindowProc(HWND window,
779 UINT message,
780 WPARAM w_param,
781 LPARAM l_param) {
782 return ::DefWindowProc(window, message, w_param, l_param);
783}
784
[email protected]246a70452010-03-05 21:53:50785// Helper routine that does one-off initialization like determining the
786// pixel format and initializing glew.
787bool GLES2DecoderImpl::InitializeOneOff(bool anti_aliased) {
[email protected]96449d2c2009-11-25 00:01:32788 // We must initialize a GL context before we can determine the multi-sampling
789 // supported on the current hardware, so we create an intermediate window
790 // and context here.
791 HINSTANCE module_handle;
792 if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
793 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
794 reinterpret_cast<wchar_t*>(IntermediateWindowProc),
795 &module_handle)) {
796 return false;
797 }
798
799 WNDCLASS intermediate_class;
800 intermediate_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
801 intermediate_class.lpfnWndProc = IntermediateWindowProc;
802 intermediate_class.cbClsExtra = 0;
803 intermediate_class.cbWndExtra = 0;
804 intermediate_class.hInstance = module_handle;
805 intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
806 intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
807 intermediate_class.hbrBackground = NULL;
808 intermediate_class.lpszMenuName = NULL;
809 intermediate_class.lpszClassName = L"Intermediate GL Window";
810
811 ATOM class_registration = ::RegisterClass(&intermediate_class);
812 if (!class_registration) {
813 return false;
814 }
815
816 HWND intermediate_window = ::CreateWindow(
817 reinterpret_cast<wchar_t*>(class_registration),
818 L"",
819 WS_OVERLAPPEDWINDOW,
820 0, 0,
821 CW_USEDEFAULT, CW_USEDEFAULT,
822 NULL,
823 NULL,
824 NULL,
825 NULL);
826
827 if (!intermediate_window) {
828 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
829 module_handle);
830 return false;
831 }
832
833 HDC intermediate_dc = ::GetDC(intermediate_window);
[email protected]246a70452010-03-05 21:53:50834 pixel_format_ = ::ChoosePixelFormat(intermediate_dc,
835 &kPixelFormatDescriptor);
836 if (pixel_format_ == 0) {
[email protected]96449d2c2009-11-25 00:01:32837 DLOG(ERROR) << "Unable to get the pixel format for GL context.";
838 ::ReleaseDC(intermediate_window, intermediate_dc);
839 ::DestroyWindow(intermediate_window);
840 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
841 module_handle);
842 return false;
843 }
[email protected]246a70452010-03-05 21:53:50844 if (!::SetPixelFormat(intermediate_dc, pixel_format_,
[email protected]96449d2c2009-11-25 00:01:32845 &kPixelFormatDescriptor)) {
846 DLOG(ERROR) << "Unable to set the pixel format for GL context.";
847 ::ReleaseDC(intermediate_window, intermediate_dc);
848 ::DestroyWindow(intermediate_window);
849 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
850 module_handle);
851 return false;
852 }
853
[email protected]246a70452010-03-05 21:53:50854 // Create a temporary GL context to query for multisampled pixel formats.
[email protected]96449d2c2009-11-25 00:01:32855 HGLRC gl_context = ::wglCreateContext(intermediate_dc);
856 if (::wglMakeCurrent(intermediate_dc, gl_context)) {
857 // GL context was successfully created and applied to the window's DC.
858 // Startup GLEW, the GL extensions wrangler.
[email protected]246a70452010-03-05 21:53:50859 if (InitGlew()) {
[email protected]96449d2c2009-11-25 00:01:32860 DLOG(INFO) << "Initialized GLEW " << ::glewGetString(GLEW_VERSION);
861 } else {
[email protected]96449d2c2009-11-25 00:01:32862 ::wglMakeCurrent(intermediate_dc, NULL);
863 ::wglDeleteContext(gl_context);
864 ::ReleaseDC(intermediate_window, intermediate_dc);
865 ::DestroyWindow(intermediate_window);
866 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
867 module_handle);
868 return false;
869 }
870
871 // If the multi-sample extensions are present, query the api to determine
872 // the pixel format.
873 if (anti_aliased && WGLEW_ARB_pixel_format && WGLEW_ARB_multisample) {
874 int pixel_attributes[] = {
875 WGL_SAMPLES_ARB, 4,
876 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
877 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
878 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
879 WGL_COLOR_BITS_ARB, 24,
880 WGL_ALPHA_BITS_ARB, 8,
881 WGL_DEPTH_BITS_ARB, 24,
882 WGL_STENCIL_BITS_ARB, 8,
883 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
884 WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
885 0, 0};
886
887 float pixel_attributes_f[] = {0, 0};
888 int msaa_pixel_format;
889 unsigned int num_formats;
890
891 // Query for the highest sampling rate supported, starting at 4x.
892 static const int kSampleCount[] = {4, 2};
893 static const int kNumSamples = 2;
894 for (int sample = 0; sample < kNumSamples; ++sample) {
895 pixel_attributes[1] = kSampleCount[sample];
896 if (GL_TRUE == ::wglChoosePixelFormatARB(intermediate_dc,
897 pixel_attributes,
898 pixel_attributes_f,
899 1,
900 &msaa_pixel_format,
901 &num_formats)) {
[email protected]246a70452010-03-05 21:53:50902 pixel_format_ = msaa_pixel_format;
[email protected]96449d2c2009-11-25 00:01:32903 break;
904 }
905 }
906 }
907 }
908
909 ::wglMakeCurrent(intermediate_dc, NULL);
910 ::wglDeleteContext(gl_context);
911 ::ReleaseDC(intermediate_window, intermediate_dc);
912 ::DestroyWindow(intermediate_window);
913 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
914 module_handle);
915 return true;
916}
917
[email protected]69d80ae2009-12-23 08:57:42918#endif // OS_WIN
919
[email protected]07f54fcc2009-12-22 02:46:30920// These commands convert from c calls to local os calls.
921void GLGenBuffersHelper(
[email protected]a93bb842010-02-16 23:03:47922 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:30923 glGenBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:47924 // TODO(gman): handle error
925 for (GLsizei ii = 0; ii < n; ++ii) {
926 decoder->CreateBufferInfo(ids[ii]);
927 }
[email protected]07f54fcc2009-12-22 02:46:30928}
929
930void GLGenFramebuffersHelper(
931 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
932 glGenFramebuffersEXT(n, ids);
933}
934
935void GLGenRenderbuffersHelper(
936 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
937 glGenRenderbuffersEXT(n, ids);
938}
939
940void GLGenTexturesHelper(
[email protected]a93bb842010-02-16 23:03:47941 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:30942 glGenTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:47943 // TODO(gman): handle error
944 for (GLsizei ii = 0; ii < n; ++ii) {
945 decoder->CreateTextureInfo(ids[ii]);
946 }
[email protected]07f54fcc2009-12-22 02:46:30947}
948
949void GLDeleteBuffersHelper(
950 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
951 glDeleteBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:47952 // TODO(gman): handle error
[email protected]07f54fcc2009-12-22 02:46:30953 for (GLsizei ii = 0; ii < n; ++ii) {
954 decoder->RemoveBufferInfo(ids[ii]);
955 }
956}
957
958void GLDeleteFramebuffersHelper(
959 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
960 glDeleteFramebuffersEXT(n, ids);
961}
962
963void GLDeleteRenderbuffersHelper(
964 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
965 glDeleteRenderbuffersEXT(n, ids);
966}
967
968void GLDeleteTexturesHelper(
[email protected]a93bb842010-02-16 23:03:47969 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:30970 glDeleteTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:47971 // TODO(gman): handle error
972 for (GLsizei ii = 0; ii < n; ++ii) {
973 decoder->RemoveTextureInfo(ids[ii]);
974 }
[email protected]07f54fcc2009-12-22 02:46:30975}
976
[email protected]43f28f832010-02-03 02:28:48977// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:32978
[email protected]eb54a562010-01-20 21:55:18979bool GLES2DecoderImpl::MakeCurrent() {
980#if defined(UNIT_TEST)
981 return true;
[email protected]b5f1aa032010-03-11 00:07:59982#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
983 return true;
[email protected]eb54a562010-01-20 21:55:18984#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:50985 if (::wglGetCurrentDC() == gl_device_context_ &&
[email protected]eb54a562010-01-20 21:55:18986 ::wglGetCurrentContext() == gl_context_) {
987 return true;
988 }
[email protected]246a70452010-03-05 21:53:50989 if (!::wglMakeCurrent(gl_device_context_, gl_context_)) {
[email protected]eb54a562010-01-20 21:55:18990 DLOG(ERROR) << "Unable to make gl context current.";
991 return false;
992 }
993 return true;
994#elif defined(OS_LINUX)
995 return window()->MakeCurrent();
[email protected]43f28f832010-02-03 02:28:48996#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:35997 return surface_.MakeCurrent();
[email protected]eb54a562010-01-20 21:55:18998#else
999 NOTREACHED();
1000 return false;
1001#endif
1002}
1003
[email protected]8a837bb2010-01-05 00:21:241004uint32 GLES2DecoderImpl::GetServiceIdForTesting(uint32 client_id) {
1005#if defined(UNIT_TEST)
1006 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501007 bool result = id_manager()->GetServiceId(client_id, &service_id);
[email protected]8a837bb2010-01-05 00:21:241008 return result ? service_id : 0u;
1009#else
1010 DCHECK(false);
1011 return 0u;
1012#endif
1013}
1014
1015bool GLES2DecoderImpl::ValidateIdsAreUnused(
1016 GLsizei n, const GLuint* client_ids) {
1017 for (GLsizei ii = 0; ii < n; ++ii) {
1018 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501019 if (id_manager()->GetServiceId(client_ids[ii], &service_id)) {
[email protected]8a837bb2010-01-05 00:21:241020 return false;
1021 }
1022 }
1023 return true;
1024}
1025
[email protected]07f54fcc2009-12-22 02:46:301026bool GLES2DecoderImpl::RegisterObjects(
1027 GLsizei n, const GLuint* client_ids, const GLuint* service_ids) {
1028 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501029 if (!id_manager()->AddMapping(client_ids[ii], service_ids[ii])) {
[email protected]8a837bb2010-01-05 00:21:241030 NOTREACHED();
1031 return false;
[email protected]07f54fcc2009-12-22 02:46:301032 }
1033 }
1034 return true;
1035}
1036
1037void GLES2DecoderImpl::UnregisterObjects(
1038 GLsizei n, const GLuint* client_ids, GLuint* service_ids) {
[email protected]07f54fcc2009-12-22 02:46:301039 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501040 if (id_manager()->GetServiceId(client_ids[ii], &service_ids[ii])) {
1041 id_manager()->RemoveMapping(client_ids[ii], service_ids[ii]);
[email protected]07f54fcc2009-12-22 02:46:301042 } else {
1043 service_ids[ii] = 0;
1044 }
1045 }
1046}
1047
[email protected]96449d2c2009-11-25 00:01:321048bool GLES2DecoderImpl::InitPlatformSpecific() {
[email protected]69d80ae2009-12-23 08:57:421049#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591050#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:421051#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:501052 // Do one-off initialization.
1053 static bool success = InitializeOneOff(anti_aliased_);
1054 if (!success)
[email protected]96449d2c2009-11-25 00:01:321055 return false;
[email protected]246a70452010-03-05 21:53:501056
1057 if (hwnd()) {
1058 // The GL context will render to this window.
1059 gl_device_context_ = ::GetDC(hwnd());
1060
1061 if (!::SetPixelFormat(gl_device_context_,
1062 pixel_format_,
1063 &kPixelFormatDescriptor)) {
1064 DLOG(ERROR) << "Unable to set the pixel format for GL context.";
1065 DestroyPlatformSpecific();
1066 return false;
1067 }
1068 } else {
1069 // Create a device context compatible with the primary display.
1070 HDC display_device_context = ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
1071
1072 // Create a 1 x 1 pbuffer suitable for use with the device.
1073 const int kNoAttributes[] = { 0 };
1074 pbuffer_ = ::wglCreatePbufferARB(display_device_context,
1075 pixel_format_,
1076 1, 1,
1077 kNoAttributes);
1078 ::DeleteDC(display_device_context);
1079 if (!pbuffer_) {
1080 DLOG(ERROR) << "Unable to create pbuffer.";
1081 DestroyPlatformSpecific();
1082 return false;
1083 }
1084
1085 gl_device_context_ = ::wglGetPbufferDCARB(pbuffer_);
1086 if (!gl_device_context_) {
1087 DLOG(ERROR) << "Unable to get pbuffer device context.";
1088 DestroyPlatformSpecific();
1089 return false;
1090 }
[email protected]96449d2c2009-11-25 00:01:321091 }
1092
[email protected]246a70452010-03-05 21:53:501093 gl_context_ = ::wglCreateContext(gl_device_context_);
[email protected]96449d2c2009-11-25 00:01:321094 if (!gl_context_) {
1095 DLOG(ERROR) << "Failed to create GL context.";
[email protected]246a70452010-03-05 21:53:501096 DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:321097 return false;
1098 }
[email protected]96449d2c2009-11-25 00:01:321099#elif defined(OS_LINUX)
1100 DCHECK(window());
1101 if (!window()->Initialize())
1102 return false;
[email protected]43f28f832010-02-03 02:28:481103#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:351104 return surface_.Initialize();
[email protected]96449d2c2009-11-25 00:01:321105#endif
1106
1107 return true;
1108}
1109
1110bool GLES2DecoderImpl::InitGlew() {
[email protected]b5f1aa032010-03-11 00:07:591111#if !defined(UNIT_TEST) && !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]96449d2c2009-11-25 00:01:321112 DLOG(INFO) << "Initializing GL and GLEW for GLES2Decoder.";
1113
1114 GLenum glew_error = glewInit();
1115 if (glew_error != GLEW_OK) {
1116 DLOG(ERROR) << "Unable to initialise GLEW : "
1117 << ::glewGetErrorString(glew_error);
1118 return false;
1119 }
1120
1121 // Check to see that we can use the OpenGL vertex attribute APIs
1122 // TODO(petersont): Return false if this check fails, but because some
1123 // Intel hardware does not support OpenGL 2.0, yet does support all of the
1124 // extensions we require, we only log an error. A future CL should change
1125 // this check to ensure that all of the extension strings we require are
1126 // present.
1127 if (!GLEW_VERSION_2_0) {
1128 DLOG(ERROR) << "GL drivers do not have OpenGL 2.0 functionality.";
1129 }
1130
1131 bool extensions_found = true;
1132 if (!GLEW_ARB_vertex_buffer_object) {
1133 // NOTE: Linux NVidia drivers claim to support OpenGL 2.0 when using
1134 // indirect rendering (e.g. remote X), but it is actually lying. The
1135 // ARB_vertex_buffer_object functions silently no-op (!) when using
1136 // indirect rendering, leading to crashes. Fortunately, in that case, the
1137 // driver claims to not support ARB_vertex_buffer_object, so fail in that
1138 // case.
1139 DLOG(ERROR) << "GL drivers do not support vertex buffer objects.";
1140 extensions_found = false;
1141 }
1142 if (!GLEW_EXT_framebuffer_object) {
1143 DLOG(ERROR) << "GL drivers do not support framebuffer objects.";
1144 extensions_found = false;
1145 }
1146 // Check for necessary extensions
1147 if (!GLEW_VERSION_2_0 && !GLEW_EXT_stencil_two_side) {
1148 DLOG(ERROR) << "Two sided stencil extension missing.";
1149 extensions_found = false;
1150 }
1151 if (!GLEW_VERSION_1_4 && !GLEW_EXT_blend_func_separate) {
1152 DLOG(ERROR) <<"Separate blend func extension missing.";
1153 extensions_found = false;
1154 }
1155 if (!GLEW_VERSION_2_0 && !GLEW_EXT_blend_equation_separate) {
1156 DLOG(ERROR) << "Separate blend function extension missing.";
1157 extensions_found = false;
1158 }
1159 if (!extensions_found)
1160 return false;
[email protected]69d80ae2009-12-23 08:57:421161#endif
[email protected]96449d2c2009-11-25 00:01:321162
1163 return true;
1164}
1165
[email protected]246a70452010-03-05 21:53:501166void GLES2DecoderImpl::DestroyPlatformSpecific() {
1167#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591168#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]246a70452010-03-05 21:53:501169#elif defined(OS_WIN)
1170 if (gl_context_) {
1171 ::wglDeleteContext(gl_context_);
1172 }
1173
1174 if (gl_device_context_) {
1175 if (hwnd())
1176 ::ReleaseDC(hwnd(), gl_device_context_);
1177 else
1178 ::wglReleasePbufferDCARB(pbuffer_, gl_device_context_);
1179
1180 gl_device_context_ = NULL;
1181 }
1182
1183 if (pbuffer_) {
1184 ::wglDestroyPbufferARB(pbuffer_);
1185 pbuffer_ = NULL;
1186 }
1187#endif
1188}
1189
[email protected]6098b712010-02-09 17:59:341190#if defined(OS_MACOSX)
[email protected]1aef98132010-02-23 18:00:071191
1192uint64 GLES2DecoderImpl::SetWindowSizeForIOSurface(int32 width, int32 height) {
[email protected]6098b712010-02-09 17:59:341193#if defined(UNIT_TEST)
1194 return 0;
[email protected]b5f1aa032010-03-11 00:07:591195#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1196 return 0;
[email protected]6098b712010-02-09 17:59:341197#else
[email protected]3d1e89d2010-03-10 20:01:351198 return surface_.SetSurfaceSize(width, height);
[email protected]6098b712010-02-09 17:59:341199#endif // !defined(UNIT_TEST)
[email protected]43f28f832010-02-03 02:28:481200}
[email protected]1aef98132010-02-23 18:00:071201
1202TransportDIB::Handle GLES2DecoderImpl::SetWindowSizeForTransportDIB(
1203 int32 width, int32 height) {
1204#if defined(UNIT_TEST)
1205 return TransportDIB::DefaultHandleValue();
[email protected]b5f1aa032010-03-11 00:07:591206#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1207 return TransportDIB::DefaultHandleValue();
[email protected]1aef98132010-02-23 18:00:071208#else
[email protected]3d1e89d2010-03-10 20:01:351209 return surface_.SetTransportDIBSize(width, height);
[email protected]1aef98132010-02-23 18:00:071210#endif // !defined(UNIT_TEST)
1211}
1212
1213void GLES2DecoderImpl::SetTransportDIBAllocAndFree(
1214 Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
1215 Callback1<TransportDIB::Id>::Type* deallocator) {
[email protected]3d1e89d2010-03-10 20:01:351216 surface_.SetTransportDIBAllocAndFree(allocator, deallocator);
[email protected]1aef98132010-02-23 18:00:071217}
[email protected]6098b712010-02-09 17:59:341218#endif // defined(OS_MACOSX)
[email protected]43f28f832010-02-03 02:28:481219
1220void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
1221 swap_buffers_callback_.reset(callback);
1222}
1223
[email protected]96449d2c2009-11-25 00:01:321224void GLES2DecoderImpl::Destroy() {
[email protected]69d80ae2009-12-23 08:57:421225#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591226#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:421227#elif defined(OS_LINUX)
[email protected]96449d2c2009-11-25 00:01:321228 DCHECK(window());
1229 window()->Destroy();
[email protected]43f28f832010-02-03 02:28:481230#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:351231 surface_.Destroy();
[email protected]96449d2c2009-11-25 00:01:321232#endif
[email protected]246a70452010-03-05 21:53:501233
1234 DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:321235}
1236
1237const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
1238 if (command_id > kStartPoint && command_id < kNumCommands) {
1239 return gles2::GetCommandName(static_cast<CommandId>(command_id));
1240 }
1241 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
1242}
1243
1244// Decode command with its arguments, and call the corresponding GL function.
1245// Note: args is a pointer to the command buffer. As such, it could be changed
1246// by a (malicious) client at any time, so if validation has to happen, it
1247// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:141248error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:321249 unsigned int command,
1250 unsigned int arg_count,
1251 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:141252 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191253 if (debug()) {
1254 // TODO(gman): Change output to something useful for NaCl.
[email protected]b9849abf2009-11-25 19:13:191255 printf("cmd: %s\n", GetCommandName(command));
1256 }
[email protected]96449d2c2009-11-25 00:01:321257 unsigned int command_index = command - kStartPoint - 1;
1258 if (command_index < arraysize(g_command_info)) {
1259 const CommandInfo& info = g_command_info[command_index];
1260 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
1261 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
1262 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:191263 uint32 immediate_data_size =
1264 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:321265 switch (command) {
1266 #define GLES2_CMD_OP(name) \
1267 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:191268 result = Handle ## name( \
1269 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321270 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:191271 break; \
[email protected]96449d2c2009-11-25 00:01:321272
1273 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:321274 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:381275 }
1276 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:301277 GLenum error;
1278 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:381279 // TODO(gman): Change output to something useful for NaCl.
[email protected]07f54fcc2009-12-22 02:46:301280 SetGLError(error);
[email protected]bf0985e2009-12-17 03:04:381281 printf("GL ERROR b4: %s\n", GetCommandName(command));
[email protected]b9849abf2009-11-25 19:13:191282 }
[email protected]96449d2c2009-11-25 00:01:321283 }
1284 } else {
[email protected]f7a64ee2010-02-01 22:24:141285 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:321286 }
[email protected]b9849abf2009-11-25 19:13:191287 } else {
1288 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:321289 }
[email protected]b9849abf2009-11-25 19:13:191290 return result;
[email protected]96449d2c2009-11-25 00:01:321291}
1292
[email protected]3916c97e2010-02-25 03:20:501293void GLES2DecoderImpl::RemoveBufferInfo(GLuint buffer_id) {
1294 buffer_manager()->RemoveBufferInfo(buffer_id);
1295 // TODO(gman): See if we can remove the rest of this function as
1296 // buffers are now reference counted and have a "IsDeleted" function.
1297 if (bound_array_buffer_ && bound_array_buffer_->buffer_id() == buffer_id) {
1298 bound_array_buffer_ = NULL;
1299 }
1300 if (bound_element_array_buffer_ &&
1301 bound_element_array_buffer_->buffer_id() == buffer_id) {
1302 bound_element_array_buffer_ = NULL;
1303 }
1304
1305 // go through VertexAttribInfo and update any info that references the buffer.
1306 for (GLuint ii = 0; ii < group_->max_vertex_attribs(); ++ii) {
1307 VertexAttribInfo& info = vertex_attrib_infos_[ii];
1308 if (info.buffer() && info.buffer()->buffer_id() == buffer_id) {
1309 info.ClearBuffer();
1310 }
1311 }
1312}
1313
[email protected]96449d2c2009-11-25 00:01:321314void GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
1315 // TODO(gman): verify client_id is unused.
1316 GLuint service_id = glCreateProgram();
1317 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501318 id_manager()->AddMapping(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:471319 CreateProgramInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321320 }
1321}
1322
1323void GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
1324 // TODO(gman): verify client_id is unused.
1325 GLuint service_id = glCreateShader(type);
1326 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501327 id_manager()->AddMapping(client_id, service_id);
[email protected]45bf5152010-02-12 00:11:311328 CreateShaderInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321329 }
1330}
1331
[email protected]86093972010-03-11 00:13:561332bool GLES2DecoderImpl::ValidateGLenumCompressedTextureInternalFormat(GLenum) {
1333 // TODO(gman): Add support for compressed texture formats.
1334 return false;
1335}
1336
[email protected]3916c97e2010-02-25 03:20:501337void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:451338 GLuint texture_index = texture_unit - GL_TEXTURE0;
1339 if (texture_index > group_->max_texture_units()) {
[email protected]3916c97e2010-02-25 03:20:501340 SetGLError(GL_INVALID_ENUM);
1341 return;
1342 }
[email protected]36cef8ce2010-03-16 07:34:451343 active_texture_unit_ = texture_index;
1344 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:501345}
1346
[email protected]96449d2c2009-11-25 00:01:321347void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:501348 BufferManager::BufferInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471349 if (buffer) {
[email protected]3916c97e2010-02-25 03:20:501350 info = GetBufferInfo(buffer);
[email protected]0c86dbf2010-03-05 08:14:111351 // Check the buffer exists
1352 // Check that we are not trying to bind it to a different target.
1353 if (!info || (info->target() != 0 && info->target() != target)) {
[email protected]a93bb842010-02-16 23:03:471354 SetGLError(GL_INVALID_OPERATION);
1355 return;
1356 }
[email protected]0c86dbf2010-03-05 08:14:111357 if (info->target() == 0) {
1358 info->set_target(target);
1359 }
[email protected]a93bb842010-02-16 23:03:471360 }
[email protected]96449d2c2009-11-25 00:01:321361 switch (target) {
1362 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501363 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321364 break;
1365 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501366 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321367 break;
1368 default:
[email protected]a93bb842010-02-16 23:03:471369 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:321370 break;
1371 }
1372 glBindBuffer(target, buffer);
1373}
1374
[email protected]86093972010-03-11 00:13:561375void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint framebuffer) {
1376 bound_framebuffer_ = framebuffer;
1377 glBindFramebufferEXT(target, framebuffer);
1378}
1379
1380void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint renderbuffer) {
1381 bound_renderbuffer_ = renderbuffer;
1382 glBindRenderbufferEXT(target, renderbuffer);
1383}
1384
[email protected]a93bb842010-02-16 23:03:471385void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:501386 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471387 if (texture) {
[email protected]3916c97e2010-02-25 03:20:501388 info = GetTextureInfo(texture);
1389 // Check the texture exists
1390 // Check that we are not trying to bind it to a different target.
[email protected]a93bb842010-02-16 23:03:471391 if (!info || (info->target() != 0 && info->target() != target)) {
1392 SetGLError(GL_INVALID_OPERATION);
1393 return;
1394 }
1395 if (info->target() == 0) {
[email protected]3916c97e2010-02-25 03:20:501396 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:471397 }
1398 }
1399 glBindTexture(target, texture);
[email protected]3916c97e2010-02-25 03:20:501400 TextureUnit& unit = texture_units_[active_texture_unit_];
1401 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:471402 switch (target) {
1403 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501404 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:471405 break;
1406 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:501407 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:471408 break;
1409 default:
1410 NOTREACHED(); // Validation should prevent us getting here.
1411 break;
1412 }
1413}
1414
[email protected]07f54fcc2009-12-22 02:46:301415void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501416 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301417 vertex_attrib_infos_[index].set_enabled(false);
[email protected]8a837bb2010-01-05 00:21:241418 glDisableVertexAttribArray(index);
[email protected]07f54fcc2009-12-22 02:46:301419 } else {
1420 SetGLError(GL_INVALID_VALUE);
1421 }
1422}
1423
1424void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501425 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301426 vertex_attrib_infos_[index].set_enabled(true);
1427 glEnableVertexAttribArray(index);
1428 } else {
1429 SetGLError(GL_INVALID_VALUE);
1430 }
1431}
1432
[email protected]a93bb842010-02-16 23:03:471433void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:501434 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1435 if (!info || !info->MarkMipmapsGenerated()) {
[email protected]a93bb842010-02-16 23:03:471436 SetGLError(GL_INVALID_OPERATION);
1437 return;
1438 }
1439 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:471440}
1441
[email protected]f7a64ee2010-02-01 22:24:141442error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:461443 uint32 immediate_data_size, const gles2::DeleteShader& c) {
1444 GLuint shader = c.shader;
[email protected]96449d2c2009-11-25 00:01:321445 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501446 if (!id_manager()->GetServiceId(shader, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:461447 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141448 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321449 }
[email protected]45bf5152010-02-12 00:11:311450 RemoveShaderInfo(service_id);
[email protected]07f54fcc2009-12-22 02:46:301451 glDeleteShader(service_id);
[email protected]3916c97e2010-02-25 03:20:501452 id_manager()->RemoveMapping(shader, service_id);
[email protected]f7a64ee2010-02-01 22:24:141453 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321454}
1455
[email protected]f7a64ee2010-02-01 22:24:141456error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:461457 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
1458 GLuint program = c.program;
[email protected]96449d2c2009-11-25 00:01:321459 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501460 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:461461 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141462 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321463 }
[email protected]1d32bc82010-01-13 22:06:461464 RemoveProgramInfo(service_id);
[email protected]ba3176a2009-12-16 18:19:461465 glDeleteProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:501466 id_manager()->RemoveMapping(program, service_id);
[email protected]f7a64ee2010-02-01 22:24:141467 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321468}
1469
[email protected]07f54fcc2009-12-22 02:46:301470void GLES2DecoderImpl::DoDrawArrays(
1471 GLenum mode, GLint first, GLsizei count) {
1472 if (IsDrawValid(first + count - 1)) {
[email protected]3916c97e2010-02-25 03:20:501473 bool has_non_renderable_textures;
1474 SetBlackTextureForNonRenderableTextures(&has_non_renderable_textures);
[email protected]07f54fcc2009-12-22 02:46:301475 glDrawArrays(mode, first, count);
[email protected]3916c97e2010-02-25 03:20:501476 if (has_non_renderable_textures) {
1477 RestoreStateForNonRenderableTextures();
1478 }
[email protected]07f54fcc2009-12-22 02:46:301479 }
1480}
1481
[email protected]36cef8ce2010-03-16 07:34:451482void GLES2DecoderImpl::DoFramebufferRenderbuffer(
1483 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1484 GLuint renderbuffer) {
1485 if (bound_framebuffer_ == 0) {
1486 SetGLError(GL_INVALID_OPERATION);
1487 return;
1488 }
1489 glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget,
1490 renderbuffer);
1491}
1492
1493GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
1494 if (bound_framebuffer_ == 0) {
1495 return GL_FRAMEBUFFER_COMPLETE;
1496 }
1497 return glCheckFramebufferStatusEXT(target);
1498}
1499
1500void GLES2DecoderImpl::DoFramebufferTexture2D(
1501 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1502 GLint level) {
1503 if (bound_framebuffer_ == 0) {
1504 SetGLError(GL_INVALID_OPERATION);
1505 return;
1506 }
1507 glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
1508}
1509
1510void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
1511 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
1512 if (bound_framebuffer_ == 0) {
1513 SetGLError(GL_INVALID_OPERATION);
1514 return;
1515 }
1516 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
1517}
1518
1519void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
1520 GLenum target, GLenum pname, GLint* params) {
1521 if (bound_renderbuffer_ == 0) {
1522 SetGLError(GL_INVALID_OPERATION);
1523 return;
1524 }
1525 glGetRenderbufferParameterivEXT(target, pname, params);
1526}
1527
1528void GLES2DecoderImpl::DoRenderbufferStorage(
1529 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
1530 if (bound_renderbuffer_ == 0) {
1531 SetGLError(GL_INVALID_OPERATION);
1532 return;
1533 }
1534 glRenderbufferStorageEXT(target, internalformat, width, height);
1535}
1536
[email protected]07f54fcc2009-12-22 02:46:301537void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]a93bb842010-02-16 23:03:471538 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
1539 if (!info) {
1540 SetGLError(GL_INVALID_OPERATION);
1541 return;
1542 }
[email protected]07f54fcc2009-12-22 02:46:301543 CopyRealGLErrorsToWrapper();
1544 glLinkProgram(program);
1545 GLenum error = glGetError();
1546 if (error != GL_NO_ERROR) {
1547 RemoveProgramInfo(program);
1548 SetGLError(error);
1549 } else {
[email protected]a93bb842010-02-16 23:03:471550 info->Update();
[email protected]07f54fcc2009-12-22 02:46:301551 }
1552};
1553
[email protected]96449d2c2009-11-25 00:01:321554void GLES2DecoderImpl::DoSwapBuffers() {
[email protected]69d80ae2009-12-23 08:57:421555#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591556#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:421557#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:501558 ::SwapBuffers(gl_device_context_);
[email protected]69d80ae2009-12-23 08:57:421559#elif defined(OS_LINUX)
[email protected]96449d2c2009-11-25 00:01:321560 DCHECK(window());
1561 window()->SwapBuffers();
[email protected]43f28f832010-02-03 02:28:481562#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:351563 // TODO(kbr): Need to property hook up and track the OpenGL state and hook
1564 // up the notion of the currently bound FBO.
1565 surface_.SwapBuffers();
[email protected]96449d2c2009-11-25 00:01:321566#endif
[email protected]43f28f832010-02-03 02:28:481567 if (swap_buffers_callback_.get()) {
1568 swap_buffers_callback_->Run();
1569 }
[email protected]96449d2c2009-11-25 00:01:321570}
1571
[email protected]3916c97e2010-02-25 03:20:501572void GLES2DecoderImpl::DoTexParameterf(
1573 GLenum target, GLenum pname, GLfloat param) {
1574 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:301575 if (!info) {
[email protected]3916c97e2010-02-25 03:20:501576 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:301577 } else {
[email protected]3916c97e2010-02-25 03:20:501578 info->SetParameter(pname, static_cast<GLint>(param));
1579 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:301580 }
1581}
1582
[email protected]3916c97e2010-02-25 03:20:501583void GLES2DecoderImpl::DoTexParameteri(
1584 GLenum target, GLenum pname, GLint param) {
1585 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1586 if (!info) {
1587 SetGLError(GL_INVALID_VALUE);
1588 } else {
1589 info->SetParameter(pname, param);
1590 glTexParameteri(target, pname, param);
1591 }
1592}
1593
1594void GLES2DecoderImpl::DoTexParameterfv(
1595 GLenum target, GLenum pname, const GLfloat* params) {
1596 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1597 if (!info) {
1598 SetGLError(GL_INVALID_VALUE);
1599 } else {
1600 info->SetParameter(pname, *reinterpret_cast<const GLint*>(params));
1601 glTexParameterfv(target, pname, params);
1602 }
1603}
1604
1605void GLES2DecoderImpl::DoTexParameteriv(
1606 GLenum target, GLenum pname, const GLint* params) {
1607 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1608 if (!info) {
1609 SetGLError(GL_INVALID_VALUE);
1610 } else {
1611 info->SetParameter(pname, *params);
1612 glTexParameteriv(target, pname, params);
1613 }
1614}
1615
1616void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
1617 if (!current_program_ || current_program_->IsDeleted()) {
1618 // The program does not exist.
1619 SetGLError(GL_INVALID_OPERATION);
1620 return;
1621 }
1622 current_program_->SetSamplers(location, 1, &v0);
1623 glUniform1i(location, v0);
1624}
1625
1626void GLES2DecoderImpl::DoUniform1iv(
1627 GLint location, GLsizei count, const GLint *value) {
1628 if (!current_program_ || current_program_->IsDeleted()) {
1629 // The program does not exist.
1630 SetGLError(GL_INVALID_OPERATION);
1631 return;
1632 }
1633 current_program_->SetSamplers(location, count, value);
1634 glUniform1iv(location, count, value);
1635}
1636
1637void GLES2DecoderImpl::DoUseProgram(GLuint program) {
1638 ProgramManager::ProgramInfo* info = NULL;
1639 if (program) {
1640 info = GetProgramInfo(program);
1641 if (!info) {
1642 // Program was not linked successfully. (ie, glLinkProgram)
1643 SetGLError(GL_INVALID_OPERATION);
1644 return;
1645 }
1646 }
1647 current_program_ = info;
1648 glUseProgram(program);
1649}
1650
[email protected]96449d2c2009-11-25 00:01:321651GLenum GLES2DecoderImpl::GetGLError() {
1652 // Check the GL error first, then our wrapped error.
1653 GLenum error = glGetError();
1654 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:371655 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:321656 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:291657 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:321658 break;
1659 }
1660 }
1661 }
1662
1663 if (error != GL_NO_ERROR) {
1664 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:291665 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:321666 }
1667 return error;
1668}
1669
1670void GLES2DecoderImpl::SetGLError(GLenum error) {
[email protected]ddd968b82010-03-02 00:44:291671 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:321672}
1673
[email protected]07f54fcc2009-12-22 02:46:301674void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
1675 GLenum error;
1676 while ((error = glGetError()) != GL_NO_ERROR) {
1677 SetGLError(error);
1678 }
1679}
1680
[email protected]07f54fcc2009-12-22 02:46:301681bool GLES2DecoderImpl::VertexAttribInfo::CanAccess(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501682 if (!enabled_) {
1683 return true;
1684 }
1685
1686 if (!buffer_ || buffer_->IsDeleted()) {
1687 return false;
1688 }
1689
1690 // The number of elements that can be accessed.
1691 GLsizeiptr buffer_size = buffer_->size();
1692 if (offset_ > buffer_size || real_stride_ == 0) {
1693 return false;
1694 }
1695
1696 uint32 usable_size = buffer_size - offset_;
1697 GLuint num_elements = usable_size / real_stride_ +
1698 ((usable_size % real_stride_) >=
1699 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
1700 return index < num_elements;
1701}
1702
1703void GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures(
1704 bool* has_non_renderable_textures) {
1705 DCHECK(has_non_renderable_textures);
1706 DCHECK(current_program_);
1707 DCHECK(!current_program_->IsDeleted());
1708 *has_non_renderable_textures = false;
1709 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
1710 current_program_->sampler_indices();
1711 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
1712 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
1713 current_program_->GetUniformInfo(sampler_indices[ii]);
1714 DCHECK(uniform_info);
1715 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
1716 GLuint texture_unit_index = uniform_info->texture_units[jj];
1717 if (texture_unit_index < group_->max_texture_units()) {
1718 TextureUnit& texture_unit = texture_units_[texture_unit_index];
1719 TextureManager::TextureInfo* texture_info =
1720 uniform_info->type == GL_SAMPLER_2D ?
1721 texture_unit.bound_texture_2d :
1722 texture_unit.bound_texture_cube_map;
1723 if (!texture_info || !texture_info->CanRender()) {
1724 *has_non_renderable_textures = true;
1725 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
1726 glBindTexture(
1727 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
1728 GL_TEXTURE_CUBE_MAP,
1729 uniform_info->type == GL_SAMPLER_2D ? black_2d_texture_id_ :
1730 black_cube_texture_id_);
1731 }
1732 }
1733 // else: should this be an error?
1734 }
1735 }
1736}
1737
1738void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
1739 DCHECK(current_program_);
1740 DCHECK(!current_program_->IsDeleted());
1741 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
1742 current_program_->sampler_indices();
1743 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
1744 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
1745 current_program_->GetUniformInfo(sampler_indices[ii]);
1746 DCHECK(uniform_info);
1747 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
1748 GLuint texture_unit_index = uniform_info->texture_units[jj];
1749 if (texture_unit_index < group_->max_texture_units()) {
1750 TextureUnit& texture_unit = texture_units_[texture_unit_index];
1751 TextureManager::TextureInfo* texture_info =
1752 uniform_info->type == GL_SAMPLER_2D ?
1753 texture_unit.bound_texture_2d :
1754 texture_unit.bound_texture_cube_map;
1755 if (!texture_info || !texture_info->CanRender()) {
1756 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
1757 // Get the texture info that was previously bound here.
1758 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
1759 texture_unit.bound_texture_2d :
1760 texture_unit.bound_texture_cube_map;
1761 glBindTexture(texture_unit.bind_target,
1762 texture_info ? texture_info->texture_id() : 0);
1763 }
1764 }
1765 }
1766 }
1767 // Set the active texture back to whatever the user had it as.
1768 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:301769}
1770
1771bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]3916c97e2010-02-25 03:20:501772 if (!current_program_ || current_program_->IsDeleted()) {
1773 // The program does not exist.
1774 // But GL says no ERROR.
1775 return false;
1776 }
1777 // Validate that all attribs current program needs are setup correctly.
1778 const ProgramManager::ProgramInfo::AttribInfoVector& infos =
1779 current_program_->GetAttribInfos();
1780 for (size_t ii = 0; ii < infos.size(); ++ii) {
1781 GLint location = infos[ii].location;
1782 if (location < 0) {
1783 return false;
1784 }
1785 DCHECK_LT(static_cast<GLuint>(location), group_->max_vertex_attribs());
1786 if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:461787 SetGLError(GL_INVALID_OPERATION);
1788 return false;
1789 }
[email protected]07f54fcc2009-12-22 02:46:301790 }
[email protected]3916c97e2010-02-25 03:20:501791 return true;
[email protected]07f54fcc2009-12-22 02:46:301792};
1793
[email protected]f7a64ee2010-02-01 22:24:141794error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:191795 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:501796 if (!bound_element_array_buffer_ ||
1797 bound_element_array_buffer_->IsDeleted()) {
1798 SetGLError(GL_INVALID_OPERATION);
1799 } else {
[email protected]96449d2c2009-11-25 00:01:321800 GLenum mode = c.mode;
1801 GLsizei count = c.count;
1802 GLenum type = c.type;
[email protected]1d32bc82010-01-13 22:06:461803 int32 offset = c.index_offset;
[email protected]a76b0052010-03-05 00:33:181804 if (count < 0 || offset < 0) {
[email protected]d2cf0a2d2010-02-25 21:36:121805 SetGLError(GL_INVALID_VALUE);
1806 } else if (!ValidateGLenumDrawMode(mode) ||
1807 !ValidateGLenumIndexType(type)) {
[email protected]1d32bc82010-01-13 22:06:461808 SetGLError(GL_INVALID_ENUM);
[email protected]ba3176a2009-12-16 18:19:461809 } else {
[email protected]0c86dbf2010-03-05 08:14:111810 GLuint max_vertex_accessed;
1811 if (!bound_element_array_buffer_->GetMaxValueForRange(
1812 offset, count, type, &max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:461813 SetGLError(GL_INVALID_OPERATION);
1814 } else {
[email protected]0c86dbf2010-03-05 08:14:111815 if (IsDrawValid(max_vertex_accessed)) {
1816 bool has_non_renderable_textures;
1817 SetBlackTextureForNonRenderableTextures(
1818 &has_non_renderable_textures);
[email protected]3916c97e2010-02-25 03:20:501819 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]0c86dbf2010-03-05 08:14:111820 glDrawElements(mode, count, type, indices);
1821 if (has_non_renderable_textures) {
1822 RestoreStateForNonRenderableTextures();
[email protected]1d32bc82010-01-13 22:06:461823 }
1824 }
[email protected]07f54fcc2009-12-22 02:46:301825 }
[email protected]ba3176a2009-12-16 18:19:461826 }
[email protected]96449d2c2009-11-25 00:01:321827 }
[email protected]f7a64ee2010-02-01 22:24:141828 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321829}
1830
[email protected]96449d2c2009-11-25 00:01:321831// Calls glShaderSource for the various versions of the ShaderSource command.
1832// Assumes that data / data_size points to a piece of memory that is in range
1833// of whatever context it came from (shared memory, immediate memory, bucket
1834// memory.)
[email protected]45bf5152010-02-12 00:11:311835error::Error GLES2DecoderImpl::ShaderSourceHelper(
1836 GLuint shader, const char* data, uint32 data_size) {
1837 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
1838 if (!info) {
1839 SetGLError(GL_INVALID_OPERATION);
1840 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321841 }
[email protected]45bf5152010-02-12 00:11:311842 // Note: We don't actually call glShaderSource here. We wait until
1843 // the call to glCompileShader.
1844 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:141845 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321846}
1847
[email protected]f7a64ee2010-02-01 22:24:141848error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:191849 uint32 immediate_data_size, const gles2::ShaderSource& c) {
1850 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:501851 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:191852 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141853 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191854 }
[email protected]96449d2c2009-11-25 00:01:321855 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:311856 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:321857 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:461858 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:141859 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:321860 }
[email protected]45bf5152010-02-12 00:11:311861 return ShaderSourceHelper(shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:321862}
1863
[email protected]f7a64ee2010-02-01 22:24:141864error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:191865 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
1866 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:501867 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:191868 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141869 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191870 }
[email protected]96449d2c2009-11-25 00:01:321871 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:311872 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:301873 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:461874 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:141875 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:321876 }
[email protected]45bf5152010-02-12 00:11:311877 return ShaderSourceHelper(shader, data, data_size);
1878}
1879
1880void GLES2DecoderImpl::DoCompileShader(GLuint shader) {
1881 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
1882 if (!info) {
1883 SetGLError(GL_INVALID_OPERATION);
1884 return;
1885 }
1886 // TODO(gman): Run shader through compiler that converts GL ES 2.0 shader
1887 // to DesktopGL shader and pass that to glShaderSource and then
1888 // glCompileShader.
1889 const char* ptr = info->source().c_str();
1890 glShaderSource(shader, 1, &ptr, NULL);
1891 glCompileShader(shader);
1892};
1893
[email protected]ddd968b82010-03-02 00:44:291894void GLES2DecoderImpl::DoGetShaderiv(
1895 GLuint shader, GLenum pname, GLint* params) {
1896 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
1897 if (!info) {
1898 SetGLError(GL_INVALID_OPERATION);
1899 return;
1900 }
1901 if (pname == GL_SHADER_SOURCE_LENGTH) {
1902 *params = info->source().size();
1903 } else {
1904 glGetShaderiv(shader, pname, params);
1905 }
1906}
1907
[email protected]45bf5152010-02-12 00:11:311908void GLES2DecoderImpl::DoGetShaderSource(
1909 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst) {
1910 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
1911 if (!info) {
1912 SetGLError(GL_INVALID_OPERATION);
1913 return;
1914 }
[email protected]a76b0052010-03-05 00:33:181915 // bufsize is set by the service side code and should always be positive.
1916 DCHECK_GT(bufsize, 0);
[email protected]45bf5152010-02-12 00:11:311917 const std::string& source = info->source();
1918 GLsizei size = std::min(bufsize - 1, static_cast<GLsizei>(source.size()));
1919 if (length) {
1920 *length = size;
1921 }
1922 memcpy(dst, source.c_str(), size);
1923 dst[size] = '\0';
[email protected]96449d2c2009-11-25 00:01:321924}
1925
[email protected]f7a64ee2010-02-01 22:24:141926error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:191927 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]3916c97e2010-02-25 03:20:501928 if (bound_array_buffer_ && !bound_array_buffer_->IsDeleted()) {
[email protected]96449d2c2009-11-25 00:01:321929 GLuint indx = c.indx;
1930 GLint size = c.size;
1931 GLenum type = c.type;
1932 GLboolean normalized = c.normalized;
1933 GLsizei stride = c.stride;
[email protected]07f54fcc2009-12-22 02:46:301934 GLsizei offset = c.offset;
1935 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]ba3176a2009-12-16 18:19:461936 if (!ValidateGLenumVertexAttribType(type) ||
[email protected]d2cf0a2d2010-02-25 21:36:121937 !ValidateGLintVertexAttribSize(size)) {
1938 SetGLError(GL_INVALID_ENUM);
1939 return error::kNoError;
1940 }
1941 if (indx >= group_->max_vertex_attribs() ||
1942 stride < 0 ||
1943 offset < 0) {
[email protected]ba3176a2009-12-16 18:19:461944 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141945 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321946 }
[email protected]3916c97e2010-02-25 03:20:501947 GLsizei component_size =
1948 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]07f54fcc2009-12-22 02:46:301949 GLsizei real_stride = stride != 0 ? stride : component_size * size;
1950 if (offset % component_size > 0) {
1951 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141952 return error::kNoError;
[email protected]07f54fcc2009-12-22 02:46:301953 }
1954 vertex_attrib_infos_[indx].SetInfo(
1955 bound_array_buffer_,
[email protected]07f54fcc2009-12-22 02:46:301956 size,
1957 type,
1958 real_stride,
1959 offset);
[email protected]96449d2c2009-11-25 00:01:321960 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
1961 } else {
1962 SetGLError(GL_INVALID_VALUE);
1963 }
[email protected]f7a64ee2010-02-01 22:24:141964 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321965}
1966
[email protected]f7a64ee2010-02-01 22:24:141967error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:191968 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:311969 GLint x = c.x;
1970 GLint y = c.y;
1971 GLsizei width = c.width;
1972 GLsizei height = c.height;
1973 GLenum format = c.format;
1974 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:561975 if (width < 0 || height < 0) {
1976 SetGLError(GL_INVALID_VALUE);
1977 return error::kNoError;
1978 }
[email protected]a51788e2010-02-24 21:54:251979 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:181980 uint32 pixels_size;
1981 if (!GLES2Util::ComputeImageDataSize(
1982 width, height, format, type, pack_alignment_, &pixels_size)) {
1983 return error::kOutOfBounds;
1984 }
[email protected]612d2f82009-12-08 20:49:311985 void* pixels = GetSharedMemoryAs<void*>(
1986 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:251987 Result* result = GetSharedMemoryAs<Result*>(
1988 c.result_shm_id, c.result_shm_offset, sizeof(*result));
1989 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:141990 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:461991 }
[email protected]a51788e2010-02-24 21:54:251992
[email protected]ba3176a2009-12-16 18:19:461993 if (!ValidateGLenumReadPixelFormat(format) ||
1994 !ValidateGLenumPixelType(type)) {
[email protected]d2cf0a2d2010-02-25 21:36:121995 SetGLError(GL_INVALID_ENUM);
1996 return error::kNoError;
1997 }
[email protected]57f223832010-03-19 01:57:561998 if (width == 0 || height == 0) {
1999 return error::kNoError;
2000 }
2001
2002 CopyRealGLErrorsToWrapper();
2003
2004 // Get the size of the current fbo or backbuffer.
2005 GLsizei max_width = 0;
2006 GLsizei max_height = 0;
2007 if (bound_framebuffer_ != 0) {
2008 // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
2009 // stencil.
2010 GLint fb_type = 0;
2011 glGetFramebufferAttachmentParameterivEXT(
2012 GL_FRAMEBUFFER,
2013 GL_COLOR_ATTACHMENT0,
2014 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
2015 &fb_type);
2016 switch (fb_type) {
2017 case GL_RENDERBUFFER:
2018 {
2019 GLint renderbuffer_id = 0;
2020 glGetFramebufferAttachmentParameterivEXT(
2021 GL_FRAMEBUFFER,
2022 GL_COLOR_ATTACHMENT0,
2023 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
2024 &renderbuffer_id);
2025 if (renderbuffer_id != 0) {
2026 glGetRenderbufferParameterivEXT(
2027 GL_RENDERBUFFER,
2028 GL_RENDERBUFFER_WIDTH,
2029 &max_width);
2030 glGetRenderbufferParameterivEXT(
2031 GL_RENDERBUFFER,
2032 GL_RENDERBUFFER_HEIGHT,
2033 &max_height);
2034 }
2035 break;
2036 }
2037 case GL_TEXTURE:
2038 {
2039 GLint texture_id = 0;
2040 glGetFramebufferAttachmentParameterivEXT(
2041 GL_FRAMEBUFFER,
2042 GL_COLOR_ATTACHMENT0,
2043 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
2044 &texture_id);
2045 if (texture_id != 0) {
2046 TextureManager::TextureInfo* texture_info =
2047 GetTextureInfo(texture_id);
2048 if (texture_info) {
2049 GLint level = 0;
2050 GLint face = 0;
2051 glGetFramebufferAttachmentParameterivEXT(
2052 GL_FRAMEBUFFER,
2053 GL_COLOR_ATTACHMENT0,
2054 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
2055 &level);
2056 glGetFramebufferAttachmentParameterivEXT(
2057 GL_FRAMEBUFFER,
2058 GL_COLOR_ATTACHMENT0,
2059 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
2060 &face);
2061 texture_info->GetLevelSize(
2062 face ? face : GL_TEXTURE_2D, level, &max_width, &max_height);
2063 }
2064 }
2065 break;
2066 }
2067 default:
2068 // unknown so assume max_width = 0.
2069 break;
2070 }
2071 } else {
2072 // TODO(gman): Get these values from the proper place.
2073 max_width = 300;
2074 max_height = 150;
2075 }
2076
2077 GLint max_x;
2078 GLint max_y;
2079 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]ba3176a2009-12-16 18:19:462080 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142081 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:312082 }
[email protected]57f223832010-03-19 01:57:562083
2084 if (x < 0 || y < 0 || max_x > max_width || max_y > max_height) {
2085 // The user requested an out of range area. Get the results 1 line
2086 // at a time.
2087 uint32 temp_size;
2088 if (!GLES2Util::ComputeImageDataSize(
2089 width, 1, format, type, pack_alignment_, &temp_size)) {
2090 SetGLError(GL_INVALID_VALUE);
2091 return error::kNoError;
2092 }
2093 GLsizei unpadded_row_size = temp_size;
2094 if (!GLES2Util::ComputeImageDataSize(
2095 width, 2, format, type, pack_alignment_, &temp_size)) {
2096 SetGLError(GL_INVALID_VALUE);
2097 return error::kNoError;
2098 }
2099 GLsizei padded_row_size = temp_size - unpadded_row_size;
2100 if (padded_row_size < 0 || unpadded_row_size < 0) {
2101 SetGLError(GL_INVALID_VALUE);
2102 return error::kNoError;
2103 }
2104
2105 GLint dest_x_offset = std::max(-x, 0);
2106 uint32 dest_row_offset;
2107 if (!GLES2Util::ComputeImageDataSize(
2108 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
2109 SetGLError(GL_INVALID_VALUE);
2110 return error::kNoError;
2111 }
2112
2113 // Copy each row into the larger dest rect.
2114 int8* dst = static_cast<int8*>(pixels);
2115 GLint read_x = std::max(0, x);
2116 GLint read_end_x = std::max(0, std::min(max_width, max_x));
2117 GLint read_width = read_end_x - read_x;
2118 for (GLint yy = 0; yy < height; ++yy) {
2119 GLint ry = y + yy;
2120
2121 // Clear the row.
2122 memset(dst, 0, unpadded_row_size);
2123
2124 // If the row is in range, copy it.
2125 if (ry >= 0 && ry < max_height && read_width > 0) {
2126 glReadPixels(
2127 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
2128 }
2129 dst += padded_row_size;
2130 }
2131 } else {
2132 glReadPixels(x, y, width, height, format, type, pixels);
2133 }
[email protected]a51788e2010-02-24 21:54:252134 GLenum error = glGetError();
2135 if (error == GL_NO_ERROR) {
2136 *result = true;
2137 } else {
2138 SetGLError(error);
2139 }
[email protected]f7a64ee2010-02-01 22:24:142140 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322141}
2142
[email protected]f7a64ee2010-02-01 22:24:142143error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:192144 uint32 immediate_data_size, const gles2::PixelStorei& c) {
2145 GLenum pname = c.pname;
2146 GLenum param = c.param;
[email protected]d2cf0a2d2010-02-25 21:36:122147 if (!ValidateGLenumPixelStore(pname)) {
2148 SetGLError(GL_INVALID_ENUM);
2149 return error::kNoError;
2150 }
2151 if (!ValidateGLintPixelStoreAlignment(param)) {
[email protected]ba3176a2009-12-16 18:19:462152 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142153 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192154 }
2155 glPixelStorei(pname, param);
2156 switch (pname) {
2157 case GL_PACK_ALIGNMENT:
2158 pack_alignment_ = param;
2159 break;
2160 case GL_UNPACK_ALIGNMENT:
2161 unpack_alignment_ = param;
2162 break;
2163 default:
2164 // Validation should have prevented us from getting here.
2165 DCHECK(false);
2166 break;
2167 }
[email protected]f7a64ee2010-02-01 22:24:142168 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192169}
2170
[email protected]f7a64ee2010-02-01 22:24:142171error::Error GLES2DecoderImpl::HandleGetAttribLocation(
[email protected]b9849abf2009-11-25 19:13:192172 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
2173 GLuint program;
[email protected]3916c97e2010-02-25 03:20:502174 if (!id_manager()->GetServiceId(c.program, &program)) {
[email protected]b9849abf2009-11-25 19:13:192175 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142176 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192177 }
[email protected]0bfd9882010-02-05 23:02:252178 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2179 if (!info) {
2180 // Program was not linked successfully. (ie, glLinkProgram)
2181 SetGLError(GL_INVALID_OPERATION);
2182 return error::kNoError;
2183 }
[email protected]b9849abf2009-11-25 19:13:192184 uint32 name_size = c.data_size;
2185 const char* name = GetSharedMemoryAs<const char*>(
2186 c.name_shm_id, c.name_shm_offset, name_size);
2187 GLint* location = GetSharedMemoryAs<GLint*>(
2188 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
2189 if (!location || !name) {
[email protected]f7a64ee2010-02-01 22:24:142190 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192191 }
2192 String name_str(name, name_size);
[email protected]0bfd9882010-02-05 23:02:252193 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142194 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192195}
2196
[email protected]f7a64ee2010-02-01 22:24:142197error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192198 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
2199 GLuint program;
[email protected]3916c97e2010-02-25 03:20:502200 if (!id_manager()->GetServiceId(c.program, &program)) {
[email protected]b9849abf2009-11-25 19:13:192201 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142202 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192203 }
[email protected]0bfd9882010-02-05 23:02:252204 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2205 if (!info) {
2206 // Program was not linked successfully. (ie, glLinkProgram)
2207 SetGLError(GL_INVALID_OPERATION);
2208 return error::kNoError;
2209 }
[email protected]b9849abf2009-11-25 19:13:192210 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:302211 const char* name = GetImmediateDataAs<const char*>(
2212 c, name_size, immediate_data_size);
[email protected]b9849abf2009-11-25 19:13:192213 GLint* location = GetSharedMemoryAs<GLint*>(
2214 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
2215 if (!location || !name) {
[email protected]f7a64ee2010-02-01 22:24:142216 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192217 }
2218 String name_str(name, name_size);
[email protected]0bfd9882010-02-05 23:02:252219 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142220 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192221}
2222
[email protected]f7a64ee2010-02-01 22:24:142223error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:192224 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
2225 GLuint program;
[email protected]3916c97e2010-02-25 03:20:502226 if (!id_manager()->GetServiceId(c.program, &program)) {
[email protected]b9849abf2009-11-25 19:13:192227 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142228 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192229 }
[email protected]0bfd9882010-02-05 23:02:252230 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2231 if (!info) {
2232 // Program was not linked successfully. (ie, glLinkProgram)
2233 SetGLError(GL_INVALID_OPERATION);
2234 return error::kNoError;
2235 }
[email protected]b9849abf2009-11-25 19:13:192236 uint32 name_size = c.data_size;
2237 const char* name = GetSharedMemoryAs<const char*>(
2238 c.name_shm_id, c.name_shm_offset, name_size);
2239 GLint* location = GetSharedMemoryAs<GLint*>(
2240 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
2241 if (!location || !name) {
[email protected]f7a64ee2010-02-01 22:24:142242 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192243 }
2244 String name_str(name, name_size);
[email protected]0bfd9882010-02-05 23:02:252245 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142246 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192247}
2248
[email protected]f7a64ee2010-02-01 22:24:142249error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192250 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
2251 GLuint program;
[email protected]3916c97e2010-02-25 03:20:502252 if (!id_manager()->GetServiceId(c.program, &program)) {
[email protected]b9849abf2009-11-25 19:13:192253 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142254 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192255 }
[email protected]0bfd9882010-02-05 23:02:252256 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2257 if (!info) {
2258 // Program was not linked successfully. (ie, glLinkProgram)
2259 SetGLError(GL_INVALID_OPERATION);
2260 return error::kNoError;
2261 }
[email protected]b9849abf2009-11-25 19:13:192262 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:302263 const char* name = GetImmediateDataAs<const char*>(
2264 c, name_size, immediate_data_size);
[email protected]b9849abf2009-11-25 19:13:192265 GLint* location = GetSharedMemoryAs<GLint*>(
2266 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
2267 if (!location || !name) {
[email protected]f7a64ee2010-02-01 22:24:142268 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192269 }
2270 String name_str(name, name_size);
[email protected]0bfd9882010-02-05 23:02:252271 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142272 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192273}
2274
[email protected]ddd968b82010-03-02 00:44:292275error::Error GLES2DecoderImpl::HandleGetString(
2276 uint32 immediate_data_size, const gles2::GetString& c) {
2277 GLenum name = static_cast<GLenum>(c.name);
2278 if (!ValidateGLenumStringType(name)) {
2279 SetGLError(GL_INVALID_ENUM);
2280 return error::kNoError;
2281 }
2282 Bucket* bucket = CreateBucket(c.bucket_id);
2283 bucket->SetFromString(reinterpret_cast<const char*>(glGetString(name)));
2284 return error::kNoError;
2285}
2286
[email protected]0c86dbf2010-03-05 08:14:112287void GLES2DecoderImpl::DoBufferData(
2288 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]3b6ec202010-03-05 05:16:232289 if (!ValidateGLenumBufferTarget(target) ||
2290 !ValidateGLenumBufferUsage(usage)) {
2291 SetGLError(GL_INVALID_ENUM);
[email protected]0c86dbf2010-03-05 08:14:112292 return;
[email protected]3b6ec202010-03-05 05:16:232293 }
2294 if (size < 0) {
2295 SetGLError(GL_INVALID_VALUE);
[email protected]0c86dbf2010-03-05 08:14:112296 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232297 }
2298 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
2299 if (!info) {
2300 SetGLError(GL_INVALID_OPERATION);
[email protected]0c86dbf2010-03-05 08:14:112301 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232302 }
2303 // Clear the buffer to 0 if no initial data was passed in.
2304 scoped_array<int8> zero;
2305 if (!data) {
2306 zero.reset(new int8[size]);
2307 memset(zero.get(), 0, size);
2308 data = zero.get();
2309 }
2310 CopyRealGLErrorsToWrapper();
2311 glBufferData(target, size, data, usage);
2312 GLenum error = glGetError();
2313 if (error != GL_NO_ERROR) {
2314 SetGLError(error);
2315 } else {
[email protected]0c86dbf2010-03-05 08:14:112316 info->SetSize(size);
2317 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:232318 }
[email protected]0c86dbf2010-03-05 08:14:112319}
2320
2321error::Error GLES2DecoderImpl::HandleBufferData(
2322 uint32 immediate_data_size, const gles2::BufferData& c) {
2323 GLenum target = static_cast<GLenum>(c.target);
2324 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
2325 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
2326 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
2327 GLenum usage = static_cast<GLenum>(c.usage);
2328 const void* data = NULL;
2329 if (data_shm_id != 0 || data_shm_offset != 0) {
2330 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
2331 if (!data) {
2332 return error::kOutOfBounds;
2333 }
2334 }
2335 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:142336 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192337}
2338
[email protected]f7a64ee2010-02-01 22:24:142339error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:192340 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
2341 GLenum target = static_cast<GLenum>(c.target);
2342 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:302343 const void* data = GetImmediateDataAs<const void*>(
2344 c, size, immediate_data_size);
2345 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142346 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:302347 }
[email protected]b9849abf2009-11-25 19:13:192348 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:112349 DoBufferData(target, size, data, usage);
2350 return error::kNoError;
2351}
2352
2353void GLES2DecoderImpl::DoBufferSubData(
2354 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:502355 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472356 if (!info) {
2357 SetGLError(GL_INVALID_OPERATION);
[email protected]a93bb842010-02-16 23:03:472358 }
[email protected]0c86dbf2010-03-05 08:14:112359 if (!info->SetRange(offset, size, data)) {
2360 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:302361 } else {
[email protected]0c86dbf2010-03-05 08:14:112362 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:302363 }
[email protected]b9849abf2009-11-25 19:13:192364}
2365
[email protected]a93bb842010-02-16 23:03:472366error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
2367 GLenum target,
2368 GLint level,
2369 GLenum internal_format,
2370 GLsizei width,
2371 GLsizei height,
2372 GLint border,
2373 GLsizei image_size,
2374 const void* data) {
[email protected]a93bb842010-02-16 23:03:472375 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]86093972010-03-11 00:13:562376 if (!ValidateGLenumTextureTarget(target) ||
2377 !ValidateGLenumCompressedTextureInternalFormat(internal_format)) {
[email protected]a93bb842010-02-16 23:03:472378 SetGLError(GL_INVALID_ENUM);
2379 return error::kNoError;
2380 }
[email protected]3916c97e2010-02-25 03:20:502381 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:472382 border != 0) {
2383 SetGLError(GL_INVALID_VALUE);
2384 return error::kNoError;
2385 }
[email protected]3916c97e2010-02-25 03:20:502386 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472387 if (!info) {
2388 SetGLError(GL_INVALID_OPERATION);
2389 return error::kNoError;
2390 }
2391 scoped_array<int8> zero;
2392 if (!data) {
2393 zero.reset(new int8[image_size]);
2394 memset(zero.get(), 0, image_size);
2395 data = zero.get();
2396 }
2397 info->SetLevelInfo(
2398 target, level, internal_format, width, height, 1, border, 0, 0);
2399 glCompressedTexImage2D(
2400 target, level, internal_format, width, height, border, image_size, data);
2401 return error::kNoError;
2402}
2403
[email protected]f7a64ee2010-02-01 22:24:142404error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192405 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
2406 GLenum target = static_cast<GLenum>(c.target);
2407 GLint level = static_cast<GLint>(c.level);
2408 GLenum internal_format = static_cast<GLenum>(c.internalformat);
2409 GLsizei width = static_cast<GLsizei>(c.width);
2410 GLsizei height = static_cast<GLsizei>(c.height);
2411 GLint border = static_cast<GLint>(c.border);
2412 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
2413 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
2414 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
2415 const void* data = NULL;
2416 if (data_shm_id != 0 || data_shm_offset != 0) {
2417 data = GetSharedMemoryAs<const void*>(
2418 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:462419 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142420 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192421 }
2422 }
[email protected]a93bb842010-02-16 23:03:472423 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192424 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:192425}
2426
[email protected]f7a64ee2010-02-01 22:24:142427error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:192428 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
2429 GLenum target = static_cast<GLenum>(c.target);
2430 GLint level = static_cast<GLint>(c.level);
2431 GLenum internal_format = static_cast<GLenum>(c.internalformat);
2432 GLsizei width = static_cast<GLsizei>(c.width);
2433 GLsizei height = static_cast<GLsizei>(c.height);
2434 GLint border = static_cast<GLint>(c.border);
2435 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:302436 const void* data = GetImmediateDataAs<const void*>(
2437 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462438 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142439 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462440 }
[email protected]a93bb842010-02-16 23:03:472441 return DoCompressedTexImage2D(
2442 target, level, internal_format, width, height, border, image_size, data);
2443}
2444
[email protected]a93bb842010-02-16 23:03:472445error::Error GLES2DecoderImpl::DoTexImage2D(
2446 GLenum target,
2447 GLint level,
2448 GLenum internal_format,
2449 GLsizei width,
2450 GLsizei height,
2451 GLint border,
2452 GLenum format,
2453 GLenum type,
2454 const void* pixels,
2455 uint32 pixels_size) {
2456 if (!ValidateGLenumTextureTarget(target) ||
2457 !ValidateGLenumTextureFormat(internal_format) ||
2458 !ValidateGLenumTextureFormat(format) ||
2459 !ValidateGLenumPixelType(type)) {
[email protected]8bf5a3e2010-01-29 04:21:362460 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:142461 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192462 }
[email protected]3916c97e2010-02-25 03:20:502463 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:472464 border != 0) {
2465 SetGLError(GL_INVALID_VALUE);
2466 return error::kNoError;
2467 }
[email protected]3916c97e2010-02-25 03:20:502468 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472469 if (!info) {
2470 SetGLError(GL_INVALID_OPERATION);
2471 return error::kNoError;
2472 }
2473 scoped_array<int8> zero;
2474 if (!pixels) {
2475 zero.reset(new int8[pixels_size]);
2476 memset(zero.get(), 0, pixels_size);
2477 pixels = zero.get();
2478 }
2479 info->SetLevelInfo(
2480 target, level, internal_format, width, height, 1, border, format, type);
2481 glTexImage2D(
2482 target, level, internal_format, width, height, border, format, type,
2483 pixels);
[email protected]f7a64ee2010-02-01 22:24:142484 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192485}
2486
[email protected]f7a64ee2010-02-01 22:24:142487error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192488 uint32 immediate_data_size, const gles2::TexImage2D& c) {
2489 GLenum target = static_cast<GLenum>(c.target);
2490 GLint level = static_cast<GLint>(c.level);
2491 GLint internal_format = static_cast<GLint>(c.internalformat);
2492 GLsizei width = static_cast<GLsizei>(c.width);
2493 GLsizei height = static_cast<GLsizei>(c.height);
2494 GLint border = static_cast<GLint>(c.border);
2495 GLenum format = static_cast<GLenum>(c.format);
2496 GLenum type = static_cast<GLenum>(c.type);
2497 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
2498 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:182499 uint32 pixels_size;
2500 if (!GLES2Util::ComputeImageDataSize(
2501 width, height, format, type, unpack_alignment_, &pixels_size)) {
2502 return error::kOutOfBounds;
2503 }
[email protected]b9849abf2009-11-25 19:13:192504 const void* pixels = NULL;
2505 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
2506 pixels = GetSharedMemoryAs<const void*>(
2507 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:462508 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:142509 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192510 }
2511 }
[email protected]a93bb842010-02-16 23:03:472512 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192513 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:472514 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:192515}
2516
[email protected]f7a64ee2010-02-01 22:24:142517error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:192518 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
2519 GLenum target = static_cast<GLenum>(c.target);
2520 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:462521 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:192522 GLsizei width = static_cast<GLsizei>(c.width);
2523 GLsizei height = static_cast<GLsizei>(c.height);
2524 GLint border = static_cast<GLint>(c.border);
2525 GLenum format = static_cast<GLenum>(c.format);
2526 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:182527 uint32 size;
2528 if (!GLES2Util::ComputeImageDataSize(
2529 width, height, format, type, unpack_alignment_, &size)) {
2530 return error::kOutOfBounds;
2531 }
[email protected]07f54fcc2009-12-22 02:46:302532 const void* pixels = GetImmediateDataAs<const void*>(
2533 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462534 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:142535 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462536 }
[email protected]a93bb842010-02-16 23:03:472537 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:462538 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:472539 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:142540 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322541}
2542
[email protected]f7a64ee2010-02-01 22:24:142543error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:192544 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:362545 GLuint index = static_cast<GLuint>(c.index);
2546 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:252547 typedef gles2::GetVertexAttribPointerv::Result Result;
2548 Result* result = GetSharedMemoryAs<Result*>(
2549 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:362550 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:142551 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:362552 }
[email protected]07d0cc82010-02-17 04:51:402553 // Check that the client initialized the result.
2554 if (result->size != 0) {
2555 return error::kInvalidArguments;
2556 }
[email protected]8bf5a3e2010-01-29 04:21:362557 if (!ValidateGLenumVertexPointer(pname)) {
2558 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:142559 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:362560 }
[email protected]3916c97e2010-02-25 03:20:502561 if (index >= group_->max_vertex_attribs()) {
[email protected]8bf5a3e2010-01-29 04:21:362562 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142563 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:362564 }
[email protected]0bfd9882010-02-05 23:02:252565 result->SetNumResults(1);
2566 *result->GetData() = vertex_attrib_infos_[index].offset();
[email protected]f7a64ee2010-02-01 22:24:142567 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322568}
2569
[email protected]f7b85372010-02-03 01:11:372570bool GLES2DecoderImpl::GetUniformSetup(
2571 GLuint program, GLint location,
2572 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:252573 error::Error* error, GLuint* service_id, void** result_pointer) {
[email protected]f7b85372010-02-03 01:11:372574 *error = error::kNoError;
2575 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:252576 SizedResult<GLint>* result;
2577 result = GetSharedMemoryAs<SizedResult<GLint>*>(
2578 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
2579 if (!result) {
[email protected]f7b85372010-02-03 01:11:372580 *error = error::kOutOfBounds;
2581 return false;
2582 }
[email protected]0bfd9882010-02-05 23:02:252583 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:372584 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:252585 result->SetNumResults(0);
[email protected]3916c97e2010-02-25 03:20:502586 if (!id_manager()->GetServiceId(program, service_id)) {
[email protected]f7b85372010-02-03 01:11:372587 SetGLError(GL_INVALID_VALUE);
2588 return error::kNoError;
2589 }
2590 ProgramManager::ProgramInfo* info = GetProgramInfo(*service_id);
2591 if (!info) {
2592 // Program was not linked successfully. (ie, glLinkProgram)
2593 SetGLError(GL_INVALID_OPERATION);
2594 return false;
2595 }
[email protected]0bfd9882010-02-05 23:02:252596 GLenum type;
2597 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:372598 // No such location.
2599 SetGLError(GL_INVALID_OPERATION);
2600 return false;
2601 }
[email protected]3916c97e2010-02-25 03:20:502602 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:372603 if (size == 0) {
2604 SetGLError(GL_INVALID_OPERATION);
2605 return false;
2606 }
[email protected]0bfd9882010-02-05 23:02:252607 result = GetSharedMemoryAs<SizedResult<GLint>*>(
2608 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
2609 if (!result) {
[email protected]f7b85372010-02-03 01:11:372610 *error = error::kOutOfBounds;
2611 return false;
2612 }
[email protected]0bfd9882010-02-05 23:02:252613 result->size = size;
[email protected]f7b85372010-02-03 01:11:372614 return true;
2615}
2616
[email protected]f7a64ee2010-02-01 22:24:142617error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:192618 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:372619 GLuint program = c.program;
2620 GLint location = c.location;
2621 GLuint service_id;
2622 Error error;
[email protected]0bfd9882010-02-05 23:02:252623 void* result;
[email protected]f7b85372010-02-03 01:11:372624 if (GetUniformSetup(
2625 program, location, c.params_shm_id, c.params_shm_offset,
2626 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:252627 glGetUniformiv(
2628 service_id, location,
2629 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:372630 }
2631 return error;
[email protected]96449d2c2009-11-25 00:01:322632}
2633
[email protected]f7a64ee2010-02-01 22:24:142634error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:192635 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:372636 GLuint program = c.program;
2637 GLint location = c.location;
2638 GLuint service_id;
2639 Error error;
[email protected]0bfd9882010-02-05 23:02:252640 void* result;
2641 typedef gles2::GetUniformfv::Result Result;
[email protected]f7b85372010-02-03 01:11:372642 if (GetUniformSetup(
2643 program, location, c.params_shm_id, c.params_shm_offset,
2644 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:252645 glGetUniformfv(
2646 service_id,
2647 location,
2648 static_cast<gles2::GetUniformfv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:372649 }
2650 return error;
[email protected]96449d2c2009-11-25 00:01:322651}
2652
[email protected]f7a64ee2010-02-01 22:24:142653error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:192654 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:252655 GLenum shader_type = static_cast<GLenum>(c.shadertype);
2656 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
2657 typedef gles2::GetShaderPrecisionFormat::Result Result;
2658 Result* result = GetSharedMemoryAs<Result*>(
2659 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2660 if (!result) {
2661 return error::kOutOfBounds;
2662 }
[email protected]07d0cc82010-02-17 04:51:402663 // Check that the client initialized the result.
2664 if (result->success != 0) {
2665 return error::kInvalidArguments;
2666 }
[email protected]0bfd9882010-02-05 23:02:252667 if (!ValidateGLenumShaderType(shader_type) ||
2668 !ValidateGLenumShaderPrecision(precision_type)) {
[email protected]0bfd9882010-02-05 23:02:252669 SetGLError(GL_INVALID_ENUM);
2670 } else {
2671 result->success = 1; // true
2672 switch (precision_type) {
2673 case GL_LOW_INT:
2674 case GL_MEDIUM_INT:
2675 case GL_HIGH_INT:
2676 result->min_range = -31;
2677 result->max_range = 31;
2678 result->precision = 0;
2679 case GL_LOW_FLOAT:
2680 case GL_MEDIUM_FLOAT:
2681 case GL_HIGH_FLOAT:
2682 result->min_range = -62;
2683 result->max_range = 62;
2684 result->precision = -16;
2685 break;
2686 default:
2687 NOTREACHED();
2688 break;
2689 }
2690 }
[email protected]f7a64ee2010-02-01 22:24:142691 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322692}
2693
[email protected]f7a64ee2010-02-01 22:24:142694error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:192695 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:252696 GLuint service_id;
2697 uint32 result_size = c.result_size;
[email protected]3916c97e2010-02-25 03:20:502698 if (!id_manager()->GetServiceId(c.program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252699 SetGLError(GL_INVALID_VALUE);
2700 return error::kNoError;
2701 }
2702 typedef gles2::GetAttachedShaders::Result Result;
2703 uint32 max_count = Result::ComputeMaxResults(result_size);
2704 Result* result = GetSharedMemoryAs<Result*>(
2705 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
2706 if (!result) {
2707 return error::kOutOfBounds;
2708 }
[email protected]07d0cc82010-02-17 04:51:402709 // Check that the client initialized the result.
2710 if (result->size != 0) {
2711 return error::kInvalidArguments;
2712 }
[email protected]0bfd9882010-02-05 23:02:252713 GLsizei count = 0;
2714 glGetAttachedShaders(service_id, max_count, &count, result->GetData());
2715 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]3916c97e2010-02-25 03:20:502716 if (!id_manager()->GetClientId(result->GetData()[ii],
[email protected]0bfd9882010-02-05 23:02:252717 &result->GetData()[ii])) {
2718 NOTREACHED();
2719 return error::kGenericError;
2720 }
2721 }
2722 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:142723 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322724}
2725
[email protected]f7a64ee2010-02-01 22:24:142726error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:192727 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:252728 GLuint program = c.program;
2729 GLuint index = c.index;
2730 uint32 name_bucket_id = c.name_bucket_id;
2731 GLuint service_id;
2732 typedef gles2::GetActiveUniform::Result Result;
2733 Result* result = GetSharedMemoryAs<Result*>(
2734 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2735 if (!result) {
2736 return error::kOutOfBounds;
2737 }
[email protected]07d0cc82010-02-17 04:51:402738 // Check that the client initialized the result.
2739 if (result->success != 0) {
2740 return error::kInvalidArguments;
2741 }
[email protected]3916c97e2010-02-25 03:20:502742 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252743 SetGLError(GL_INVALID_VALUE);
2744 return error::kNoError;
2745 }
2746 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
2747 if (!info) {
2748 // Program was not linked successfully. (ie, glLinkProgram)
2749 SetGLError(GL_INVALID_OPERATION);
2750 return error::kNoError;
2751 }
2752 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2753 info->GetUniformInfo(index);
2754 if (!uniform_info) {
2755 SetGLError(GL_INVALID_VALUE);
2756 return error::kNoError;
2757 }
2758 result->success = 1; // true.
2759 result->size = uniform_info->size;
2760 result->type = uniform_info->type;
2761 Bucket* bucket = CreateBucket(name_bucket_id);
2762 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:142763 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322764}
2765
[email protected]f7a64ee2010-02-01 22:24:142766error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:192767 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:252768 GLuint program = c.program;
2769 GLuint index = c.index;
2770 uint32 name_bucket_id = c.name_bucket_id;
2771 GLuint service_id;
2772 typedef gles2::GetActiveAttrib::Result Result;
2773 Result* result = GetSharedMemoryAs<Result*>(
2774 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2775 if (!result) {
2776 return error::kOutOfBounds;
2777 }
[email protected]07d0cc82010-02-17 04:51:402778 // Check that the client initialized the result.
2779 if (result->success != 0) {
2780 return error::kInvalidArguments;
2781 }
[email protected]3916c97e2010-02-25 03:20:502782 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252783 SetGLError(GL_INVALID_VALUE);
2784 return error::kNoError;
2785 }
2786 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
2787 if (!info) {
2788 // Program was not linked successfully. (ie, glLinkProgram)
2789 SetGLError(GL_INVALID_OPERATION);
2790 return error::kNoError;
2791 }
2792 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
2793 info->GetAttribInfo(index);
2794 if (!attrib_info) {
2795 SetGLError(GL_INVALID_VALUE);
2796 return error::kNoError;
2797 }
2798 result->success = 1; // true.
2799 result->size = attrib_info->size;
2800 result->type = attrib_info->type;
2801 Bucket* bucket = CreateBucket(name_bucket_id);
2802 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:142803 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322804}
2805
2806// Include the auto-generated part of this file. We split this because it means
2807// we can easily edit the non-auto generated parts right here in this file
2808// instead of having to edit some template or the code generator.
2809#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
2810
2811} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:252812} // namespace gpu