blob: e07dc996d3ebd7806624324ccf35f9504df8c757 [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)
34// The following two #includes CAN NOT go above the inclusion of
35// gl_utils.h and therefore glew.h regardless of what the Google C++
36// style guide says.
37#include <CoreFoundation/CoreFoundation.h> // NOLINT
38#include <OpenGL/OpenGL.h> // NOLINT
39#include "base/scoped_cftyperef.h"
40#include "chrome/common/io_surface_support_mac.h"
[email protected]be4f1882010-01-06 04:38:5541#endif
[email protected]96449d2c2009-11-25 00:01:3242
[email protected]a7a27ace2009-12-12 00:11:2543namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3244namespace gles2 {
45
[email protected]07f54fcc2009-12-22 02:46:3046// Check that certain assumptions the code makes are true. There are places in
47// the code where shared memory is passed direclty to GL. Example, glUniformiv,
48// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
49// a few others) are 32bits. If they are not 32bits the code will have to change
50// to call those GL functions with service side memory and then copy the results
51// to shared memory, converting the sizes.
52COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
53 GLint_not_same_size_as_uint32);
54COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
55 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3756COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
57 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3058
[email protected]43f28f832010-02-03 02:28:4859// TODO(kbr): the use of this anonymous namespace core dumps the
60// linker on Mac OS X 10.6 when the symbol ordering file is used
61// namespace {
[email protected]96449d2c2009-11-25 00:01:3262
63// Returns the address of the first byte after a struct.
64template <typename T>
65const void* AddressAfterStruct(const T& pod) {
66 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
67}
68
[email protected]07f54fcc2009-12-22 02:46:3069// Returns the address of the frst byte after the struct or NULL if size >
70// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3271template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3072RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
73 uint32 size,
74 uint32 immediate_data_size) {
75 return (size <= immediate_data_size) ?
76 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
77 NULL;
[email protected]96449d2c2009-11-25 00:01:3278}
79
[email protected]07f54fcc2009-12-22 02:46:3080// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1881bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3282 GLuint count,
83 size_t size,
[email protected]a76b0052010-03-05 00:33:1884 unsigned int elements_per_unit,
85 uint32* dst) {
86 uint32 value;
87 if (!SafeMultiplyUint32(count, size, &value)) {
88 return false;
89 }
90 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
91 return false;
92 }
93 *dst = value;
94 return true;
[email protected]96449d2c2009-11-25 00:01:3295}
96
97// A struct to hold info about each command.
98struct CommandInfo {
99 int arg_flags; // How to handle the arguments for this command
100 int arg_count; // How many arguments are expected for this command.
101};
102
103// A table of CommandInfo for all the commands.
104const CommandInfo g_command_info[] = {
105 #define GLES2_CMD_OP(name) { \
106 name::kArgFlags, \
107 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
108
109 GLES2_COMMAND_LIST(GLES2_CMD_OP)
110
111 #undef GLES2_CMD_OP
112};
113
[email protected]43f28f832010-02-03 02:28:48114// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32115
[email protected]3916c97e2010-02-25 03:20:50116GLES2Decoder::GLES2Decoder(ContextGroup* group)
117 : group_(group),
[email protected]69d80ae2009-12-23 08:57:42118#if defined(UNIT_TEST)
[email protected]3916c97e2010-02-25 03:20:50119 debug_(false) {
[email protected]69d80ae2009-12-23 08:57:42120#elif defined(OS_LINUX)
[email protected]3916c97e2010-02-25 03:20:50121 debug_(false),
[email protected]b9849abf2009-11-25 19:13:19122 window_(NULL) {
123#elif defined(OS_WIN)
[email protected]3916c97e2010-02-25 03:20:50124 debug_(false),
[email protected]b9849abf2009-11-25 19:13:19125 hwnd_(NULL) {
126#else
[email protected]3916c97e2010-02-25 03:20:50127 debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32128#endif
129}
130
[email protected]3916c97e2010-02-25 03:20:50131GLES2Decoder::~GLES2Decoder() {
132}
133
[email protected]96449d2c2009-11-25 00:01:32134// This class implements GLES2Decoder so we don't have to expose all the GLES2
135// cmd stuff to outside this class.
136class GLES2DecoderImpl : public GLES2Decoder {
137 public:
[email protected]3916c97e2010-02-25 03:20:50138 explicit GLES2DecoderImpl(ContextGroup* group);
139
[email protected]07f54fcc2009-12-22 02:46:30140 // Info about Vertex Attributes. This is used to track what the user currently
141 // has bound on each Vertex Attribute so that checking can be done at
142 // glDrawXXX time.
143 class VertexAttribInfo {
144 public:
145 VertexAttribInfo()
146 : enabled_(false),
147 size_(0),
148 type_(0),
149 offset_(0),
[email protected]3916c97e2010-02-25 03:20:50150 real_stride_(0) {
[email protected]07f54fcc2009-12-22 02:46:30151 }
[email protected]3916c97e2010-02-25 03:20:50152
[email protected]07f54fcc2009-12-22 02:46:30153 // Returns true if this VertexAttrib can access index.
154 bool CanAccess(GLuint index);
155
156 void set_enabled(bool enabled) {
157 enabled_ = enabled;
158 }
159
[email protected]3916c97e2010-02-25 03:20:50160 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30161 return buffer_;
162 }
163
[email protected]8bf5a3e2010-01-29 04:21:36164 GLsizei offset() const {
165 return offset_;
166 }
167
[email protected]07f54fcc2009-12-22 02:46:30168 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50169 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30170 GLint size,
171 GLenum type,
172 GLsizei real_stride,
173 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24174 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30175 buffer_ = buffer;
176 size_ = size;
177 type_ = type;
178 real_stride_ = real_stride;
179 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50180 }
181
182 void ClearBuffer() {
183 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30184 }
185
186 private:
187 // Whether or not this attribute is enabled.
188 bool enabled_;
189
190 // number of components (1, 2, 3, 4)
191 GLint size_;
192
193 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
194 GLenum type_;
195
196 // The offset into the buffer.
197 GLsizei offset_;
198
199 // The stride that will be used to access the buffer. This is the actual
200 // stide, NOT the GL bogus stride. In other words there is never a stride
201 // of 0.
202 GLsizei real_stride_;
203
[email protected]3916c97e2010-02-25 03:20:50204 // The buffer bound to this attribute.
205 BufferManager::BufferInfo::Ref buffer_;
[email protected]07f54fcc2009-12-22 02:46:30206 };
207
[email protected]96449d2c2009-11-25 00:01:32208 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14209 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50210 unsigned int arg_count,
211 const void* args);
[email protected]96449d2c2009-11-25 00:01:32212
213 // Overridden from AsyncAPIInterface.
214 virtual const char* GetCommandName(unsigned int command_id) const;
215
216 // Overridden from GLES2Decoder.
217 virtual bool Initialize();
[email protected]96449d2c2009-11-25 00:01:32218 virtual void Destroy();
[email protected]eb54a562010-01-20 21:55:18219 virtual bool MakeCurrent();
[email protected]8a837bb2010-01-05 00:21:24220 virtual uint32 GetServiceIdForTesting(uint32 client_id);
221
[email protected]6098b712010-02-09 17:59:34222#if defined(OS_MACOSX)
[email protected]43f28f832010-02-03 02:28:48223 // Overridden from GLES2Decoder.
[email protected]1aef98132010-02-23 18:00:07224
225 // The recommended usage is to call SetWindowSizeForIOSurface() first, and if
226 // that returns 0, try calling SetWindowSizeForTransportDIB(). A return value
227 // of 0 from SetWindowSizeForIOSurface() might mean the IOSurface API is not
228 // available, which is true if you are not running on Max OS X 10.6 or later.
229 // If SetWindowSizeForTransportDIB() also returns a NULL handle, then an
230 // error has occured.
231 virtual uint64 SetWindowSizeForIOSurface(int32 width, int32 height);
232 virtual TransportDIB::Handle SetWindowSizeForTransportDIB(int32 width,
233 int32 height);
234 // |allocator| sends a message to the renderer asking for a new
235 // TransportDIB big enough to hold the rendered bits. The parameters to the
236 // call back are the size of the DIB and the handle (filled in on return).
237 virtual void SetTransportDIBAllocAndFree(
238 Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
239 Callback1<TransportDIB::Id>::Type* deallocator);
[email protected]43f28f832010-02-03 02:28:48240#endif
241
242 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
243
[email protected]96449d2c2009-11-25 00:01:32244 private:
[email protected]3916c97e2010-02-25 03:20:50245 // State associated with each texture unit.
246 struct TextureUnit {
247 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
248
249 // The last target that was bound to this texture unit.
250 GLenum bind_target;
251
252 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
253 TextureManager::TextureInfo::Ref bound_texture_2d;
254
255 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
256 // glBindTexture
257 TextureManager::TextureInfo::Ref bound_texture_cube_map;
258 };
259
[email protected]a93bb842010-02-16 23:03:47260 friend void GLGenTexturesHelper(
261 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
262 friend void GLDeleteTexturesHelper(
263 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
264 friend void GLGenBuffersHelper(
265 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
266 friend void GLDeleteBuffersHelper(
267 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
268
[email protected]3916c97e2010-02-25 03:20:50269 // TODO(gman): Cache these pointers?
270 IdManager* id_manager() {
271 return group_->id_manager();
272 }
273
274 BufferManager* buffer_manager() {
275 return group_->buffer_manager();
276 }
277
278 ProgramManager* program_manager() {
279 return group_->program_manager();
280 }
281
282 ShaderManager* shader_manager() {
283 return group_->shader_manager();
284 }
285
286 TextureManager* texture_manager() {
287 return group_->texture_manager();
288 }
289
[email protected]246a70452010-03-05 21:53:50290#if defined(OS_WIN)
291 static bool InitializeOneOff(bool anti_aliased);
292#endif
293
294
[email protected]96449d2c2009-11-25 00:01:32295 bool InitPlatformSpecific();
[email protected]246a70452010-03-05 21:53:50296 static bool InitGlew();
297 void DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:32298
[email protected]96449d2c2009-11-25 00:01:32299 // Template to help call glGenXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30300 template <void gl_gen_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32301 bool GenGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12302 DCHECK_GE(n, 0);
[email protected]8a837bb2010-01-05 00:21:24303 if (!ValidateIdsAreUnused(n, client_ids)) {
304 return false;
305 }
[email protected]96449d2c2009-11-25 00:01:32306 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30307 gl_gen_function(this, n, temp.get());
[email protected]07f54fcc2009-12-22 02:46:30308 return RegisterObjects(n, client_ids, temp.get());
[email protected]96449d2c2009-11-25 00:01:32309 }
310
311 // Template to help call glDeleteXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30312 template <void gl_delete_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32313 bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12314 DCHECK_GE(n, 0);
[email protected]96449d2c2009-11-25 00:01:32315 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30316 UnregisterObjects(n, client_ids, temp.get());
317 gl_delete_function(this, n, temp.get());
[email protected]96449d2c2009-11-25 00:01:32318 return true;
319 }
320
[email protected]8a837bb2010-01-05 00:21:24321 // Check that the given ids are not used.
322 bool ValidateIdsAreUnused(GLsizei n, const GLuint* client_ids);
323
[email protected]07f54fcc2009-12-22 02:46:30324 // Register client ids with generated service ids.
325 bool RegisterObjects(
326 GLsizei n, const GLuint* client_ids, const GLuint* service_ids);
327
328 // Unregisters client ids with service ids.
329 void UnregisterObjects(
330 GLsizei n, const GLuint* client_ids, GLuint* service_ids);
331
[email protected]a93bb842010-02-16 23:03:47332 // Creates a TextureInfo for the given texture.
333 void CreateTextureInfo(GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:50334 texture_manager()->CreateTextureInfo(texture);
[email protected]a93bb842010-02-16 23:03:47335 }
336
337 // Gets the texture info for the given texture. Returns NULL if none exists.
338 TextureManager::TextureInfo* GetTextureInfo(GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:50339 TextureManager::TextureInfo* info =
340 texture_manager()->GetTextureInfo(texture);
341 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47342 }
343
344 // Deletes the texture info for the given texture.
[email protected]3916c97e2010-02-25 03:20:50345 void RemoveTextureInfo(GLuint texture) {
346 texture_manager()->RemoveTextureInfo(texture);
347 }
[email protected]a93bb842010-02-16 23:03:47348
349 // Wrapper for CompressedTexImage2D commands.
350 error::Error DoCompressedTexImage2D(
351 GLenum target,
352 GLint level,
353 GLenum internal_format,
354 GLsizei width,
355 GLsizei height,
356 GLint border,
357 GLsizei image_size,
358 const void* data);
359
360 // Wrapper for TexImage2D commands.
361 error::Error DoTexImage2D(
362 GLenum target,
363 GLint level,
364 GLenum internal_format,
365 GLsizei width,
366 GLsizei height,
367 GLint border,
368 GLenum format,
369 GLenum type,
370 const void* pixels,
371 uint32 pixels_size);
372
373 // Creates a ProgramInfo for the given program.
374 void CreateProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50375 program_manager()->CreateProgramInfo(program);
[email protected]a93bb842010-02-16 23:03:47376 }
377
[email protected]07f54fcc2009-12-22 02:46:30378 // Gets the program info for the given program. Returns NULL if none exists.
379 // Programs that have no had glLinkProgram succesfully called on them will
380 // not exist.
[email protected]1d32bc82010-01-13 22:06:46381 ProgramManager::ProgramInfo* GetProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50382 ProgramManager::ProgramInfo* info =
383 program_manager()->GetProgramInfo(program);
384 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46385 }
[email protected]07f54fcc2009-12-22 02:46:30386
[email protected]07f54fcc2009-12-22 02:46:30387 // Deletes the program info for the given program.
[email protected]1d32bc82010-01-13 22:06:46388 void RemoveProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50389 program_manager()->RemoveProgramInfo(program);
[email protected]1d32bc82010-01-13 22:06:46390 }
[email protected]07f54fcc2009-12-22 02:46:30391
[email protected]45bf5152010-02-12 00:11:31392 // Creates a ShaderInfo for the given shader.
393 void CreateShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50394 shader_manager()->CreateShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31395 }
396
397 // Gets the shader info for the given shader. Returns NULL if none exists.
398 ShaderManager::ShaderInfo* GetShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50399 ShaderManager::ShaderInfo* info = shader_manager()->GetShaderInfo(shader);
400 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]45bf5152010-02-12 00:11:31401 }
402
403 // Deletes the shader info for the given shader.
404 void RemoveShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50405 shader_manager()->RemoveShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31406 }
407
[email protected]a93bb842010-02-16 23:03:47408 // Creates a buffer info for the given buffer.
409 void CreateBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50410 return buffer_manager()->CreateBufferInfo(buffer);
[email protected]a93bb842010-02-16 23:03:47411 }
412
[email protected]07f54fcc2009-12-22 02:46:30413 // Gets the buffer info for the given buffer.
[email protected]1d32bc82010-01-13 22:06:46414 BufferManager::BufferInfo* GetBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50415 BufferManager::BufferInfo* info = buffer_manager()->GetBufferInfo(buffer);
416 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46417 }
[email protected]07f54fcc2009-12-22 02:46:30418
[email protected]a93bb842010-02-16 23:03:47419 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
420 // on glDeleteBuffers so we can make sure the user does not try to render
421 // with deleted buffers.
422 void RemoveBufferInfo(GLuint buffer_id);
423
[email protected]3916c97e2010-02-25 03:20:50424 // Helper for glShaderSource.
425 error::Error ShaderSourceHelper(
426 GLuint shader, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30427
[email protected]96449d2c2009-11-25 00:01:32428 // Wrapper for glCreateProgram
429 void CreateProgramHelper(GLuint client_id);
430
431 // Wrapper for glCreateShader
432 void CreateShaderHelper(GLenum type, GLuint client_id);
433
[email protected]3916c97e2010-02-25 03:20:50434 // Wrapper for glActiveTexture
435 void DoActiveTexture(GLenum texture_unit);
436
[email protected]96449d2c2009-11-25 00:01:32437 // Wrapper for glBindBuffer since we need to track the current targets.
438 void DoBindBuffer(GLenum target, GLuint buffer);
439
[email protected]a93bb842010-02-16 23:03:47440 // Wrapper for glBindTexture since we need to track the current targets.
441 void DoBindTexture(GLenum target, GLuint texture);
442
[email protected]0c86dbf2010-03-05 08:14:11443 // Wrapper for BufferData.
444 void DoBufferData(
445 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
446
447 // Wrapper for BufferSubData.
448 void DoBufferSubData(
449 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
450
[email protected]45bf5152010-02-12 00:11:31451 // Wrapper for glCompileShader.
452 void DoCompileShader(GLuint shader);
453
[email protected]07f54fcc2009-12-22 02:46:30454 // Wrapper for glDrawArrays.
455 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
456
457 // Wrapper for glDisableVertexAttribArray.
458 void DoDisableVertexAttribArray(GLuint index);
459
460 // Wrapper for glEnableVertexAttribArray.
461 void DoEnableVertexAttribArray(GLuint index);
462
[email protected]a93bb842010-02-16 23:03:47463 // Wrapper for glGenerateMipmap
464 void DoGenerateMipmap(GLenum target);
465
[email protected]ddd968b82010-03-02 00:44:29466 // Wrapper for glGetShaderiv
467 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
468
[email protected]45bf5152010-02-12 00:11:31469 // Wrapper for glGetShaderSource.
470 void DoGetShaderSource(
471 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst);
472
[email protected]07f54fcc2009-12-22 02:46:30473 // Wrapper for glLinkProgram
474 void DoLinkProgram(GLuint program);
475
[email protected]96449d2c2009-11-25 00:01:32476 // Swaps the buffers (copies/renders to the current window).
477 void DoSwapBuffers();
478
[email protected]3916c97e2010-02-25 03:20:50479 // Wrappers for glTexParameter functions.
480 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
481 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
482 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
483 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
484
485 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
486 // spec only these 2 functions can be used to set sampler uniforms.
487 void DoUniform1i(GLint location, GLint v0);
488 void DoUniform1iv(GLint location, GLsizei count, const GLint *value);
489
[email protected]07f54fcc2009-12-22 02:46:30490 // Wrapper for glUseProgram
491 void DoUseProgram(GLuint program);
492
[email protected]96449d2c2009-11-25 00:01:32493 // Gets the GLError through our wrapper.
494 GLenum GetGLError();
495
496 // Sets our wrapper for the GLError.
497 void SetGLError(GLenum error);
498
[email protected]07f54fcc2009-12-22 02:46:30499 // Copies the real GL errors to the wrapper. This is so we can
500 // make sure there are no native GL errors before calling some GL function
501 // so that on return we know any error generated was for that specific
502 // command.
503 void CopyRealGLErrorsToWrapper();
504
505 // Checks if the current program and vertex attributes are valid for drawing.
506 bool IsDrawValid(GLuint max_vertex_accessed);
507
[email protected]3916c97e2010-02-25 03:20:50508 void SetBlackTextureForNonRenderableTextures(
509 bool* has_non_renderable_textures);
510 void RestoreStateForNonRenderableTextures();
511
[email protected]07f54fcc2009-12-22 02:46:30512 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:50513 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:30514 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:50515 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
516 bound_array_buffer_ : bound_element_array_buffer_;
517 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:30518 }
519
[email protected]a93bb842010-02-16 23:03:47520 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:50521 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
522 TextureUnit& unit = texture_units_[active_texture_unit_];
523 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:47524 switch (target) {
525 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:50526 info = unit.bound_texture_2d;
527 break;
[email protected]a93bb842010-02-16 23:03:47528 case GL_TEXTURE_CUBE_MAP:
529 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
530 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
531 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
532 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
533 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
534 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:50535 info = unit.bound_texture_cube_map;
536 break;
[email protected]1aef98132010-02-23 18:00:07537 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
538 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
539 // because |texture_| is used by the FBO rendering mechanism for readback
540 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:47541 default:
542 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:50543 return NULL;
[email protected]a93bb842010-02-16 23:03:47544 }
[email protected]3916c97e2010-02-25 03:20:50545 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47546 }
547
[email protected]f7b85372010-02-03 01:11:37548 // Validates the program and location for a glGetUniform call and returns
549 // a SizeResult setup to receive the result. Returns true if glGetUniform
550 // should be called.
551 bool GetUniformSetup(
552 GLuint program, GLint location,
553 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:25554 error::Error* error, GLuint* service_id, void** result);
[email protected]f7b85372010-02-03 01:11:37555
[email protected]96449d2c2009-11-25 00:01:32556 // Generate a member function prototype for each command in an automated and
557 // typesafe way.
558 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:14559 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:19560 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:32561 const gles2::name& args); \
562
563 GLES2_COMMAND_LIST(GLES2_CMD_OP)
564
565 #undef GLES2_CMD_OP
566
[email protected]1aef98132010-02-23 18:00:07567#if defined(OS_MACOSX)
568 // Helper function to generate names for the backing texture, render buffers
569 // and FBO. On return, the resulting buffer names can be attached to |fbo_|.
570 // |target| is the target type for the color buffer.
571 void AllocateRenderBuffers(GLenum target, int32 width, int32 height);
572
573 // Helper function to attach the buffers previously allocated by a call to
574 // AllocateRenderBuffers(). On return, |fbo_| can be used for
575 // rendering. |target| must be the same value as used in the call to
576 // AllocateRenderBuffers(). Returns |true| if the resulting framebuffer
577 // object is valid.
578 bool SetupFrameBufferObject(GLenum target);
579#endif
580
[email protected]96449d2c2009-11-25 00:01:32581 // Current GL error bits.
582 uint32 error_bits_;
583
[email protected]96449d2c2009-11-25 00:01:32584 // Util to help with GL.
585 GLES2Util util_;
586
587 // pack alignment as last set by glPixelStorei
588 GLint pack_alignment_;
589
590 // unpack alignment as last set by glPixelStorei
591 GLint unpack_alignment_;
592
593 // The currently bound array buffer. If this is 0 it is illegal to call
594 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:50595 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:32596
597 // The currently bound element array buffer. If this is 0 it is illegal
598 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:50599 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:30600
601 // Info for each vertex attribute saved so we can check at glDrawXXX time
602 // if it is safe to draw.
603 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
604
[email protected]3916c97e2010-02-25 03:20:50605 // Current active texture by 0 - n index.
606 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
607 // be 2.
608 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:30609
[email protected]3916c97e2010-02-25 03:20:50610 // Which textures are bound to texture units through glActiveTexture.
611 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:47612
[email protected]3916c97e2010-02-25 03:20:50613 // Black (0,0,0,0) textures for when non-renderable textures are used.
614 // NOTE: There is no corresponding TextureInfo for these textures.
615 // TextureInfos are only for textures the client side can access.
616 GLuint black_2d_texture_id_;
617 GLuint black_cube_texture_id_;
[email protected]45bf5152010-02-12 00:11:31618
[email protected]1d32bc82010-01-13 22:06:46619 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:50620 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:30621
[email protected]69d80ae2009-12-23 08:57:42622#if defined(UNIT_TEST)
623#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:50624 static int pixel_format_;
625 HDC gl_device_context_;
[email protected]96449d2c2009-11-25 00:01:32626 HGLRC gl_context_;
[email protected]246a70452010-03-05 21:53:50627 HPBUFFERARB pbuffer_;
[email protected]43f28f832010-02-03 02:28:48628#elif defined(OS_MACOSX)
629 CGLContextObj gl_context_;
630 CGLPBufferObj pbuffer_;
[email protected]1aef98132010-02-23 18:00:07631 // Either |io_surface_| or |transport_dib_| is a valid pointer, but not both.
632 // |io_surface_| is non-NULL if the IOSurface APIs are supported (Mac OS X
633 // 10.6 and later).
634 // TODO(dspringer,kbr): Should the GPU backing store be encapsulated in its
635 // own class so all this implementation detail is hidden?
[email protected]43f28f832010-02-03 02:28:48636 scoped_cftyperef<CFTypeRef> io_surface_;
[email protected]1aef98132010-02-23 18:00:07637 // TODO(dspringer): If we end up keeping this TransportDIB mechanism, this
638 // should really be a scoped_ptr_malloc<>, with a deallocate functor that
639 // runs |dib_free_callback_|. I was not able to figure out how to
640 // make this work (or even compile).
641 scoped_ptr<TransportDIB> transport_dib_;
[email protected]43f28f832010-02-03 02:28:48642 int32 surface_width_;
643 int32 surface_height_;
644 GLuint texture_;
645 GLuint fbo_;
[email protected]1aef98132010-02-23 18:00:07646 GLuint depth_stencil_renderbuffer_;
[email protected]43f28f832010-02-03 02:28:48647 // For tracking whether the default framebuffer / renderbuffer or
648 // ones created by the end user are currently bound
649 GLuint bound_fbo_;
650 GLuint bound_renderbuffer_;
[email protected]1aef98132010-02-23 18:00:07651 // Allocate a TransportDIB in the renderer.
652 scoped_ptr<Callback2<size_t, TransportDIB::Handle*>::Type>
653 dib_alloc_callback_;
654 scoped_ptr<Callback1<TransportDIB::Id>::Type> dib_free_callback_;
[email protected]96449d2c2009-11-25 00:01:32655#endif
656
657 bool anti_aliased_;
658
[email protected]43f28f832010-02-03 02:28:48659 scoped_ptr<Callback0::Type> swap_buffers_callback_;
660
[email protected]96449d2c2009-11-25 00:01:32661 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
662};
663
[email protected]3916c97e2010-02-25 03:20:50664GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
665 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:32666}
667
[email protected]246a70452010-03-05 21:53:50668#if defined(UNIT_TEST)
669#elif defined(OS_WIN)
670int GLES2DecoderImpl::pixel_format_;
671#endif
672
[email protected]3916c97e2010-02-25 03:20:50673GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
674 : GLES2Decoder(group),
[email protected]96449d2c2009-11-25 00:01:32675 error_bits_(0),
676 util_(0), // TODO(gman): Set to actual num compress texture formats.
677 pack_alignment_(4),
678 unpack_alignment_(4),
[email protected]3916c97e2010-02-25 03:20:50679 active_texture_unit_(0),
680 black_2d_texture_id_(0),
681 black_cube_texture_id_(0),
[email protected]69d80ae2009-12-23 08:57:42682#if defined(UNIT_TEST)
683#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]43f28f832010-02-03 02:28:48687#elif defined(OS_MACOSX)
688 gl_context_(NULL),
689 pbuffer_(NULL),
690 surface_width_(0),
691 surface_height_(0),
692 texture_(0),
693 fbo_(0),
[email protected]1aef98132010-02-23 18:00:07694 depth_stencil_renderbuffer_(0),
[email protected]43f28f832010-02-03 02:28:48695 bound_fbo_(0),
696 bound_renderbuffer_(0),
[email protected]96449d2c2009-11-25 00:01:32697#endif
698 anti_aliased_(false) {
699}
700
701bool GLES2DecoderImpl::Initialize() {
[email protected]246a70452010-03-05 21:53:50702 if (!InitPlatformSpecific()) {
703 Destroy();
704 return false;
705 }
706 if (!MakeCurrent()) {
707 Destroy();
708 return false;
[email protected]eb54a562010-01-20 21:55:18709 }
710
[email protected]246a70452010-03-05 21:53:50711 // This happens in InitializeOneOff in windows. TODO(apatrick): generalize to
712 // other platforms.
713#if !defined(OS_WIN)
714 if (!InitGlew()) {
715 Destroy();
716 return false;
717 }
718#endif
719
720 CHECK_GL_ERROR();
721
722 if (!group_->Initialize()) {
723 Destroy();
724 return false;
725 }
726
727 vertex_attrib_infos_.reset(
728 new VertexAttribInfo[group_->max_vertex_attribs()]);
729 texture_units_.reset(
730 new TextureUnit[group_->max_texture_units()]);
731 GLuint ids[2];
732 glGenTextures(2, ids);
733 // Make black textures for replacing non-renderable textures.
734 black_2d_texture_id_ = ids[0];
735 black_cube_texture_id_ = ids[1];
736 static int8 black[] = {0, 0, 0, 0};
737 glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
738 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
739 GL_UNSIGNED_BYTE, black);
740 glBindTexture(GL_TEXTURE_2D, 0);
741 glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
742 static GLenum faces[] = {
743 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
744 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
745 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
746 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
747 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
748 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
749 };
750 for (size_t ii = 0; ii < arraysize(faces); ++ii) {
751 glTexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA,
752 GL_UNSIGNED_BYTE, black);
753 }
754 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
755 CHECK_GL_ERROR();
756
757 return true;
[email protected]96449d2c2009-11-25 00:01:32758}
759
[email protected]43f28f832010-02-03 02:28:48760// TODO(kbr): the use of this anonymous namespace core dumps the
761// linker on Mac OS X 10.6 when the symbol ordering file is used
762// namespace {
[email protected]96449d2c2009-11-25 00:01:32763
[email protected]69d80ae2009-12-23 08:57:42764#if defined(UNIT_TEST)
765#elif defined(OS_WIN)
766
[email protected]96449d2c2009-11-25 00:01:32767const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
768 sizeof(kPixelFormatDescriptor), // Size of structure.
769 1, // Default version.
770 PFD_DRAW_TO_WINDOW | // Window drawing support.
771 PFD_SUPPORT_OPENGL | // OpenGL support.
772 PFD_DOUBLEBUFFER, // Double buffering support (not stereo).
773 PFD_TYPE_RGBA, // RGBA color mode (not indexed).
774 24, // 24 bit color mode.
775 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts.
776 8, 0, // 8 bit alpha
777 0, // No accumulation buffer.
778 0, 0, 0, 0, // Ignore accumulation bits.
779 24, // 24 bit z-buffer size.
780 8, // 8-bit stencil buffer.
781 0, // No aux buffer.
782 PFD_MAIN_PLANE, // Main drawing plane (not overlay).
783 0, // Reserved.
784 0, 0, 0, // Layer masks ignored.
785};
786
787LRESULT CALLBACK IntermediateWindowProc(HWND window,
788 UINT message,
789 WPARAM w_param,
790 LPARAM l_param) {
791 return ::DefWindowProc(window, message, w_param, l_param);
792}
793
[email protected]246a70452010-03-05 21:53:50794// Helper routine that does one-off initialization like determining the
795// pixel format and initializing glew.
796bool GLES2DecoderImpl::InitializeOneOff(bool anti_aliased) {
[email protected]96449d2c2009-11-25 00:01:32797 // We must initialize a GL context before we can determine the multi-sampling
798 // supported on the current hardware, so we create an intermediate window
799 // and context here.
800 HINSTANCE module_handle;
801 if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
802 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
803 reinterpret_cast<wchar_t*>(IntermediateWindowProc),
804 &module_handle)) {
805 return false;
806 }
807
808 WNDCLASS intermediate_class;
809 intermediate_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
810 intermediate_class.lpfnWndProc = IntermediateWindowProc;
811 intermediate_class.cbClsExtra = 0;
812 intermediate_class.cbWndExtra = 0;
813 intermediate_class.hInstance = module_handle;
814 intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
815 intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
816 intermediate_class.hbrBackground = NULL;
817 intermediate_class.lpszMenuName = NULL;
818 intermediate_class.lpszClassName = L"Intermediate GL Window";
819
820 ATOM class_registration = ::RegisterClass(&intermediate_class);
821 if (!class_registration) {
822 return false;
823 }
824
825 HWND intermediate_window = ::CreateWindow(
826 reinterpret_cast<wchar_t*>(class_registration),
827 L"",
828 WS_OVERLAPPEDWINDOW,
829 0, 0,
830 CW_USEDEFAULT, CW_USEDEFAULT,
831 NULL,
832 NULL,
833 NULL,
834 NULL);
835
836 if (!intermediate_window) {
837 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
838 module_handle);
839 return false;
840 }
841
842 HDC intermediate_dc = ::GetDC(intermediate_window);
[email protected]246a70452010-03-05 21:53:50843 pixel_format_ = ::ChoosePixelFormat(intermediate_dc,
844 &kPixelFormatDescriptor);
845 if (pixel_format_ == 0) {
[email protected]96449d2c2009-11-25 00:01:32846 DLOG(ERROR) << "Unable to get 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 }
[email protected]246a70452010-03-05 21:53:50853 if (!::SetPixelFormat(intermediate_dc, pixel_format_,
[email protected]96449d2c2009-11-25 00:01:32854 &kPixelFormatDescriptor)) {
855 DLOG(ERROR) << "Unable to set the pixel format for GL context.";
856 ::ReleaseDC(intermediate_window, intermediate_dc);
857 ::DestroyWindow(intermediate_window);
858 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
859 module_handle);
860 return false;
861 }
862
[email protected]246a70452010-03-05 21:53:50863 // Create a temporary GL context to query for multisampled pixel formats.
[email protected]96449d2c2009-11-25 00:01:32864 HGLRC gl_context = ::wglCreateContext(intermediate_dc);
865 if (::wglMakeCurrent(intermediate_dc, gl_context)) {
866 // GL context was successfully created and applied to the window's DC.
867 // Startup GLEW, the GL extensions wrangler.
[email protected]246a70452010-03-05 21:53:50868 if (InitGlew()) {
[email protected]96449d2c2009-11-25 00:01:32869 DLOG(INFO) << "Initialized GLEW " << ::glewGetString(GLEW_VERSION);
870 } else {
[email protected]96449d2c2009-11-25 00:01:32871 ::wglMakeCurrent(intermediate_dc, NULL);
872 ::wglDeleteContext(gl_context);
873 ::ReleaseDC(intermediate_window, intermediate_dc);
874 ::DestroyWindow(intermediate_window);
875 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
876 module_handle);
877 return false;
878 }
879
880 // If the multi-sample extensions are present, query the api to determine
881 // the pixel format.
882 if (anti_aliased && WGLEW_ARB_pixel_format && WGLEW_ARB_multisample) {
883 int pixel_attributes[] = {
884 WGL_SAMPLES_ARB, 4,
885 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
886 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
887 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
888 WGL_COLOR_BITS_ARB, 24,
889 WGL_ALPHA_BITS_ARB, 8,
890 WGL_DEPTH_BITS_ARB, 24,
891 WGL_STENCIL_BITS_ARB, 8,
892 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
893 WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
894 0, 0};
895
896 float pixel_attributes_f[] = {0, 0};
897 int msaa_pixel_format;
898 unsigned int num_formats;
899
900 // Query for the highest sampling rate supported, starting at 4x.
901 static const int kSampleCount[] = {4, 2};
902 static const int kNumSamples = 2;
903 for (int sample = 0; sample < kNumSamples; ++sample) {
904 pixel_attributes[1] = kSampleCount[sample];
905 if (GL_TRUE == ::wglChoosePixelFormatARB(intermediate_dc,
906 pixel_attributes,
907 pixel_attributes_f,
908 1,
909 &msaa_pixel_format,
910 &num_formats)) {
[email protected]246a70452010-03-05 21:53:50911 pixel_format_ = msaa_pixel_format;
[email protected]96449d2c2009-11-25 00:01:32912 break;
913 }
914 }
915 }
916 }
917
918 ::wglMakeCurrent(intermediate_dc, NULL);
919 ::wglDeleteContext(gl_context);
920 ::ReleaseDC(intermediate_window, intermediate_dc);
921 ::DestroyWindow(intermediate_window);
922 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
923 module_handle);
924 return true;
925}
926
[email protected]69d80ae2009-12-23 08:57:42927#endif // OS_WIN
928
[email protected]07f54fcc2009-12-22 02:46:30929// These commands convert from c calls to local os calls.
930void GLGenBuffersHelper(
[email protected]a93bb842010-02-16 23:03:47931 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:30932 glGenBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:47933 // TODO(gman): handle error
934 for (GLsizei ii = 0; ii < n; ++ii) {
935 decoder->CreateBufferInfo(ids[ii]);
936 }
[email protected]07f54fcc2009-12-22 02:46:30937}
938
939void GLGenFramebuffersHelper(
940 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
941 glGenFramebuffersEXT(n, ids);
942}
943
944void GLGenRenderbuffersHelper(
945 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
946 glGenRenderbuffersEXT(n, ids);
947}
948
949void GLGenTexturesHelper(
[email protected]a93bb842010-02-16 23:03:47950 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:30951 glGenTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:47952 // TODO(gman): handle error
953 for (GLsizei ii = 0; ii < n; ++ii) {
954 decoder->CreateTextureInfo(ids[ii]);
955 }
[email protected]07f54fcc2009-12-22 02:46:30956}
957
958void GLDeleteBuffersHelper(
959 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
960 glDeleteBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:47961 // TODO(gman): handle error
[email protected]07f54fcc2009-12-22 02:46:30962 for (GLsizei ii = 0; ii < n; ++ii) {
963 decoder->RemoveBufferInfo(ids[ii]);
964 }
965}
966
967void GLDeleteFramebuffersHelper(
968 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
969 glDeleteFramebuffersEXT(n, ids);
970}
971
972void GLDeleteRenderbuffersHelper(
973 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
974 glDeleteRenderbuffersEXT(n, ids);
975}
976
977void GLDeleteTexturesHelper(
[email protected]a93bb842010-02-16 23:03:47978 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:30979 glDeleteTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:47980 // TODO(gman): handle error
981 for (GLsizei ii = 0; ii < n; ++ii) {
982 decoder->RemoveTextureInfo(ids[ii]);
983 }
[email protected]07f54fcc2009-12-22 02:46:30984}
985
[email protected]43f28f832010-02-03 02:28:48986// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:32987
[email protected]eb54a562010-01-20 21:55:18988bool GLES2DecoderImpl::MakeCurrent() {
989#if defined(UNIT_TEST)
990 return true;
991#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:50992 if (::wglGetCurrentDC() == gl_device_context_ &&
[email protected]eb54a562010-01-20 21:55:18993 ::wglGetCurrentContext() == gl_context_) {
994 return true;
995 }
[email protected]246a70452010-03-05 21:53:50996 if (!::wglMakeCurrent(gl_device_context_, gl_context_)) {
[email protected]eb54a562010-01-20 21:55:18997 DLOG(ERROR) << "Unable to make gl context current.";
998 return false;
999 }
1000 return true;
1001#elif defined(OS_LINUX)
1002 return window()->MakeCurrent();
[email protected]43f28f832010-02-03 02:28:481003#elif defined(OS_MACOSX)
1004 if (CGLGetCurrentContext() != gl_context_) {
1005 if (CGLSetCurrentContext(gl_context_) != kCGLNoError) {
1006 DLOG(ERROR) << "Unable to make gl context current.";
1007 return false;
1008 }
1009 }
1010 return true;
[email protected]eb54a562010-01-20 21:55:181011#else
1012 NOTREACHED();
1013 return false;
1014#endif
1015}
1016
[email protected]8a837bb2010-01-05 00:21:241017uint32 GLES2DecoderImpl::GetServiceIdForTesting(uint32 client_id) {
1018#if defined(UNIT_TEST)
1019 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501020 bool result = id_manager()->GetServiceId(client_id, &service_id);
[email protected]8a837bb2010-01-05 00:21:241021 return result ? service_id : 0u;
1022#else
1023 DCHECK(false);
1024 return 0u;
1025#endif
1026}
1027
1028bool GLES2DecoderImpl::ValidateIdsAreUnused(
1029 GLsizei n, const GLuint* client_ids) {
1030 for (GLsizei ii = 0; ii < n; ++ii) {
1031 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501032 if (id_manager()->GetServiceId(client_ids[ii], &service_id)) {
[email protected]8a837bb2010-01-05 00:21:241033 return false;
1034 }
1035 }
1036 return true;
1037}
1038
[email protected]07f54fcc2009-12-22 02:46:301039bool GLES2DecoderImpl::RegisterObjects(
1040 GLsizei n, const GLuint* client_ids, const GLuint* service_ids) {
1041 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501042 if (!id_manager()->AddMapping(client_ids[ii], service_ids[ii])) {
[email protected]8a837bb2010-01-05 00:21:241043 NOTREACHED();
1044 return false;
[email protected]07f54fcc2009-12-22 02:46:301045 }
1046 }
1047 return true;
1048}
1049
1050void GLES2DecoderImpl::UnregisterObjects(
1051 GLsizei n, const GLuint* client_ids, GLuint* service_ids) {
[email protected]07f54fcc2009-12-22 02:46:301052 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501053 if (id_manager()->GetServiceId(client_ids[ii], &service_ids[ii])) {
1054 id_manager()->RemoveMapping(client_ids[ii], service_ids[ii]);
[email protected]07f54fcc2009-12-22 02:46:301055 } else {
1056 service_ids[ii] = 0;
1057 }
1058 }
1059}
1060
[email protected]96449d2c2009-11-25 00:01:321061bool GLES2DecoderImpl::InitPlatformSpecific() {
[email protected]69d80ae2009-12-23 08:57:421062#if defined(UNIT_TEST)
1063#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:501064 // Do one-off initialization.
1065 static bool success = InitializeOneOff(anti_aliased_);
1066 if (!success)
[email protected]96449d2c2009-11-25 00:01:321067 return false;
[email protected]246a70452010-03-05 21:53:501068
1069 if (hwnd()) {
1070 // The GL context will render to this window.
1071 gl_device_context_ = ::GetDC(hwnd());
1072
1073 if (!::SetPixelFormat(gl_device_context_,
1074 pixel_format_,
1075 &kPixelFormatDescriptor)) {
1076 DLOG(ERROR) << "Unable to set the pixel format for GL context.";
1077 DestroyPlatformSpecific();
1078 return false;
1079 }
1080 } else {
1081 // Create a device context compatible with the primary display.
1082 HDC display_device_context = ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
1083
1084 // Create a 1 x 1 pbuffer suitable for use with the device.
1085 const int kNoAttributes[] = { 0 };
1086 pbuffer_ = ::wglCreatePbufferARB(display_device_context,
1087 pixel_format_,
1088 1, 1,
1089 kNoAttributes);
1090 ::DeleteDC(display_device_context);
1091 if (!pbuffer_) {
1092 DLOG(ERROR) << "Unable to create pbuffer.";
1093 DestroyPlatformSpecific();
1094 return false;
1095 }
1096
1097 gl_device_context_ = ::wglGetPbufferDCARB(pbuffer_);
1098 if (!gl_device_context_) {
1099 DLOG(ERROR) << "Unable to get pbuffer device context.";
1100 DestroyPlatformSpecific();
1101 return false;
1102 }
[email protected]96449d2c2009-11-25 00:01:321103 }
1104
[email protected]246a70452010-03-05 21:53:501105 gl_context_ = ::wglCreateContext(gl_device_context_);
[email protected]96449d2c2009-11-25 00:01:321106 if (!gl_context_) {
1107 DLOG(ERROR) << "Failed to create GL context.";
[email protected]246a70452010-03-05 21:53:501108 DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:321109 return false;
1110 }
[email protected]96449d2c2009-11-25 00:01:321111#elif defined(OS_LINUX)
1112 DCHECK(window());
1113 if (!window()->Initialize())
1114 return false;
[email protected]43f28f832010-02-03 02:28:481115#elif defined(OS_MACOSX)
1116 // Create a 1x1 pbuffer and associated context to bootstrap things
1117 static const CGLPixelFormatAttribute attribs[] = {
1118 (CGLPixelFormatAttribute) kCGLPFAPBuffer,
1119 (CGLPixelFormatAttribute) 0
1120 };
[email protected]246a70452010-03-05 21:53:501121 CGLPixelFormatObj pixel_format;
1122 GLint num_pixel_formats;
[email protected]43f28f832010-02-03 02:28:481123 if (CGLChoosePixelFormat(attribs,
[email protected]246a70452010-03-05 21:53:501124 &pixel_format,
1125 &num_pixel_formats) != kCGLNoError) {
[email protected]43f28f832010-02-03 02:28:481126 DLOG(ERROR) << "Error choosing pixel format.";
1127 return false;
1128 }
[email protected]246a70452010-03-05 21:53:501129 if (!pixel_format) {
[email protected]43f28f832010-02-03 02:28:481130 return false;
1131 }
1132 CGLContextObj context;
[email protected]246a70452010-03-05 21:53:501133 CGLError res = CGLCreateContext(pixel_format, 0, &context);
1134 CGLDestroyPixelFormat(pixel_format);
[email protected]43f28f832010-02-03 02:28:481135 if (res != kCGLNoError) {
1136 DLOG(ERROR) << "Error creating context.";
1137 return false;
1138 }
1139 CGLPBufferObj pbuffer;
1140 if (CGLCreatePBuffer(1, 1,
1141 GL_TEXTURE_2D, GL_RGBA,
1142 0, &pbuffer) != kCGLNoError) {
1143 CGLDestroyContext(context);
1144 DLOG(ERROR) << "Error creating pbuffer.";
1145 return false;
1146 }
1147 if (CGLSetPBuffer(context, pbuffer, 0, 0, 0) != kCGLNoError) {
1148 CGLDestroyContext(context);
1149 CGLDestroyPBuffer(pbuffer);
1150 DLOG(ERROR) << "Error attaching pbuffer to context.";
1151 return false;
1152 }
1153 gl_context_ = context;
1154 pbuffer_ = pbuffer;
1155 // Now we're ready to handle SetWindowSize calls, which will
1156 // allocate and/or reallocate the IOSurface and associated offscreen
1157 // OpenGL structures for rendering.
[email protected]96449d2c2009-11-25 00:01:321158#endif
1159
1160 return true;
1161}
1162
1163bool GLES2DecoderImpl::InitGlew() {
[email protected]69d80ae2009-12-23 08:57:421164#if !defined(UNIT_TEST)
[email protected]96449d2c2009-11-25 00:01:321165 DLOG(INFO) << "Initializing GL and GLEW for GLES2Decoder.";
1166
1167 GLenum glew_error = glewInit();
1168 if (glew_error != GLEW_OK) {
1169 DLOG(ERROR) << "Unable to initialise GLEW : "
1170 << ::glewGetErrorString(glew_error);
1171 return false;
1172 }
1173
1174 // Check to see that we can use the OpenGL vertex attribute APIs
1175 // TODO(petersont): Return false if this check fails, but because some
1176 // Intel hardware does not support OpenGL 2.0, yet does support all of the
1177 // extensions we require, we only log an error. A future CL should change
1178 // this check to ensure that all of the extension strings we require are
1179 // present.
1180 if (!GLEW_VERSION_2_0) {
1181 DLOG(ERROR) << "GL drivers do not have OpenGL 2.0 functionality.";
1182 }
1183
1184 bool extensions_found = true;
1185 if (!GLEW_ARB_vertex_buffer_object) {
1186 // NOTE: Linux NVidia drivers claim to support OpenGL 2.0 when using
1187 // indirect rendering (e.g. remote X), but it is actually lying. The
1188 // ARB_vertex_buffer_object functions silently no-op (!) when using
1189 // indirect rendering, leading to crashes. Fortunately, in that case, the
1190 // driver claims to not support ARB_vertex_buffer_object, so fail in that
1191 // case.
1192 DLOG(ERROR) << "GL drivers do not support vertex buffer objects.";
1193 extensions_found = false;
1194 }
1195 if (!GLEW_EXT_framebuffer_object) {
1196 DLOG(ERROR) << "GL drivers do not support framebuffer objects.";
1197 extensions_found = false;
1198 }
1199 // Check for necessary extensions
1200 if (!GLEW_VERSION_2_0 && !GLEW_EXT_stencil_two_side) {
1201 DLOG(ERROR) << "Two sided stencil extension missing.";
1202 extensions_found = false;
1203 }
1204 if (!GLEW_VERSION_1_4 && !GLEW_EXT_blend_func_separate) {
1205 DLOG(ERROR) <<"Separate blend func extension missing.";
1206 extensions_found = false;
1207 }
1208 if (!GLEW_VERSION_2_0 && !GLEW_EXT_blend_equation_separate) {
1209 DLOG(ERROR) << "Separate blend function extension missing.";
1210 extensions_found = false;
1211 }
1212 if (!extensions_found)
1213 return false;
[email protected]69d80ae2009-12-23 08:57:421214#endif
[email protected]96449d2c2009-11-25 00:01:321215
1216 return true;
1217}
1218
[email protected]246a70452010-03-05 21:53:501219void GLES2DecoderImpl::DestroyPlatformSpecific() {
1220#if defined(UNIT_TEST)
1221#elif defined(OS_WIN)
1222 if (gl_context_) {
1223 ::wglDeleteContext(gl_context_);
1224 }
1225
1226 if (gl_device_context_) {
1227 if (hwnd())
1228 ::ReleaseDC(hwnd(), gl_device_context_);
1229 else
1230 ::wglReleasePbufferDCARB(pbuffer_, gl_device_context_);
1231
1232 gl_device_context_ = NULL;
1233 }
1234
1235 if (pbuffer_) {
1236 ::wglDestroyPbufferARB(pbuffer_);
1237 pbuffer_ = NULL;
1238 }
1239#endif
1240}
1241
[email protected]6098b712010-02-09 17:59:341242#if defined(OS_MACOSX)
1243#if !defined(UNIT_TEST)
[email protected]43f28f832010-02-03 02:28:481244static void AddBooleanValue(CFMutableDictionaryRef dictionary,
1245 const CFStringRef key,
1246 bool value) {
1247 CFDictionaryAddValue(dictionary, key,
1248 (value ? kCFBooleanTrue : kCFBooleanFalse));
1249}
1250
1251static void AddIntegerValue(CFMutableDictionaryRef dictionary,
1252 const CFStringRef key,
1253 int32 value) {
1254 CFNumberRef number = CFNumberCreate(NULL, kCFNumberSInt32Type, &value);
1255 CFDictionaryAddValue(dictionary, key, number);
1256}
[email protected]6098b712010-02-09 17:59:341257#endif // !defined(UNIT_TEST)
[email protected]43f28f832010-02-03 02:28:481258
[email protected]1aef98132010-02-23 18:00:071259void GLES2DecoderImpl::AllocateRenderBuffers(GLenum target,
1260 int32 width, int32 height) {
1261 if (!texture_) {
1262 // Generate the texture object.
1263 glGenTextures(1, &texture_);
1264 glBindTexture(target, texture_);
1265 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1266 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1267 // Generate and bind the framebuffer object.
1268 glGenFramebuffersEXT(1, &fbo_);
1269 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
1270 bound_fbo_ = fbo_;
1271 // Generate (but don't bind) the depth buffer -- we don't need
1272 // this bound in order to do offscreen rendering.
1273 glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_);
1274 }
1275
1276 // Reallocate the depth buffer.
1277 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_renderbuffer_);
1278 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
1279 GL_DEPTH24_STENCIL8_EXT,
1280 width,
1281 height);
1282
1283 // Unbind the renderbuffers.
1284 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, bound_renderbuffer_);
1285
1286 // Make sure that subsequent set-up code affects the render texture.
1287 glBindTexture(target, texture_);
1288}
1289
1290bool GLES2DecoderImpl::SetupFrameBufferObject(GLenum target) {
1291 if (bound_fbo_ != fbo_) {
1292 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
1293 }
1294 GLenum fbo_status;
1295 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
1296 GL_COLOR_ATTACHMENT0_EXT,
1297 target,
1298 texture_,
1299 0);
1300 fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1301 if (fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT) {
1302 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
1303 GL_DEPTH_ATTACHMENT_EXT,
1304 GL_RENDERBUFFER_EXT,
1305 depth_stencil_renderbuffer_);
1306 fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1307 }
1308 // Attach the depth and stencil buffer.
1309 if (fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT) {
1310 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
1311 GL_STENCIL_ATTACHMENT,
1312 GL_RENDERBUFFER_EXT,
1313 depth_stencil_renderbuffer_);
1314 fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1315 }
1316 if (bound_fbo_ != fbo_) {
1317 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
1318 }
1319 return fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT;
1320}
1321
1322uint64 GLES2DecoderImpl::SetWindowSizeForIOSurface(int32 width, int32 height) {
[email protected]6098b712010-02-09 17:59:341323#if defined(UNIT_TEST)
1324 return 0;
1325#else
[email protected]43f28f832010-02-03 02:28:481326 if (surface_width_ == width && surface_height_ == height) {
1327 // Return 0 to indicate to the caller that no new backing store
1328 // allocation occurred.
1329 return 0;
1330 }
1331
1332 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
1333 if (!io_surface_support)
[email protected]1aef98132010-02-23 18:00:071334 return 0; // Caller can try using SetWindowSizeForTransportDIB().
[email protected]43f28f832010-02-03 02:28:481335
1336 if (!MakeCurrent())
1337 return 0;
1338
1339 // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on
1340 // Mac OS X and is required for IOSurface interoperability.
1341 GLenum target = GL_TEXTURE_RECTANGLE_ARB;
[email protected]1aef98132010-02-23 18:00:071342 AllocateRenderBuffers(target, width, height);
[email protected]43f28f832010-02-03 02:28:481343
1344 // Allocate a new IOSurface, which is the GPU resource that can be
1345 // shared across processes.
1346 scoped_cftyperef<CFMutableDictionaryRef> properties;
1347 properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault,
1348 0,
1349 &kCFTypeDictionaryKeyCallBacks,
1350 &kCFTypeDictionaryValueCallBacks));
1351 AddIntegerValue(properties,
1352 io_surface_support->GetKIOSurfaceWidth(), width);
1353 AddIntegerValue(properties,
1354 io_surface_support->GetKIOSurfaceHeight(), height);
1355 AddIntegerValue(properties,
1356 io_surface_support->GetKIOSurfaceBytesPerElement(), 4);
1357 AddBooleanValue(properties,
1358 io_surface_support->GetKIOSurfaceIsGlobal(), true);
1359 // I believe we should be able to unreference the IOSurfaces without
1360 // synchronizing with the browser process because they are
1361 // ultimately reference counted by the operating system.
1362 io_surface_.reset(io_surface_support->IOSurfaceCreate(properties));
1363
[email protected]43f28f832010-02-03 02:28:481364 // Don't think we need to identify a plane.
1365 GLuint plane = 0;
1366 io_surface_support->CGLTexImageIOSurface2D(gl_context_,
1367 target,
1368 GL_RGBA,
1369 width,
1370 height,
1371 GL_BGRA,
1372 GL_UNSIGNED_INT_8_8_8_8_REV,
1373 io_surface_.get(),
1374 plane);
[email protected]43f28f832010-02-03 02:28:481375 // Set up the frame buffer object.
[email protected]1aef98132010-02-23 18:00:071376 SetupFrameBufferObject(target);
[email protected]43f28f832010-02-03 02:28:481377 surface_width_ = width;
1378 surface_height_ = height;
1379
1380 // Now send back an identifier for the IOSurface. We originally
1381 // intended to send back a mach port from IOSurfaceCreateMachPort
1382 // but it looks like Chrome IPC would need to be modified to
1383 // properly send mach ports between processes. For the time being we
1384 // make our IOSurfaces global and send back their identifiers. On
1385 // the browser process side the identifier is reconstituted into an
1386 // IOSurface for on-screen rendering.
1387 return io_surface_support->IOSurfaceGetID(io_surface_);
[email protected]6098b712010-02-09 17:59:341388#endif // !defined(UNIT_TEST)
[email protected]43f28f832010-02-03 02:28:481389}
[email protected]1aef98132010-02-23 18:00:071390
1391TransportDIB::Handle GLES2DecoderImpl::SetWindowSizeForTransportDIB(
1392 int32 width, int32 height) {
1393#if defined(UNIT_TEST)
1394 return TransportDIB::DefaultHandleValue();
1395#else
1396 if (surface_width_ == width && surface_height_ == height) {
1397 // Return an invalid handle to indicate to the caller that no new backing
1398 // store allocation occurred.
1399 return TransportDIB::DefaultHandleValue();
1400 }
1401 surface_width_ = width;
1402 surface_height_ = height;
1403
1404 // Release the old TransportDIB in the browser.
1405 if (dib_free_callback_.get() && transport_dib_.get()) {
1406 dib_free_callback_->Run(transport_dib_->id());
1407 }
1408 transport_dib_.reset();
1409
1410 // Ask the renderer to create a TransportDIB.
1411 size_t dib_size = width * 4 * height; // 4 bytes per pixel.
1412 TransportDIB::Handle dib_handle;
1413 if (dib_alloc_callback_.get()) {
1414 dib_alloc_callback_->Run(dib_size, &dib_handle);
1415 }
1416 if (!TransportDIB::is_valid(dib_handle)) {
1417 // If the allocator fails, it means the DIB was not created in the browser,
1418 // so there is no need to run the deallocator here.
1419 return TransportDIB::DefaultHandleValue();
1420 }
1421 transport_dib_.reset(TransportDIB::Map(dib_handle));
1422 if (transport_dib_.get() == NULL) {
1423 // TODO(dspringer): if the Map() fails, should the deallocator be run so
1424 // that the DIB is deallocated in the browser?
1425 return TransportDIB::DefaultHandleValue();
1426 }
1427
1428 // Set up the render buffers and reserve enough space on the card for the
1429 // framebuffer texture.
1430 GLenum target = GL_TEXTURE_RECTANGLE_ARB;
1431 AllocateRenderBuffers(target, width, height);
1432 glTexImage2D(target,
1433 0, // mipmap level 0
1434 GL_RGBA8, // internal pixel format
1435 width,
1436 height,
1437 0, // 0 border
1438 GL_BGRA, // Used for consistency
1439 GL_UNSIGNED_INT_8_8_8_8_REV,
1440 NULL); // No data, just reserve room on the card.
1441 SetupFrameBufferObject(target);
1442 return transport_dib_->handle();
1443#endif // !defined(UNIT_TEST)
1444}
1445
1446void GLES2DecoderImpl::SetTransportDIBAllocAndFree(
1447 Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
1448 Callback1<TransportDIB::Id>::Type* deallocator) {
1449 dib_alloc_callback_.reset(allocator);
1450 dib_free_callback_.reset(deallocator);
1451}
[email protected]6098b712010-02-09 17:59:341452#endif // defined(OS_MACOSX)
[email protected]43f28f832010-02-03 02:28:481453
1454void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
1455 swap_buffers_callback_.reset(callback);
1456}
1457
[email protected]96449d2c2009-11-25 00:01:321458void GLES2DecoderImpl::Destroy() {
[email protected]69d80ae2009-12-23 08:57:421459#if defined(UNIT_TEST)
1460#elif defined(OS_LINUX)
[email protected]96449d2c2009-11-25 00:01:321461 DCHECK(window());
1462 window()->Destroy();
[email protected]43f28f832010-02-03 02:28:481463#elif defined(OS_MACOSX)
[email protected]1aef98132010-02-23 18:00:071464 // Release the old TransportDIB in the browser.
1465 if (dib_free_callback_.get() && transport_dib_.get()) {
1466 dib_free_callback_->Run(transport_dib_->id());
1467 }
1468 transport_dib_.reset();
[email protected]43f28f832010-02-03 02:28:481469 if (gl_context_)
1470 CGLDestroyContext(gl_context_);
1471 if (pbuffer_)
1472 CGLDestroyPBuffer(pbuffer_);
[email protected]96449d2c2009-11-25 00:01:321473#endif
[email protected]246a70452010-03-05 21:53:501474
1475 DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:321476}
1477
1478const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
1479 if (command_id > kStartPoint && command_id < kNumCommands) {
1480 return gles2::GetCommandName(static_cast<CommandId>(command_id));
1481 }
1482 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
1483}
1484
1485// Decode command with its arguments, and call the corresponding GL function.
1486// Note: args is a pointer to the command buffer. As such, it could be changed
1487// by a (malicious) client at any time, so if validation has to happen, it
1488// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:141489error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:321490 unsigned int command,
1491 unsigned int arg_count,
1492 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:141493 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191494 if (debug()) {
1495 // TODO(gman): Change output to something useful for NaCl.
[email protected]b9849abf2009-11-25 19:13:191496 printf("cmd: %s\n", GetCommandName(command));
1497 }
[email protected]96449d2c2009-11-25 00:01:321498 unsigned int command_index = command - kStartPoint - 1;
1499 if (command_index < arraysize(g_command_info)) {
1500 const CommandInfo& info = g_command_info[command_index];
1501 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
1502 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
1503 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:191504 uint32 immediate_data_size =
1505 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:321506 switch (command) {
1507 #define GLES2_CMD_OP(name) \
1508 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:191509 result = Handle ## name( \
1510 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321511 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:191512 break; \
[email protected]96449d2c2009-11-25 00:01:321513
1514 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:321515 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:381516 }
1517 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:301518 GLenum error;
1519 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:381520 // TODO(gman): Change output to something useful for NaCl.
[email protected]07f54fcc2009-12-22 02:46:301521 SetGLError(error);
[email protected]bf0985e2009-12-17 03:04:381522 printf("GL ERROR b4: %s\n", GetCommandName(command));
[email protected]b9849abf2009-11-25 19:13:191523 }
[email protected]96449d2c2009-11-25 00:01:321524 }
1525 } else {
[email protected]f7a64ee2010-02-01 22:24:141526 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:321527 }
[email protected]b9849abf2009-11-25 19:13:191528 } else {
1529 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:321530 }
[email protected]b9849abf2009-11-25 19:13:191531 return result;
[email protected]96449d2c2009-11-25 00:01:321532}
1533
[email protected]3916c97e2010-02-25 03:20:501534void GLES2DecoderImpl::RemoveBufferInfo(GLuint buffer_id) {
1535 buffer_manager()->RemoveBufferInfo(buffer_id);
1536 // TODO(gman): See if we can remove the rest of this function as
1537 // buffers are now reference counted and have a "IsDeleted" function.
1538 if (bound_array_buffer_ && bound_array_buffer_->buffer_id() == buffer_id) {
1539 bound_array_buffer_ = NULL;
1540 }
1541 if (bound_element_array_buffer_ &&
1542 bound_element_array_buffer_->buffer_id() == buffer_id) {
1543 bound_element_array_buffer_ = NULL;
1544 }
1545
1546 // go through VertexAttribInfo and update any info that references the buffer.
1547 for (GLuint ii = 0; ii < group_->max_vertex_attribs(); ++ii) {
1548 VertexAttribInfo& info = vertex_attrib_infos_[ii];
1549 if (info.buffer() && info.buffer()->buffer_id() == buffer_id) {
1550 info.ClearBuffer();
1551 }
1552 }
1553}
1554
[email protected]96449d2c2009-11-25 00:01:321555void GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
1556 // TODO(gman): verify client_id is unused.
1557 GLuint service_id = glCreateProgram();
1558 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501559 id_manager()->AddMapping(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:471560 CreateProgramInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321561 }
1562}
1563
1564void GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
1565 // TODO(gman): verify client_id is unused.
1566 GLuint service_id = glCreateShader(type);
1567 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501568 id_manager()->AddMapping(client_id, service_id);
[email protected]45bf5152010-02-12 00:11:311569 CreateShaderInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321570 }
1571}
1572
[email protected]3916c97e2010-02-25 03:20:501573void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
1574 if (texture_unit > group_->max_texture_units()) {
1575 SetGLError(GL_INVALID_ENUM);
1576 return;
1577 }
1578 active_texture_unit_ = texture_unit - GL_TEXTURE0;
1579}
1580
[email protected]96449d2c2009-11-25 00:01:321581void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:501582 BufferManager::BufferInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471583 if (buffer) {
[email protected]3916c97e2010-02-25 03:20:501584 info = GetBufferInfo(buffer);
[email protected]0c86dbf2010-03-05 08:14:111585 // Check the buffer exists
1586 // Check that we are not trying to bind it to a different target.
1587 if (!info || (info->target() != 0 && info->target() != target)) {
[email protected]a93bb842010-02-16 23:03:471588 SetGLError(GL_INVALID_OPERATION);
1589 return;
1590 }
[email protected]0c86dbf2010-03-05 08:14:111591 if (info->target() == 0) {
1592 info->set_target(target);
1593 }
[email protected]a93bb842010-02-16 23:03:471594 }
[email protected]96449d2c2009-11-25 00:01:321595 switch (target) {
1596 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501597 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321598 break;
1599 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501600 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321601 break;
1602 default:
[email protected]a93bb842010-02-16 23:03:471603 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:321604 break;
1605 }
1606 glBindBuffer(target, buffer);
1607}
1608
[email protected]a93bb842010-02-16 23:03:471609void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:501610 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471611 if (texture) {
[email protected]3916c97e2010-02-25 03:20:501612 info = GetTextureInfo(texture);
1613 // Check the texture exists
1614 // Check that we are not trying to bind it to a different target.
[email protected]a93bb842010-02-16 23:03:471615 if (!info || (info->target() != 0 && info->target() != target)) {
1616 SetGLError(GL_INVALID_OPERATION);
1617 return;
1618 }
1619 if (info->target() == 0) {
[email protected]3916c97e2010-02-25 03:20:501620 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:471621 }
1622 }
1623 glBindTexture(target, texture);
[email protected]3916c97e2010-02-25 03:20:501624 TextureUnit& unit = texture_units_[active_texture_unit_];
1625 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:471626 switch (target) {
1627 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501628 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:471629 break;
1630 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:501631 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:471632 break;
1633 default:
1634 NOTREACHED(); // Validation should prevent us getting here.
1635 break;
1636 }
1637}
1638
[email protected]07f54fcc2009-12-22 02:46:301639void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501640 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301641 vertex_attrib_infos_[index].set_enabled(false);
[email protected]8a837bb2010-01-05 00:21:241642 glDisableVertexAttribArray(index);
[email protected]07f54fcc2009-12-22 02:46:301643 } else {
1644 SetGLError(GL_INVALID_VALUE);
1645 }
1646}
1647
1648void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501649 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301650 vertex_attrib_infos_[index].set_enabled(true);
1651 glEnableVertexAttribArray(index);
1652 } else {
1653 SetGLError(GL_INVALID_VALUE);
1654 }
1655}
1656
[email protected]a93bb842010-02-16 23:03:471657void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:501658 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1659 if (!info || !info->MarkMipmapsGenerated()) {
[email protected]a93bb842010-02-16 23:03:471660 SetGLError(GL_INVALID_OPERATION);
1661 return;
1662 }
1663 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:471664}
1665
[email protected]f7a64ee2010-02-01 22:24:141666error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:461667 uint32 immediate_data_size, const gles2::DeleteShader& c) {
1668 GLuint shader = c.shader;
[email protected]96449d2c2009-11-25 00:01:321669 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501670 if (!id_manager()->GetServiceId(shader, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:461671 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141672 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321673 }
[email protected]45bf5152010-02-12 00:11:311674 RemoveShaderInfo(service_id);
[email protected]07f54fcc2009-12-22 02:46:301675 glDeleteShader(service_id);
[email protected]3916c97e2010-02-25 03:20:501676 id_manager()->RemoveMapping(shader, service_id);
[email protected]f7a64ee2010-02-01 22:24:141677 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321678}
1679
[email protected]f7a64ee2010-02-01 22:24:141680error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:461681 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
1682 GLuint program = c.program;
[email protected]96449d2c2009-11-25 00:01:321683 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501684 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:461685 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141686 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321687 }
[email protected]1d32bc82010-01-13 22:06:461688 RemoveProgramInfo(service_id);
[email protected]ba3176a2009-12-16 18:19:461689 glDeleteProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:501690 id_manager()->RemoveMapping(program, service_id);
[email protected]f7a64ee2010-02-01 22:24:141691 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321692}
1693
[email protected]07f54fcc2009-12-22 02:46:301694void GLES2DecoderImpl::DoDrawArrays(
1695 GLenum mode, GLint first, GLsizei count) {
1696 if (IsDrawValid(first + count - 1)) {
[email protected]3916c97e2010-02-25 03:20:501697 bool has_non_renderable_textures;
1698 SetBlackTextureForNonRenderableTextures(&has_non_renderable_textures);
[email protected]07f54fcc2009-12-22 02:46:301699 glDrawArrays(mode, first, count);
[email protected]3916c97e2010-02-25 03:20:501700 if (has_non_renderable_textures) {
1701 RestoreStateForNonRenderableTextures();
1702 }
[email protected]07f54fcc2009-12-22 02:46:301703 }
1704}
1705
1706void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]a93bb842010-02-16 23:03:471707 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
1708 if (!info) {
1709 SetGLError(GL_INVALID_OPERATION);
1710 return;
1711 }
[email protected]07f54fcc2009-12-22 02:46:301712 CopyRealGLErrorsToWrapper();
1713 glLinkProgram(program);
1714 GLenum error = glGetError();
1715 if (error != GL_NO_ERROR) {
1716 RemoveProgramInfo(program);
1717 SetGLError(error);
1718 } else {
[email protected]a93bb842010-02-16 23:03:471719 info->Update();
[email protected]07f54fcc2009-12-22 02:46:301720 }
1721};
1722
[email protected]96449d2c2009-11-25 00:01:321723void GLES2DecoderImpl::DoSwapBuffers() {
[email protected]69d80ae2009-12-23 08:57:421724#if defined(UNIT_TEST)
1725#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:501726 ::SwapBuffers(gl_device_context_);
[email protected]69d80ae2009-12-23 08:57:421727#elif defined(OS_LINUX)
[email protected]96449d2c2009-11-25 00:01:321728 DCHECK(window());
1729 window()->SwapBuffers();
[email protected]43f28f832010-02-03 02:28:481730#elif defined(OS_MACOSX)
[email protected]1aef98132010-02-23 18:00:071731 if (bound_fbo_ != fbo_) {
1732 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
1733 }
1734 if (io_surface_.get() != NULL) {
[email protected]43f28f832010-02-03 02:28:481735 // Bind and unbind the framebuffer to make changes to the
1736 // IOSurface show up in the other process.
1737 glFlush();
1738 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1739 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
[email protected]1aef98132010-02-23 18:00:071740 } else if (transport_dib_.get() != NULL) {
1741 // Pre-Mac OS X 10.6, fetch the rendered image from the FBO and copy it
1742 // into the TransportDIB.
1743 // TODO(dspringer): There are a couple of options that can speed this up.
1744 // First is to use async reads into a PBO, second is to use SPI that
1745 // allows many tasks to access the same CGSSurface.
1746 void* pixel_memory = transport_dib_->memory();
1747 if (pixel_memory) {
1748 // Note that glReadPixels does an implicit glFlush().
1749 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
1750 glReadPixels(0,
1751 0,
1752 surface_width_,
1753 surface_height_,
1754 GL_BGRA, // This pixel format should have no conversion.
1755 GL_UNSIGNED_INT_8_8_8_8_REV,
1756 pixel_memory);
1757 }
1758 }
1759 if (bound_fbo_ != fbo_) {
1760 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
[email protected]43f28f832010-02-03 02:28:481761 }
[email protected]96449d2c2009-11-25 00:01:321762#endif
[email protected]43f28f832010-02-03 02:28:481763 if (swap_buffers_callback_.get()) {
1764 swap_buffers_callback_->Run();
1765 }
[email protected]96449d2c2009-11-25 00:01:321766}
1767
[email protected]3916c97e2010-02-25 03:20:501768void GLES2DecoderImpl::DoTexParameterf(
1769 GLenum target, GLenum pname, GLfloat param) {
1770 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:301771 if (!info) {
[email protected]3916c97e2010-02-25 03:20:501772 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:301773 } else {
[email protected]3916c97e2010-02-25 03:20:501774 info->SetParameter(pname, static_cast<GLint>(param));
1775 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:301776 }
1777}
1778
[email protected]3916c97e2010-02-25 03:20:501779void GLES2DecoderImpl::DoTexParameteri(
1780 GLenum target, GLenum pname, GLint param) {
1781 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1782 if (!info) {
1783 SetGLError(GL_INVALID_VALUE);
1784 } else {
1785 info->SetParameter(pname, param);
1786 glTexParameteri(target, pname, param);
1787 }
1788}
1789
1790void GLES2DecoderImpl::DoTexParameterfv(
1791 GLenum target, GLenum pname, const GLfloat* params) {
1792 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1793 if (!info) {
1794 SetGLError(GL_INVALID_VALUE);
1795 } else {
1796 info->SetParameter(pname, *reinterpret_cast<const GLint*>(params));
1797 glTexParameterfv(target, pname, params);
1798 }
1799}
1800
1801void GLES2DecoderImpl::DoTexParameteriv(
1802 GLenum target, GLenum pname, const GLint* params) {
1803 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1804 if (!info) {
1805 SetGLError(GL_INVALID_VALUE);
1806 } else {
1807 info->SetParameter(pname, *params);
1808 glTexParameteriv(target, pname, params);
1809 }
1810}
1811
1812void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
1813 if (!current_program_ || current_program_->IsDeleted()) {
1814 // The program does not exist.
1815 SetGLError(GL_INVALID_OPERATION);
1816 return;
1817 }
1818 current_program_->SetSamplers(location, 1, &v0);
1819 glUniform1i(location, v0);
1820}
1821
1822void GLES2DecoderImpl::DoUniform1iv(
1823 GLint location, GLsizei count, const GLint *value) {
1824 if (!current_program_ || current_program_->IsDeleted()) {
1825 // The program does not exist.
1826 SetGLError(GL_INVALID_OPERATION);
1827 return;
1828 }
1829 current_program_->SetSamplers(location, count, value);
1830 glUniform1iv(location, count, value);
1831}
1832
1833void GLES2DecoderImpl::DoUseProgram(GLuint program) {
1834 ProgramManager::ProgramInfo* info = NULL;
1835 if (program) {
1836 info = GetProgramInfo(program);
1837 if (!info) {
1838 // Program was not linked successfully. (ie, glLinkProgram)
1839 SetGLError(GL_INVALID_OPERATION);
1840 return;
1841 }
1842 }
1843 current_program_ = info;
1844 glUseProgram(program);
1845}
1846
[email protected]96449d2c2009-11-25 00:01:321847GLenum GLES2DecoderImpl::GetGLError() {
1848 // Check the GL error first, then our wrapped error.
1849 GLenum error = glGetError();
1850 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:371851 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:321852 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:291853 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:321854 break;
1855 }
1856 }
1857 }
1858
1859 if (error != GL_NO_ERROR) {
1860 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:291861 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:321862 }
1863 return error;
1864}
1865
1866void GLES2DecoderImpl::SetGLError(GLenum error) {
[email protected]ddd968b82010-03-02 00:44:291867 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:321868}
1869
[email protected]07f54fcc2009-12-22 02:46:301870void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
1871 GLenum error;
1872 while ((error = glGetError()) != GL_NO_ERROR) {
1873 SetGLError(error);
1874 }
1875}
1876
[email protected]07f54fcc2009-12-22 02:46:301877bool GLES2DecoderImpl::VertexAttribInfo::CanAccess(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501878 if (!enabled_) {
1879 return true;
1880 }
1881
1882 if (!buffer_ || buffer_->IsDeleted()) {
1883 return false;
1884 }
1885
1886 // The number of elements that can be accessed.
1887 GLsizeiptr buffer_size = buffer_->size();
1888 if (offset_ > buffer_size || real_stride_ == 0) {
1889 return false;
1890 }
1891
1892 uint32 usable_size = buffer_size - offset_;
1893 GLuint num_elements = usable_size / real_stride_ +
1894 ((usable_size % real_stride_) >=
1895 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
1896 return index < num_elements;
1897}
1898
1899void GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures(
1900 bool* has_non_renderable_textures) {
1901 DCHECK(has_non_renderable_textures);
1902 DCHECK(current_program_);
1903 DCHECK(!current_program_->IsDeleted());
1904 *has_non_renderable_textures = false;
1905 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
1906 current_program_->sampler_indices();
1907 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
1908 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
1909 current_program_->GetUniformInfo(sampler_indices[ii]);
1910 DCHECK(uniform_info);
1911 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
1912 GLuint texture_unit_index = uniform_info->texture_units[jj];
1913 if (texture_unit_index < group_->max_texture_units()) {
1914 TextureUnit& texture_unit = texture_units_[texture_unit_index];
1915 TextureManager::TextureInfo* texture_info =
1916 uniform_info->type == GL_SAMPLER_2D ?
1917 texture_unit.bound_texture_2d :
1918 texture_unit.bound_texture_cube_map;
1919 if (!texture_info || !texture_info->CanRender()) {
1920 *has_non_renderable_textures = true;
1921 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
1922 glBindTexture(
1923 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
1924 GL_TEXTURE_CUBE_MAP,
1925 uniform_info->type == GL_SAMPLER_2D ? black_2d_texture_id_ :
1926 black_cube_texture_id_);
1927 }
1928 }
1929 // else: should this be an error?
1930 }
1931 }
1932}
1933
1934void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
1935 DCHECK(current_program_);
1936 DCHECK(!current_program_->IsDeleted());
1937 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
1938 current_program_->sampler_indices();
1939 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
1940 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
1941 current_program_->GetUniformInfo(sampler_indices[ii]);
1942 DCHECK(uniform_info);
1943 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
1944 GLuint texture_unit_index = uniform_info->texture_units[jj];
1945 if (texture_unit_index < group_->max_texture_units()) {
1946 TextureUnit& texture_unit = texture_units_[texture_unit_index];
1947 TextureManager::TextureInfo* texture_info =
1948 uniform_info->type == GL_SAMPLER_2D ?
1949 texture_unit.bound_texture_2d :
1950 texture_unit.bound_texture_cube_map;
1951 if (!texture_info || !texture_info->CanRender()) {
1952 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
1953 // Get the texture info that was previously bound here.
1954 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
1955 texture_unit.bound_texture_2d :
1956 texture_unit.bound_texture_cube_map;
1957 glBindTexture(texture_unit.bind_target,
1958 texture_info ? texture_info->texture_id() : 0);
1959 }
1960 }
1961 }
1962 }
1963 // Set the active texture back to whatever the user had it as.
1964 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:301965}
1966
1967bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]3916c97e2010-02-25 03:20:501968 if (!current_program_ || current_program_->IsDeleted()) {
1969 // The program does not exist.
1970 // But GL says no ERROR.
1971 return false;
1972 }
1973 // Validate that all attribs current program needs are setup correctly.
1974 const ProgramManager::ProgramInfo::AttribInfoVector& infos =
1975 current_program_->GetAttribInfos();
1976 for (size_t ii = 0; ii < infos.size(); ++ii) {
1977 GLint location = infos[ii].location;
1978 if (location < 0) {
1979 return false;
1980 }
1981 DCHECK_LT(static_cast<GLuint>(location), group_->max_vertex_attribs());
1982 if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:461983 SetGLError(GL_INVALID_OPERATION);
1984 return false;
1985 }
[email protected]07f54fcc2009-12-22 02:46:301986 }
[email protected]3916c97e2010-02-25 03:20:501987 return true;
[email protected]07f54fcc2009-12-22 02:46:301988};
1989
[email protected]f7a64ee2010-02-01 22:24:141990error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:191991 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:501992 if (!bound_element_array_buffer_ ||
1993 bound_element_array_buffer_->IsDeleted()) {
1994 SetGLError(GL_INVALID_OPERATION);
1995 } else {
[email protected]96449d2c2009-11-25 00:01:321996 GLenum mode = c.mode;
1997 GLsizei count = c.count;
1998 GLenum type = c.type;
[email protected]1d32bc82010-01-13 22:06:461999 int32 offset = c.index_offset;
[email protected]a76b0052010-03-05 00:33:182000 if (count < 0 || offset < 0) {
[email protected]d2cf0a2d2010-02-25 21:36:122001 SetGLError(GL_INVALID_VALUE);
2002 } else if (!ValidateGLenumDrawMode(mode) ||
2003 !ValidateGLenumIndexType(type)) {
[email protected]1d32bc82010-01-13 22:06:462004 SetGLError(GL_INVALID_ENUM);
[email protected]ba3176a2009-12-16 18:19:462005 } else {
[email protected]0c86dbf2010-03-05 08:14:112006 GLuint max_vertex_accessed;
2007 if (!bound_element_array_buffer_->GetMaxValueForRange(
2008 offset, count, type, &max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:462009 SetGLError(GL_INVALID_OPERATION);
2010 } else {
[email protected]0c86dbf2010-03-05 08:14:112011 if (IsDrawValid(max_vertex_accessed)) {
2012 bool has_non_renderable_textures;
2013 SetBlackTextureForNonRenderableTextures(
2014 &has_non_renderable_textures);
[email protected]3916c97e2010-02-25 03:20:502015 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]0c86dbf2010-03-05 08:14:112016 glDrawElements(mode, count, type, indices);
2017 if (has_non_renderable_textures) {
2018 RestoreStateForNonRenderableTextures();
[email protected]1d32bc82010-01-13 22:06:462019 }
2020 }
[email protected]07f54fcc2009-12-22 02:46:302021 }
[email protected]ba3176a2009-12-16 18:19:462022 }
[email protected]96449d2c2009-11-25 00:01:322023 }
[email protected]f7a64ee2010-02-01 22:24:142024 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322025}
2026
[email protected]96449d2c2009-11-25 00:01:322027// Calls glShaderSource for the various versions of the ShaderSource command.
2028// Assumes that data / data_size points to a piece of memory that is in range
2029// of whatever context it came from (shared memory, immediate memory, bucket
2030// memory.)
[email protected]45bf5152010-02-12 00:11:312031error::Error GLES2DecoderImpl::ShaderSourceHelper(
2032 GLuint shader, const char* data, uint32 data_size) {
2033 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2034 if (!info) {
2035 SetGLError(GL_INVALID_OPERATION);
2036 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322037 }
[email protected]45bf5152010-02-12 00:11:312038 // Note: We don't actually call glShaderSource here. We wait until
2039 // the call to glCompileShader.
2040 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:142041 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322042}
2043
[email protected]f7a64ee2010-02-01 22:24:142044error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:192045 uint32 immediate_data_size, const gles2::ShaderSource& c) {
2046 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:502047 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:192048 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142049 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192050 }
[email protected]96449d2c2009-11-25 00:01:322051 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:312052 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:322053 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:462054 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142055 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:322056 }
[email protected]45bf5152010-02-12 00:11:312057 return ShaderSourceHelper(shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:322058}
2059
[email protected]f7a64ee2010-02-01 22:24:142060error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:192061 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
2062 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:502063 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:192064 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142065 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192066 }
[email protected]96449d2c2009-11-25 00:01:322067 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:312068 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:302069 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462070 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142071 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:322072 }
[email protected]45bf5152010-02-12 00:11:312073 return ShaderSourceHelper(shader, data, data_size);
2074}
2075
2076void GLES2DecoderImpl::DoCompileShader(GLuint shader) {
2077 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2078 if (!info) {
2079 SetGLError(GL_INVALID_OPERATION);
2080 return;
2081 }
2082 // TODO(gman): Run shader through compiler that converts GL ES 2.0 shader
2083 // to DesktopGL shader and pass that to glShaderSource and then
2084 // glCompileShader.
2085 const char* ptr = info->source().c_str();
2086 glShaderSource(shader, 1, &ptr, NULL);
2087 glCompileShader(shader);
2088};
2089
[email protected]ddd968b82010-03-02 00:44:292090void GLES2DecoderImpl::DoGetShaderiv(
2091 GLuint shader, GLenum pname, GLint* params) {
2092 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2093 if (!info) {
2094 SetGLError(GL_INVALID_OPERATION);
2095 return;
2096 }
2097 if (pname == GL_SHADER_SOURCE_LENGTH) {
2098 *params = info->source().size();
2099 } else {
2100 glGetShaderiv(shader, pname, params);
2101 }
2102}
2103
[email protected]45bf5152010-02-12 00:11:312104void GLES2DecoderImpl::DoGetShaderSource(
2105 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst) {
2106 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2107 if (!info) {
2108 SetGLError(GL_INVALID_OPERATION);
2109 return;
2110 }
[email protected]a76b0052010-03-05 00:33:182111 // bufsize is set by the service side code and should always be positive.
2112 DCHECK_GT(bufsize, 0);
[email protected]45bf5152010-02-12 00:11:312113 const std::string& source = info->source();
2114 GLsizei size = std::min(bufsize - 1, static_cast<GLsizei>(source.size()));
2115 if (length) {
2116 *length = size;
2117 }
2118 memcpy(dst, source.c_str(), size);
2119 dst[size] = '\0';
[email protected]96449d2c2009-11-25 00:01:322120}
2121
[email protected]f7a64ee2010-02-01 22:24:142122error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:192123 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]3916c97e2010-02-25 03:20:502124 if (bound_array_buffer_ && !bound_array_buffer_->IsDeleted()) {
[email protected]96449d2c2009-11-25 00:01:322125 GLuint indx = c.indx;
2126 GLint size = c.size;
2127 GLenum type = c.type;
2128 GLboolean normalized = c.normalized;
2129 GLsizei stride = c.stride;
[email protected]07f54fcc2009-12-22 02:46:302130 GLsizei offset = c.offset;
2131 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]ba3176a2009-12-16 18:19:462132 if (!ValidateGLenumVertexAttribType(type) ||
[email protected]d2cf0a2d2010-02-25 21:36:122133 !ValidateGLintVertexAttribSize(size)) {
2134 SetGLError(GL_INVALID_ENUM);
2135 return error::kNoError;
2136 }
2137 if (indx >= group_->max_vertex_attribs() ||
2138 stride < 0 ||
2139 offset < 0) {
[email protected]ba3176a2009-12-16 18:19:462140 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142141 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322142 }
[email protected]3916c97e2010-02-25 03:20:502143 GLsizei component_size =
2144 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]07f54fcc2009-12-22 02:46:302145 GLsizei real_stride = stride != 0 ? stride : component_size * size;
2146 if (offset % component_size > 0) {
2147 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142148 return error::kNoError;
[email protected]07f54fcc2009-12-22 02:46:302149 }
2150 vertex_attrib_infos_[indx].SetInfo(
2151 bound_array_buffer_,
[email protected]07f54fcc2009-12-22 02:46:302152 size,
2153 type,
2154 real_stride,
2155 offset);
[email protected]96449d2c2009-11-25 00:01:322156 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
2157 } else {
2158 SetGLError(GL_INVALID_VALUE);
2159 }
[email protected]f7a64ee2010-02-01 22:24:142160 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322161}
2162
[email protected]f7a64ee2010-02-01 22:24:142163error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:192164 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:312165 GLint x = c.x;
2166 GLint y = c.y;
2167 GLsizei width = c.width;
2168 GLsizei height = c.height;
2169 GLenum format = c.format;
2170 GLenum type = c.type;
[email protected]a51788e2010-02-24 21:54:252171 // TODO(gman): Handle out of range rectangles.
2172 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:182173 uint32 pixels_size;
2174 if (!GLES2Util::ComputeImageDataSize(
2175 width, height, format, type, pack_alignment_, &pixels_size)) {
2176 return error::kOutOfBounds;
2177 }
[email protected]612d2f82009-12-08 20:49:312178 void* pixels = GetSharedMemoryAs<void*>(
2179 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:252180 Result* result = GetSharedMemoryAs<Result*>(
2181 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2182 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:142183 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462184 }
[email protected]a51788e2010-02-24 21:54:252185
[email protected]ba3176a2009-12-16 18:19:462186 if (!ValidateGLenumReadPixelFormat(format) ||
2187 !ValidateGLenumPixelType(type)) {
[email protected]d2cf0a2d2010-02-25 21:36:122188 SetGLError(GL_INVALID_ENUM);
2189 return error::kNoError;
2190 }
2191 if (width < 0 || height < 0) {
[email protected]ba3176a2009-12-16 18:19:462192 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142193 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:312194 }
[email protected]a51788e2010-02-24 21:54:252195 CopyRealGLErrorsToWrapper();
[email protected]612d2f82009-12-08 20:49:312196 glReadPixels(x, y, width, height, format, type, pixels);
[email protected]a51788e2010-02-24 21:54:252197 GLenum error = glGetError();
2198 if (error == GL_NO_ERROR) {
2199 *result = true;
2200 } else {
2201 SetGLError(error);
2202 }
[email protected]f7a64ee2010-02-01 22:24:142203 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322204}
2205
[email protected]f7a64ee2010-02-01 22:24:142206error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:192207 uint32 immediate_data_size, const gles2::PixelStorei& c) {
2208 GLenum pname = c.pname;
2209 GLenum param = c.param;
[email protected]d2cf0a2d2010-02-25 21:36:122210 if (!ValidateGLenumPixelStore(pname)) {
2211 SetGLError(GL_INVALID_ENUM);
2212 return error::kNoError;
2213 }
2214 if (!ValidateGLintPixelStoreAlignment(param)) {
[email protected]ba3176a2009-12-16 18:19:462215 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142216 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192217 }
2218 glPixelStorei(pname, param);
2219 switch (pname) {
2220 case GL_PACK_ALIGNMENT:
2221 pack_alignment_ = param;
2222 break;
2223 case GL_UNPACK_ALIGNMENT:
2224 unpack_alignment_ = param;
2225 break;
2226 default:
2227 // Validation should have prevented us from getting here.
2228 DCHECK(false);
2229 break;
2230 }
[email protected]f7a64ee2010-02-01 22:24:142231 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192232}
2233
[email protected]f7a64ee2010-02-01 22:24:142234error::Error GLES2DecoderImpl::HandleGetAttribLocation(
[email protected]b9849abf2009-11-25 19:13:192235 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
2236 GLuint program;
[email protected]3916c97e2010-02-25 03:20:502237 if (!id_manager()->GetServiceId(c.program, &program)) {
[email protected]b9849abf2009-11-25 19:13:192238 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142239 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192240 }
[email protected]0bfd9882010-02-05 23:02:252241 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2242 if (!info) {
2243 // Program was not linked successfully. (ie, glLinkProgram)
2244 SetGLError(GL_INVALID_OPERATION);
2245 return error::kNoError;
2246 }
[email protected]b9849abf2009-11-25 19:13:192247 uint32 name_size = c.data_size;
2248 const char* name = GetSharedMemoryAs<const char*>(
2249 c.name_shm_id, c.name_shm_offset, name_size);
2250 GLint* location = GetSharedMemoryAs<GLint*>(
2251 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
2252 if (!location || !name) {
[email protected]f7a64ee2010-02-01 22:24:142253 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192254 }
2255 String name_str(name, name_size);
[email protected]0bfd9882010-02-05 23:02:252256 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142257 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192258}
2259
[email protected]f7a64ee2010-02-01 22:24:142260error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192261 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
2262 GLuint program;
[email protected]3916c97e2010-02-25 03:20:502263 if (!id_manager()->GetServiceId(c.program, &program)) {
[email protected]b9849abf2009-11-25 19:13:192264 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142265 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192266 }
[email protected]0bfd9882010-02-05 23:02:252267 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2268 if (!info) {
2269 // Program was not linked successfully. (ie, glLinkProgram)
2270 SetGLError(GL_INVALID_OPERATION);
2271 return error::kNoError;
2272 }
[email protected]b9849abf2009-11-25 19:13:192273 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:302274 const char* name = GetImmediateDataAs<const char*>(
2275 c, name_size, immediate_data_size);
[email protected]b9849abf2009-11-25 19:13:192276 GLint* location = GetSharedMemoryAs<GLint*>(
2277 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
2278 if (!location || !name) {
[email protected]f7a64ee2010-02-01 22:24:142279 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192280 }
2281 String name_str(name, name_size);
[email protected]0bfd9882010-02-05 23:02:252282 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142283 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192284}
2285
[email protected]f7a64ee2010-02-01 22:24:142286error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:192287 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
2288 GLuint program;
[email protected]3916c97e2010-02-25 03:20:502289 if (!id_manager()->GetServiceId(c.program, &program)) {
[email protected]b9849abf2009-11-25 19:13:192290 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142291 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192292 }
[email protected]0bfd9882010-02-05 23:02:252293 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2294 if (!info) {
2295 // Program was not linked successfully. (ie, glLinkProgram)
2296 SetGLError(GL_INVALID_OPERATION);
2297 return error::kNoError;
2298 }
[email protected]b9849abf2009-11-25 19:13:192299 uint32 name_size = c.data_size;
2300 const char* name = GetSharedMemoryAs<const char*>(
2301 c.name_shm_id, c.name_shm_offset, name_size);
2302 GLint* location = GetSharedMemoryAs<GLint*>(
2303 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
2304 if (!location || !name) {
[email protected]f7a64ee2010-02-01 22:24:142305 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192306 }
2307 String name_str(name, name_size);
[email protected]0bfd9882010-02-05 23:02:252308 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142309 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192310}
2311
[email protected]f7a64ee2010-02-01 22:24:142312error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192313 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
2314 GLuint program;
[email protected]3916c97e2010-02-25 03:20:502315 if (!id_manager()->GetServiceId(c.program, &program)) {
[email protected]b9849abf2009-11-25 19:13:192316 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142317 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192318 }
[email protected]0bfd9882010-02-05 23:02:252319 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2320 if (!info) {
2321 // Program was not linked successfully. (ie, glLinkProgram)
2322 SetGLError(GL_INVALID_OPERATION);
2323 return error::kNoError;
2324 }
[email protected]b9849abf2009-11-25 19:13:192325 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:302326 const char* name = GetImmediateDataAs<const char*>(
2327 c, name_size, immediate_data_size);
[email protected]b9849abf2009-11-25 19:13:192328 GLint* location = GetSharedMemoryAs<GLint*>(
2329 c.location_shm_id, c.location_shm_offset, sizeof(GLint));
2330 if (!location || !name) {
[email protected]f7a64ee2010-02-01 22:24:142331 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192332 }
2333 String name_str(name, name_size);
[email protected]0bfd9882010-02-05 23:02:252334 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142335 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192336}
2337
[email protected]ddd968b82010-03-02 00:44:292338error::Error GLES2DecoderImpl::HandleGetString(
2339 uint32 immediate_data_size, const gles2::GetString& c) {
2340 GLenum name = static_cast<GLenum>(c.name);
2341 if (!ValidateGLenumStringType(name)) {
2342 SetGLError(GL_INVALID_ENUM);
2343 return error::kNoError;
2344 }
2345 Bucket* bucket = CreateBucket(c.bucket_id);
2346 bucket->SetFromString(reinterpret_cast<const char*>(glGetString(name)));
2347 return error::kNoError;
2348}
2349
[email protected]0c86dbf2010-03-05 08:14:112350void GLES2DecoderImpl::DoBufferData(
2351 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]3b6ec202010-03-05 05:16:232352 if (!ValidateGLenumBufferTarget(target) ||
2353 !ValidateGLenumBufferUsage(usage)) {
2354 SetGLError(GL_INVALID_ENUM);
[email protected]0c86dbf2010-03-05 08:14:112355 return;
[email protected]3b6ec202010-03-05 05:16:232356 }
2357 if (size < 0) {
2358 SetGLError(GL_INVALID_VALUE);
[email protected]0c86dbf2010-03-05 08:14:112359 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232360 }
2361 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
2362 if (!info) {
2363 SetGLError(GL_INVALID_OPERATION);
[email protected]0c86dbf2010-03-05 08:14:112364 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232365 }
2366 // Clear the buffer to 0 if no initial data was passed in.
2367 scoped_array<int8> zero;
2368 if (!data) {
2369 zero.reset(new int8[size]);
2370 memset(zero.get(), 0, size);
2371 data = zero.get();
2372 }
2373 CopyRealGLErrorsToWrapper();
2374 glBufferData(target, size, data, usage);
2375 GLenum error = glGetError();
2376 if (error != GL_NO_ERROR) {
2377 SetGLError(error);
2378 } else {
[email protected]0c86dbf2010-03-05 08:14:112379 info->SetSize(size);
2380 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:232381 }
[email protected]0c86dbf2010-03-05 08:14:112382}
2383
2384error::Error GLES2DecoderImpl::HandleBufferData(
2385 uint32 immediate_data_size, const gles2::BufferData& c) {
2386 GLenum target = static_cast<GLenum>(c.target);
2387 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
2388 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
2389 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
2390 GLenum usage = static_cast<GLenum>(c.usage);
2391 const void* data = NULL;
2392 if (data_shm_id != 0 || data_shm_offset != 0) {
2393 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
2394 if (!data) {
2395 return error::kOutOfBounds;
2396 }
2397 }
2398 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:142399 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192400}
2401
[email protected]f7a64ee2010-02-01 22:24:142402error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:192403 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
2404 GLenum target = static_cast<GLenum>(c.target);
2405 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:302406 const void* data = GetImmediateDataAs<const void*>(
2407 c, size, immediate_data_size);
2408 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142409 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:302410 }
[email protected]b9849abf2009-11-25 19:13:192411 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:112412 DoBufferData(target, size, data, usage);
2413 return error::kNoError;
2414}
2415
2416void GLES2DecoderImpl::DoBufferSubData(
2417 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:502418 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472419 if (!info) {
2420 SetGLError(GL_INVALID_OPERATION);
[email protected]a93bb842010-02-16 23:03:472421 }
[email protected]0c86dbf2010-03-05 08:14:112422 if (!info->SetRange(offset, size, data)) {
2423 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:302424 } else {
[email protected]0c86dbf2010-03-05 08:14:112425 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:302426 }
[email protected]b9849abf2009-11-25 19:13:192427}
2428
[email protected]a93bb842010-02-16 23:03:472429error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
2430 GLenum target,
2431 GLint level,
2432 GLenum internal_format,
2433 GLsizei width,
2434 GLsizei height,
2435 GLint border,
2436 GLsizei image_size,
2437 const void* data) {
2438 // TODO(gman): Validate internal_format
2439 // TODO(gman): Validate image_size is correct for width, height and format.
2440 if (!ValidateGLenumTextureTarget(target)) {
2441 SetGLError(GL_INVALID_ENUM);
2442 return error::kNoError;
2443 }
[email protected]3916c97e2010-02-25 03:20:502444 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:472445 border != 0) {
2446 SetGLError(GL_INVALID_VALUE);
2447 return error::kNoError;
2448 }
[email protected]3916c97e2010-02-25 03:20:502449 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472450 if (!info) {
2451 SetGLError(GL_INVALID_OPERATION);
2452 return error::kNoError;
2453 }
2454 scoped_array<int8> zero;
2455 if (!data) {
2456 zero.reset(new int8[image_size]);
2457 memset(zero.get(), 0, image_size);
2458 data = zero.get();
2459 }
2460 info->SetLevelInfo(
2461 target, level, internal_format, width, height, 1, border, 0, 0);
2462 glCompressedTexImage2D(
2463 target, level, internal_format, width, height, border, image_size, data);
2464 return error::kNoError;
2465}
2466
[email protected]f7a64ee2010-02-01 22:24:142467error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192468 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
2469 GLenum target = static_cast<GLenum>(c.target);
2470 GLint level = static_cast<GLint>(c.level);
2471 GLenum internal_format = static_cast<GLenum>(c.internalformat);
2472 GLsizei width = static_cast<GLsizei>(c.width);
2473 GLsizei height = static_cast<GLsizei>(c.height);
2474 GLint border = static_cast<GLint>(c.border);
2475 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
2476 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
2477 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
2478 const void* data = NULL;
2479 if (data_shm_id != 0 || data_shm_offset != 0) {
2480 data = GetSharedMemoryAs<const void*>(
2481 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:462482 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142483 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192484 }
2485 }
[email protected]a93bb842010-02-16 23:03:472486 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192487 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:192488}
2489
[email protected]f7a64ee2010-02-01 22:24:142490error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:192491 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
2492 GLenum target = static_cast<GLenum>(c.target);
2493 GLint level = static_cast<GLint>(c.level);
2494 GLenum internal_format = static_cast<GLenum>(c.internalformat);
2495 GLsizei width = static_cast<GLsizei>(c.width);
2496 GLsizei height = static_cast<GLsizei>(c.height);
2497 GLint border = static_cast<GLint>(c.border);
2498 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:302499 const void* data = GetImmediateDataAs<const void*>(
2500 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462501 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142502 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462503 }
[email protected]a93bb842010-02-16 23:03:472504 return DoCompressedTexImage2D(
2505 target, level, internal_format, width, height, border, image_size, data);
2506}
2507
[email protected]a93bb842010-02-16 23:03:472508error::Error GLES2DecoderImpl::DoTexImage2D(
2509 GLenum target,
2510 GLint level,
2511 GLenum internal_format,
2512 GLsizei width,
2513 GLsizei height,
2514 GLint border,
2515 GLenum format,
2516 GLenum type,
2517 const void* pixels,
2518 uint32 pixels_size) {
2519 if (!ValidateGLenumTextureTarget(target) ||
2520 !ValidateGLenumTextureFormat(internal_format) ||
2521 !ValidateGLenumTextureFormat(format) ||
2522 !ValidateGLenumPixelType(type)) {
[email protected]8bf5a3e2010-01-29 04:21:362523 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:142524 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192525 }
[email protected]3916c97e2010-02-25 03:20:502526 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:472527 border != 0) {
2528 SetGLError(GL_INVALID_VALUE);
2529 return error::kNoError;
2530 }
[email protected]3916c97e2010-02-25 03:20:502531 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472532 if (!info) {
2533 SetGLError(GL_INVALID_OPERATION);
2534 return error::kNoError;
2535 }
2536 scoped_array<int8> zero;
2537 if (!pixels) {
2538 zero.reset(new int8[pixels_size]);
2539 memset(zero.get(), 0, pixels_size);
2540 pixels = zero.get();
2541 }
2542 info->SetLevelInfo(
2543 target, level, internal_format, width, height, 1, border, format, type);
2544 glTexImage2D(
2545 target, level, internal_format, width, height, border, format, type,
2546 pixels);
[email protected]f7a64ee2010-02-01 22:24:142547 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192548}
2549
[email protected]f7a64ee2010-02-01 22:24:142550error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192551 uint32 immediate_data_size, const gles2::TexImage2D& c) {
2552 GLenum target = static_cast<GLenum>(c.target);
2553 GLint level = static_cast<GLint>(c.level);
2554 GLint internal_format = static_cast<GLint>(c.internalformat);
2555 GLsizei width = static_cast<GLsizei>(c.width);
2556 GLsizei height = static_cast<GLsizei>(c.height);
2557 GLint border = static_cast<GLint>(c.border);
2558 GLenum format = static_cast<GLenum>(c.format);
2559 GLenum type = static_cast<GLenum>(c.type);
2560 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
2561 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:182562 uint32 pixels_size;
2563 if (!GLES2Util::ComputeImageDataSize(
2564 width, height, format, type, unpack_alignment_, &pixels_size)) {
2565 return error::kOutOfBounds;
2566 }
[email protected]b9849abf2009-11-25 19:13:192567 const void* pixels = NULL;
2568 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
2569 pixels = GetSharedMemoryAs<const void*>(
2570 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:462571 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:142572 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192573 }
2574 }
[email protected]a93bb842010-02-16 23:03:472575 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192576 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:472577 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:192578}
2579
[email protected]f7a64ee2010-02-01 22:24:142580error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:192581 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
2582 GLenum target = static_cast<GLenum>(c.target);
2583 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:462584 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:192585 GLsizei width = static_cast<GLsizei>(c.width);
2586 GLsizei height = static_cast<GLsizei>(c.height);
2587 GLint border = static_cast<GLint>(c.border);
2588 GLenum format = static_cast<GLenum>(c.format);
2589 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:182590 uint32 size;
2591 if (!GLES2Util::ComputeImageDataSize(
2592 width, height, format, type, unpack_alignment_, &size)) {
2593 return error::kOutOfBounds;
2594 }
[email protected]07f54fcc2009-12-22 02:46:302595 const void* pixels = GetImmediateDataAs<const void*>(
2596 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462597 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:142598 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462599 }
[email protected]a93bb842010-02-16 23:03:472600 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:462601 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:472602 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:142603 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322604}
2605
[email protected]f7a64ee2010-02-01 22:24:142606error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:192607 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:362608 GLuint index = static_cast<GLuint>(c.index);
2609 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:252610 typedef gles2::GetVertexAttribPointerv::Result Result;
2611 Result* result = GetSharedMemoryAs<Result*>(
2612 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:362613 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:142614 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:362615 }
[email protected]07d0cc82010-02-17 04:51:402616 // Check that the client initialized the result.
2617 if (result->size != 0) {
2618 return error::kInvalidArguments;
2619 }
[email protected]8bf5a3e2010-01-29 04:21:362620 if (!ValidateGLenumVertexPointer(pname)) {
2621 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:142622 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:362623 }
[email protected]3916c97e2010-02-25 03:20:502624 if (index >= group_->max_vertex_attribs()) {
[email protected]8bf5a3e2010-01-29 04:21:362625 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142626 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:362627 }
[email protected]0bfd9882010-02-05 23:02:252628 result->SetNumResults(1);
2629 *result->GetData() = vertex_attrib_infos_[index].offset();
[email protected]f7a64ee2010-02-01 22:24:142630 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322631}
2632
[email protected]f7b85372010-02-03 01:11:372633bool GLES2DecoderImpl::GetUniformSetup(
2634 GLuint program, GLint location,
2635 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:252636 error::Error* error, GLuint* service_id, void** result_pointer) {
[email protected]f7b85372010-02-03 01:11:372637 *error = error::kNoError;
2638 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:252639 SizedResult<GLint>* result;
2640 result = GetSharedMemoryAs<SizedResult<GLint>*>(
2641 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
2642 if (!result) {
[email protected]f7b85372010-02-03 01:11:372643 *error = error::kOutOfBounds;
2644 return false;
2645 }
[email protected]0bfd9882010-02-05 23:02:252646 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:372647 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:252648 result->SetNumResults(0);
[email protected]3916c97e2010-02-25 03:20:502649 if (!id_manager()->GetServiceId(program, service_id)) {
[email protected]f7b85372010-02-03 01:11:372650 SetGLError(GL_INVALID_VALUE);
2651 return error::kNoError;
2652 }
2653 ProgramManager::ProgramInfo* info = GetProgramInfo(*service_id);
2654 if (!info) {
2655 // Program was not linked successfully. (ie, glLinkProgram)
2656 SetGLError(GL_INVALID_OPERATION);
2657 return false;
2658 }
[email protected]0bfd9882010-02-05 23:02:252659 GLenum type;
2660 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:372661 // No such location.
2662 SetGLError(GL_INVALID_OPERATION);
2663 return false;
2664 }
[email protected]3916c97e2010-02-25 03:20:502665 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:372666 if (size == 0) {
2667 SetGLError(GL_INVALID_OPERATION);
2668 return false;
2669 }
[email protected]0bfd9882010-02-05 23:02:252670 result = GetSharedMemoryAs<SizedResult<GLint>*>(
2671 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
2672 if (!result) {
[email protected]f7b85372010-02-03 01:11:372673 *error = error::kOutOfBounds;
2674 return false;
2675 }
[email protected]0bfd9882010-02-05 23:02:252676 result->size = size;
[email protected]f7b85372010-02-03 01:11:372677 return true;
2678}
2679
[email protected]f7a64ee2010-02-01 22:24:142680error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:192681 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:372682 GLuint program = c.program;
2683 GLint location = c.location;
2684 GLuint service_id;
2685 Error error;
[email protected]0bfd9882010-02-05 23:02:252686 void* result;
[email protected]f7b85372010-02-03 01:11:372687 if (GetUniformSetup(
2688 program, location, c.params_shm_id, c.params_shm_offset,
2689 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:252690 glGetUniformiv(
2691 service_id, location,
2692 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:372693 }
2694 return error;
[email protected]96449d2c2009-11-25 00:01:322695}
2696
[email protected]f7a64ee2010-02-01 22:24:142697error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:192698 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:372699 GLuint program = c.program;
2700 GLint location = c.location;
2701 GLuint service_id;
2702 Error error;
[email protected]0bfd9882010-02-05 23:02:252703 void* result;
2704 typedef gles2::GetUniformfv::Result Result;
[email protected]f7b85372010-02-03 01:11:372705 if (GetUniformSetup(
2706 program, location, c.params_shm_id, c.params_shm_offset,
2707 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:252708 glGetUniformfv(
2709 service_id,
2710 location,
2711 static_cast<gles2::GetUniformfv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:372712 }
2713 return error;
[email protected]96449d2c2009-11-25 00:01:322714}
2715
[email protected]f7a64ee2010-02-01 22:24:142716error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:192717 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:252718 GLenum shader_type = static_cast<GLenum>(c.shadertype);
2719 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
2720 typedef gles2::GetShaderPrecisionFormat::Result Result;
2721 Result* result = GetSharedMemoryAs<Result*>(
2722 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2723 if (!result) {
2724 return error::kOutOfBounds;
2725 }
[email protected]07d0cc82010-02-17 04:51:402726 // Check that the client initialized the result.
2727 if (result->success != 0) {
2728 return error::kInvalidArguments;
2729 }
[email protected]0bfd9882010-02-05 23:02:252730 if (!ValidateGLenumShaderType(shader_type) ||
2731 !ValidateGLenumShaderPrecision(precision_type)) {
[email protected]0bfd9882010-02-05 23:02:252732 SetGLError(GL_INVALID_ENUM);
2733 } else {
2734 result->success = 1; // true
2735 switch (precision_type) {
2736 case GL_LOW_INT:
2737 case GL_MEDIUM_INT:
2738 case GL_HIGH_INT:
2739 result->min_range = -31;
2740 result->max_range = 31;
2741 result->precision = 0;
2742 case GL_LOW_FLOAT:
2743 case GL_MEDIUM_FLOAT:
2744 case GL_HIGH_FLOAT:
2745 result->min_range = -62;
2746 result->max_range = 62;
2747 result->precision = -16;
2748 break;
2749 default:
2750 NOTREACHED();
2751 break;
2752 }
2753 }
[email protected]f7a64ee2010-02-01 22:24:142754 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322755}
2756
[email protected]f7a64ee2010-02-01 22:24:142757error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:192758 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:252759 GLuint service_id;
2760 uint32 result_size = c.result_size;
[email protected]3916c97e2010-02-25 03:20:502761 if (!id_manager()->GetServiceId(c.program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252762 SetGLError(GL_INVALID_VALUE);
2763 return error::kNoError;
2764 }
2765 typedef gles2::GetAttachedShaders::Result Result;
2766 uint32 max_count = Result::ComputeMaxResults(result_size);
2767 Result* result = GetSharedMemoryAs<Result*>(
2768 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
2769 if (!result) {
2770 return error::kOutOfBounds;
2771 }
[email protected]07d0cc82010-02-17 04:51:402772 // Check that the client initialized the result.
2773 if (result->size != 0) {
2774 return error::kInvalidArguments;
2775 }
[email protected]0bfd9882010-02-05 23:02:252776 GLsizei count = 0;
2777 glGetAttachedShaders(service_id, max_count, &count, result->GetData());
2778 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]3916c97e2010-02-25 03:20:502779 if (!id_manager()->GetClientId(result->GetData()[ii],
[email protected]0bfd9882010-02-05 23:02:252780 &result->GetData()[ii])) {
2781 NOTREACHED();
2782 return error::kGenericError;
2783 }
2784 }
2785 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:142786 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322787}
2788
[email protected]f7a64ee2010-02-01 22:24:142789error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:192790 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:252791 GLuint program = c.program;
2792 GLuint index = c.index;
2793 uint32 name_bucket_id = c.name_bucket_id;
2794 GLuint service_id;
2795 typedef gles2::GetActiveUniform::Result Result;
2796 Result* result = GetSharedMemoryAs<Result*>(
2797 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2798 if (!result) {
2799 return error::kOutOfBounds;
2800 }
[email protected]07d0cc82010-02-17 04:51:402801 // Check that the client initialized the result.
2802 if (result->success != 0) {
2803 return error::kInvalidArguments;
2804 }
[email protected]3916c97e2010-02-25 03:20:502805 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252806 SetGLError(GL_INVALID_VALUE);
2807 return error::kNoError;
2808 }
2809 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
2810 if (!info) {
2811 // Program was not linked successfully. (ie, glLinkProgram)
2812 SetGLError(GL_INVALID_OPERATION);
2813 return error::kNoError;
2814 }
2815 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2816 info->GetUniformInfo(index);
2817 if (!uniform_info) {
2818 SetGLError(GL_INVALID_VALUE);
2819 return error::kNoError;
2820 }
2821 result->success = 1; // true.
2822 result->size = uniform_info->size;
2823 result->type = uniform_info->type;
2824 Bucket* bucket = CreateBucket(name_bucket_id);
2825 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:142826 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322827}
2828
[email protected]f7a64ee2010-02-01 22:24:142829error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:192830 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:252831 GLuint program = c.program;
2832 GLuint index = c.index;
2833 uint32 name_bucket_id = c.name_bucket_id;
2834 GLuint service_id;
2835 typedef gles2::GetActiveAttrib::Result Result;
2836 Result* result = GetSharedMemoryAs<Result*>(
2837 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2838 if (!result) {
2839 return error::kOutOfBounds;
2840 }
[email protected]07d0cc82010-02-17 04:51:402841 // Check that the client initialized the result.
2842 if (result->success != 0) {
2843 return error::kInvalidArguments;
2844 }
[email protected]3916c97e2010-02-25 03:20:502845 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252846 SetGLError(GL_INVALID_VALUE);
2847 return error::kNoError;
2848 }
2849 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
2850 if (!info) {
2851 // Program was not linked successfully. (ie, glLinkProgram)
2852 SetGLError(GL_INVALID_OPERATION);
2853 return error::kNoError;
2854 }
2855 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
2856 info->GetAttribInfo(index);
2857 if (!attrib_info) {
2858 SetGLError(GL_INVALID_VALUE);
2859 return error::kNoError;
2860 }
2861 result->success = 1; // true.
2862 result->size = attrib_info->size;
2863 result->type = attrib_info->type;
2864 Bucket* bucket = CreateBucket(name_bucket_id);
2865 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:142866 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322867}
2868
2869// Include the auto-generated part of this file. We split this because it means
2870// we can easily edit the non-auto generated parts right here in this file
2871// instead of having to edit some template or the code generator.
2872#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
2873
2874} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:252875} // namespace gpu