blob: 512a819acd5b150e64539b72dafc7001e7531720 [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]a25fa872010-03-25 02:57:5823#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3224#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4625#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4726#include "gpu/command_buffer/service/id_manager.h"
27#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5828#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4729#include "gpu/command_buffer/service/shader_manager.h"
30#include "gpu/command_buffer/service/texture_manager.h"
[email protected]43f28f832010-02-03 02:28:4831#if defined(UNIT_TEST)
32#elif defined(OS_LINUX)
[email protected]872fe722010-02-02 16:03:3333// XWindowWrapper is stubbed out for unit-tests.
[email protected]be4f1882010-01-06 04:38:5534#include "gpu/command_buffer/service/x_utils.h"
[email protected]43f28f832010-02-03 02:28:4835#elif defined(OS_MACOSX)
[email protected]6c077af2010-03-19 14:01:3336#include "app/surface/accelerated_surface_mac.h"
[email protected]be4f1882010-01-06 04:38:5537#endif
[email protected]96449d2c2009-11-25 00:01:3238
[email protected]a7a27ace2009-12-12 00:11:2539namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3240namespace gles2 {
41
[email protected]07f54fcc2009-12-22 02:46:3042// Check that certain assumptions the code makes are true. There are places in
43// the code where shared memory is passed direclty to GL. Example, glUniformiv,
44// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
45// a few others) are 32bits. If they are not 32bits the code will have to change
46// to call those GL functions with service side memory and then copy the results
47// to shared memory, converting the sizes.
48COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
49 GLint_not_same_size_as_uint32);
50COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
51 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3752COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
53 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3054
[email protected]43f28f832010-02-03 02:28:4855// TODO(kbr): the use of this anonymous namespace core dumps the
56// linker on Mac OS X 10.6 when the symbol ordering file is used
57// namespace {
[email protected]96449d2c2009-11-25 00:01:3258
59// Returns the address of the first byte after a struct.
60template <typename T>
61const void* AddressAfterStruct(const T& pod) {
62 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
63}
64
[email protected]07f54fcc2009-12-22 02:46:3065// Returns the address of the frst byte after the struct or NULL if size >
66// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3267template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3068RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
69 uint32 size,
70 uint32 immediate_data_size) {
71 return (size <= immediate_data_size) ?
72 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
73 NULL;
[email protected]96449d2c2009-11-25 00:01:3274}
75
[email protected]07f54fcc2009-12-22 02:46:3076// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1877bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3278 GLuint count,
79 size_t size,
[email protected]a76b0052010-03-05 00:33:1880 unsigned int elements_per_unit,
81 uint32* dst) {
82 uint32 value;
83 if (!SafeMultiplyUint32(count, size, &value)) {
84 return false;
85 }
86 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
87 return false;
88 }
89 *dst = value;
90 return true;
[email protected]96449d2c2009-11-25 00:01:3291}
92
93// A struct to hold info about each command.
94struct CommandInfo {
95 int arg_flags; // How to handle the arguments for this command
96 int arg_count; // How many arguments are expected for this command.
97};
98
99// A table of CommandInfo for all the commands.
100const CommandInfo g_command_info[] = {
101 #define GLES2_CMD_OP(name) { \
102 name::kArgFlags, \
103 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
104
105 GLES2_COMMAND_LIST(GLES2_CMD_OP)
106
107 #undef GLES2_CMD_OP
108};
109
[email protected]43f28f832010-02-03 02:28:48110// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32111
[email protected]3916c97e2010-02-25 03:20:50112GLES2Decoder::GLES2Decoder(ContextGroup* group)
113 : group_(group),
[email protected]69d80ae2009-12-23 08:57:42114#if defined(UNIT_TEST)
[email protected]3916c97e2010-02-25 03:20:50115 debug_(false) {
[email protected]69d80ae2009-12-23 08:57:42116#elif defined(OS_LINUX)
[email protected]3916c97e2010-02-25 03:20:50117 debug_(false),
[email protected]b9849abf2009-11-25 19:13:19118 window_(NULL) {
119#elif defined(OS_WIN)
[email protected]3916c97e2010-02-25 03:20:50120 debug_(false),
[email protected]b9849abf2009-11-25 19:13:19121 hwnd_(NULL) {
122#else
[email protected]3916c97e2010-02-25 03:20:50123 debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32124#endif
125}
126
[email protected]3916c97e2010-02-25 03:20:50127GLES2Decoder::~GLES2Decoder() {
128}
129
[email protected]96449d2c2009-11-25 00:01:32130// This class implements GLES2Decoder so we don't have to expose all the GLES2
131// cmd stuff to outside this class.
132class GLES2DecoderImpl : public GLES2Decoder {
133 public:
[email protected]3916c97e2010-02-25 03:20:50134 explicit GLES2DecoderImpl(ContextGroup* group);
135
[email protected]07f54fcc2009-12-22 02:46:30136 // Info about Vertex Attributes. This is used to track what the user currently
137 // has bound on each Vertex Attribute so that checking can be done at
138 // glDrawXXX time.
139 class VertexAttribInfo {
140 public:
141 VertexAttribInfo()
142 : enabled_(false),
143 size_(0),
144 type_(0),
145 offset_(0),
[email protected]3916c97e2010-02-25 03:20:50146 real_stride_(0) {
[email protected]07f54fcc2009-12-22 02:46:30147 }
[email protected]3916c97e2010-02-25 03:20:50148
[email protected]07f54fcc2009-12-22 02:46:30149 // Returns true if this VertexAttrib can access index.
150 bool CanAccess(GLuint index);
151
152 void set_enabled(bool enabled) {
153 enabled_ = enabled;
154 }
155
[email protected]3916c97e2010-02-25 03:20:50156 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30157 return buffer_;
158 }
159
[email protected]8bf5a3e2010-01-29 04:21:36160 GLsizei offset() const {
161 return offset_;
162 }
163
[email protected]07f54fcc2009-12-22 02:46:30164 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50165 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30166 GLint size,
167 GLenum type,
168 GLsizei real_stride,
169 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24170 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30171 buffer_ = buffer;
172 size_ = size;
173 type_ = type;
174 real_stride_ = real_stride;
175 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50176 }
177
178 void ClearBuffer() {
179 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30180 }
181
182 private:
183 // Whether or not this attribute is enabled.
184 bool enabled_;
185
186 // number of components (1, 2, 3, 4)
187 GLint size_;
188
189 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
190 GLenum type_;
191
192 // The offset into the buffer.
193 GLsizei offset_;
194
195 // The stride that will be used to access the buffer. This is the actual
196 // stide, NOT the GL bogus stride. In other words there is never a stride
197 // of 0.
198 GLsizei real_stride_;
199
[email protected]3916c97e2010-02-25 03:20:50200 // The buffer bound to this attribute.
201 BufferManager::BufferInfo::Ref buffer_;
[email protected]07f54fcc2009-12-22 02:46:30202 };
203
[email protected]96449d2c2009-11-25 00:01:32204 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14205 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50206 unsigned int arg_count,
207 const void* args);
[email protected]96449d2c2009-11-25 00:01:32208
209 // Overridden from AsyncAPIInterface.
210 virtual const char* GetCommandName(unsigned int command_id) const;
211
212 // Overridden from GLES2Decoder.
213 virtual bool Initialize();
[email protected]96449d2c2009-11-25 00:01:32214 virtual void Destroy();
[email protected]eb54a562010-01-20 21:55:18215 virtual bool MakeCurrent();
[email protected]8a837bb2010-01-05 00:21:24216 virtual uint32 GetServiceIdForTesting(uint32 client_id);
[email protected]56ac89b2010-03-17 21:16:55217 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]8a837bb2010-01-05 00:21:24218
[email protected]6098b712010-02-09 17:59:34219#if defined(OS_MACOSX)
[email protected]43f28f832010-02-03 02:28:48220 // Overridden from GLES2Decoder.
[email protected]1aef98132010-02-23 18:00:07221
222 // The recommended usage is to call SetWindowSizeForIOSurface() first, and if
223 // that returns 0, try calling SetWindowSizeForTransportDIB(). A return value
224 // of 0 from SetWindowSizeForIOSurface() might mean the IOSurface API is not
225 // available, which is true if you are not running on Max OS X 10.6 or later.
226 // If SetWindowSizeForTransportDIB() also returns a NULL handle, then an
227 // error has occured.
228 virtual uint64 SetWindowSizeForIOSurface(int32 width, int32 height);
229 virtual TransportDIB::Handle SetWindowSizeForTransportDIB(int32 width,
230 int32 height);
231 // |allocator| sends a message to the renderer asking for a new
232 // TransportDIB big enough to hold the rendered bits. The parameters to the
233 // call back are the size of the DIB and the handle (filled in on return).
234 virtual void SetTransportDIBAllocAndFree(
235 Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
236 Callback1<TransportDIB::Id>::Type* deallocator);
[email protected]43f28f832010-02-03 02:28:48237#endif
238
239 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
240
[email protected]96449d2c2009-11-25 00:01:32241 private:
[email protected]3916c97e2010-02-25 03:20:50242 // State associated with each texture unit.
243 struct TextureUnit {
244 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
245
246 // The last target that was bound to this texture unit.
247 GLenum bind_target;
248
249 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
250 TextureManager::TextureInfo::Ref bound_texture_2d;
251
252 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
253 // glBindTexture
254 TextureManager::TextureInfo::Ref bound_texture_cube_map;
255 };
256
[email protected]a93bb842010-02-16 23:03:47257 friend void GLGenTexturesHelper(
258 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
259 friend void GLDeleteTexturesHelper(
260 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
261 friend void GLGenBuffersHelper(
262 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
263 friend void GLDeleteBuffersHelper(
264 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
[email protected]a25fa872010-03-25 02:57:58265 friend void GLGenFramebuffersHelper(
266 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
267 friend void GLDeleteFramebuffersHelper(
268 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
269 friend void GLGenRenderbuffersHelper(
270 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
271 friend void GLDeleteRenderbuffersHelper(
272 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
[email protected]a93bb842010-02-16 23:03:47273
[email protected]3916c97e2010-02-25 03:20:50274 // TODO(gman): Cache these pointers?
275 IdManager* id_manager() {
276 return group_->id_manager();
277 }
278
279 BufferManager* buffer_manager() {
280 return group_->buffer_manager();
281 }
282
[email protected]a25fa872010-03-25 02:57:58283 RenderbufferManager* renderbuffer_manager() {
284 return group_->renderbuffer_manager();
285 }
286
287 FramebufferManager* framebuffer_manager() {
288 return group_->framebuffer_manager();
289 }
290
[email protected]3916c97e2010-02-25 03:20:50291 ProgramManager* program_manager() {
292 return group_->program_manager();
293 }
294
295 ShaderManager* shader_manager() {
296 return group_->shader_manager();
297 }
298
299 TextureManager* texture_manager() {
300 return group_->texture_manager();
301 }
302
[email protected]246a70452010-03-05 21:53:50303#if defined(OS_WIN)
304 static bool InitializeOneOff(bool anti_aliased);
305#endif
306
307
[email protected]96449d2c2009-11-25 00:01:32308 bool InitPlatformSpecific();
[email protected]246a70452010-03-05 21:53:50309 static bool InitGlew();
310 void DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:32311
[email protected]96449d2c2009-11-25 00:01:32312 // Template to help call glGenXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30313 template <void gl_gen_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32314 bool GenGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12315 DCHECK_GE(n, 0);
[email protected]8a837bb2010-01-05 00:21:24316 if (!ValidateIdsAreUnused(n, client_ids)) {
317 return false;
318 }
[email protected]96449d2c2009-11-25 00:01:32319 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30320 gl_gen_function(this, n, temp.get());
[email protected]07f54fcc2009-12-22 02:46:30321 return RegisterObjects(n, client_ids, temp.get());
[email protected]96449d2c2009-11-25 00:01:32322 }
323
324 // Template to help call glDeleteXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30325 template <void gl_delete_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32326 bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12327 DCHECK_GE(n, 0);
[email protected]96449d2c2009-11-25 00:01:32328 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30329 UnregisterObjects(n, client_ids, temp.get());
330 gl_delete_function(this, n, temp.get());
[email protected]96449d2c2009-11-25 00:01:32331 return true;
332 }
333
[email protected]8a837bb2010-01-05 00:21:24334 // Check that the given ids are not used.
335 bool ValidateIdsAreUnused(GLsizei n, const GLuint* client_ids);
336
[email protected]07f54fcc2009-12-22 02:46:30337 // Register client ids with generated service ids.
338 bool RegisterObjects(
339 GLsizei n, const GLuint* client_ids, const GLuint* service_ids);
340
341 // Unregisters client ids with service ids.
342 void UnregisterObjects(
343 GLsizei n, const GLuint* client_ids, GLuint* service_ids);
344
[email protected]a93bb842010-02-16 23:03:47345 // Creates a TextureInfo for the given texture.
346 void CreateTextureInfo(GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:50347 texture_manager()->CreateTextureInfo(texture);
[email protected]a93bb842010-02-16 23:03:47348 }
349
350 // Gets the texture info for the given texture. Returns NULL if none exists.
351 TextureManager::TextureInfo* GetTextureInfo(GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:50352 TextureManager::TextureInfo* info =
353 texture_manager()->GetTextureInfo(texture);
354 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47355 }
356
357 // Deletes the texture info for the given texture.
[email protected]3916c97e2010-02-25 03:20:50358 void RemoveTextureInfo(GLuint texture) {
359 texture_manager()->RemoveTextureInfo(texture);
360 }
[email protected]a93bb842010-02-16 23:03:47361
362 // Wrapper for CompressedTexImage2D commands.
363 error::Error DoCompressedTexImage2D(
364 GLenum target,
365 GLint level,
366 GLenum internal_format,
367 GLsizei width,
368 GLsizei height,
369 GLint border,
370 GLsizei image_size,
371 const void* data);
372
373 // Wrapper for TexImage2D commands.
374 error::Error DoTexImage2D(
375 GLenum target,
376 GLint level,
377 GLenum internal_format,
378 GLsizei width,
379 GLsizei height,
380 GLint border,
381 GLenum format,
382 GLenum type,
383 const void* pixels,
384 uint32 pixels_size);
385
386 // Creates a ProgramInfo for the given program.
387 void CreateProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50388 program_manager()->CreateProgramInfo(program);
[email protected]a93bb842010-02-16 23:03:47389 }
390
[email protected]07f54fcc2009-12-22 02:46:30391 // Gets the program info for the given program. Returns NULL if none exists.
392 // Programs that have no had glLinkProgram succesfully called on them will
393 // not exist.
[email protected]1d32bc82010-01-13 22:06:46394 ProgramManager::ProgramInfo* GetProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50395 ProgramManager::ProgramInfo* info =
396 program_manager()->GetProgramInfo(program);
397 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46398 }
[email protected]07f54fcc2009-12-22 02:46:30399
[email protected]07f54fcc2009-12-22 02:46:30400 // Deletes the program info for the given program.
[email protected]1d32bc82010-01-13 22:06:46401 void RemoveProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50402 program_manager()->RemoveProgramInfo(program);
[email protected]1d32bc82010-01-13 22:06:46403 }
[email protected]07f54fcc2009-12-22 02:46:30404
[email protected]45bf5152010-02-12 00:11:31405 // Creates a ShaderInfo for the given shader.
406 void CreateShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50407 shader_manager()->CreateShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31408 }
409
410 // Gets the shader info for the given shader. Returns NULL if none exists.
411 ShaderManager::ShaderInfo* GetShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50412 ShaderManager::ShaderInfo* info = shader_manager()->GetShaderInfo(shader);
413 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]45bf5152010-02-12 00:11:31414 }
415
416 // Deletes the shader info for the given shader.
417 void RemoveShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50418 shader_manager()->RemoveShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31419 }
420
[email protected]a93bb842010-02-16 23:03:47421 // Creates a buffer info for the given buffer.
422 void CreateBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50423 return buffer_manager()->CreateBufferInfo(buffer);
[email protected]a93bb842010-02-16 23:03:47424 }
425
[email protected]07f54fcc2009-12-22 02:46:30426 // Gets the buffer info for the given buffer.
[email protected]1d32bc82010-01-13 22:06:46427 BufferManager::BufferInfo* GetBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50428 BufferManager::BufferInfo* info = buffer_manager()->GetBufferInfo(buffer);
429 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46430 }
[email protected]07f54fcc2009-12-22 02:46:30431
[email protected]a93bb842010-02-16 23:03:47432 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
433 // on glDeleteBuffers so we can make sure the user does not try to render
434 // with deleted buffers.
435 void RemoveBufferInfo(GLuint buffer_id);
436
[email protected]a25fa872010-03-25 02:57:58437 // Creates a framebuffer info for the given framebuffer.
438 void CreateFramebufferInfo(GLuint framebuffer) {
439 return framebuffer_manager()->CreateFramebufferInfo(framebuffer);
440 }
441
442 // Gets the framebuffer info for the given framebuffer.
443 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
444 GLuint framebuffer) {
445 FramebufferManager::FramebufferInfo* info =
446 framebuffer_manager()->GetFramebufferInfo(framebuffer);
447 return (info && !info->IsDeleted()) ? info : NULL;
448 }
449
450 // Removes the framebuffer info for the given framebuffer.
451 void RemoveFramebufferInfo(GLuint framebuffer_id) {
452 framebuffer_manager()->RemoveFramebufferInfo(framebuffer_id);
453 }
454
455 // Creates a renderbuffer info for the given renderbuffer.
456 void CreateRenderbufferInfo(GLuint renderbuffer) {
457 return renderbuffer_manager()->CreateRenderbufferInfo(renderbuffer);
458 }
459
460 // Gets the renderbuffer info for the given renderbuffer.
461 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
462 GLuint renderbuffer) {
463 RenderbufferManager::RenderbufferInfo* info =
464 renderbuffer_manager()->GetRenderbufferInfo(renderbuffer);
465 return (info && !info->IsDeleted()) ? info : NULL;
466 }
467
468 // Removes the renderbuffer info for the given renderbuffer.
469 void RemoveRenderbufferInfo(GLuint renderbuffer_id) {
470 renderbuffer_manager()->RemoveRenderbufferInfo(renderbuffer_id);
471 }
472
[email protected]558847a2010-03-24 07:02:54473 error::Error GetAttribLocationHelper(
474 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
475 const std::string& name_str);
476
477 error::Error GetUniformLocationHelper(
478 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
479 const std::string& name_str);
480
[email protected]3916c97e2010-02-25 03:20:50481 // Helper for glShaderSource.
482 error::Error ShaderSourceHelper(
483 GLuint shader, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30484
[email protected]96449d2c2009-11-25 00:01:32485 // Wrapper for glCreateProgram
486 void CreateProgramHelper(GLuint client_id);
487
488 // Wrapper for glCreateShader
489 void CreateShaderHelper(GLenum type, GLuint client_id);
490
[email protected]3916c97e2010-02-25 03:20:50491 // Wrapper for glActiveTexture
492 void DoActiveTexture(GLenum texture_unit);
493
[email protected]96449d2c2009-11-25 00:01:32494 // Wrapper for glBindBuffer since we need to track the current targets.
495 void DoBindBuffer(GLenum target, GLuint buffer);
496
[email protected]86093972010-03-11 00:13:56497 // Wrapper for glBindFramebuffer since we need to track the current targets.
498 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
499
500 // Wrapper for glBindRenderbuffer since we need to track the current targets.
501 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
502
[email protected]a93bb842010-02-16 23:03:47503 // Wrapper for glBindTexture since we need to track the current targets.
504 void DoBindTexture(GLenum target, GLuint texture);
505
[email protected]36cef8ce2010-03-16 07:34:45506 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11507 void DoBufferData(
508 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
509
[email protected]36cef8ce2010-03-16 07:34:45510 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11511 void DoBufferSubData(
512 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
513
[email protected]36cef8ce2010-03-16 07:34:45514 // Wrapper for glCheckFramebufferStatus
515 GLenum DoCheckFramebufferStatus(GLenum target);
516
[email protected]45bf5152010-02-12 00:11:31517 // Wrapper for glCompileShader.
518 void DoCompileShader(GLuint shader);
519
[email protected]07f54fcc2009-12-22 02:46:30520 // Wrapper for glDrawArrays.
521 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
522
523 // Wrapper for glDisableVertexAttribArray.
524 void DoDisableVertexAttribArray(GLuint index);
525
526 // Wrapper for glEnableVertexAttribArray.
527 void DoEnableVertexAttribArray(GLuint index);
528
[email protected]36cef8ce2010-03-16 07:34:45529 // Wrapper for glFramebufferRenderbufffer.
530 void DoFramebufferRenderbuffer(
531 GLenum target, GLenum attachment, GLenum renderbuffertarget,
532 GLuint renderbuffer);
533
534 // Wrapper for glFramebufferTexture2D.
535 void DoFramebufferTexture2D(
536 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
537 GLint level);
538
[email protected]a93bb842010-02-16 23:03:47539 // Wrapper for glGenerateMipmap
540 void DoGenerateMipmap(GLenum target);
541
[email protected]36cef8ce2010-03-16 07:34:45542 // Wrapper for glGetFramebufferAttachmentParameteriv.
543 void DoGetFramebufferAttachmentParameteriv(
544 GLenum target, GLenum attachment, GLenum pname, GLint* params);
545
546 // Wrapper for glRenderbufferParameteriv.
547 void DoGetRenderbufferParameteriv(
548 GLenum target, GLenum pname, GLint* params);
549
[email protected]ddd968b82010-03-02 00:44:29550 // Wrapper for glGetShaderiv
551 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
552
[email protected]45bf5152010-02-12 00:11:31553 // Wrapper for glGetShaderSource.
554 void DoGetShaderSource(
555 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst);
556
[email protected]07f54fcc2009-12-22 02:46:30557 // Wrapper for glLinkProgram
558 void DoLinkProgram(GLuint program);
559
[email protected]36cef8ce2010-03-16 07:34:45560 // Wrapper for glRenderbufferStorage.
561 void DoRenderbufferStorage(
562 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
563
[email protected]96449d2c2009-11-25 00:01:32564 // Swaps the buffers (copies/renders to the current window).
565 void DoSwapBuffers();
566
[email protected]3916c97e2010-02-25 03:20:50567 // Wrappers for glTexParameter functions.
568 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
569 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
570 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
571 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
572
573 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
574 // spec only these 2 functions can be used to set sampler uniforms.
575 void DoUniform1i(GLint location, GLint v0);
576 void DoUniform1iv(GLint location, GLsizei count, const GLint *value);
577
[email protected]07f54fcc2009-12-22 02:46:30578 // Wrapper for glUseProgram
579 void DoUseProgram(GLuint program);
580
[email protected]96449d2c2009-11-25 00:01:32581 // Gets the GLError through our wrapper.
582 GLenum GetGLError();
583
584 // Sets our wrapper for the GLError.
585 void SetGLError(GLenum error);
586
[email protected]07f54fcc2009-12-22 02:46:30587 // Copies the real GL errors to the wrapper. This is so we can
588 // make sure there are no native GL errors before calling some GL function
589 // so that on return we know any error generated was for that specific
590 // command.
591 void CopyRealGLErrorsToWrapper();
592
593 // Checks if the current program and vertex attributes are valid for drawing.
594 bool IsDrawValid(GLuint max_vertex_accessed);
595
[email protected]3916c97e2010-02-25 03:20:50596 void SetBlackTextureForNonRenderableTextures(
597 bool* has_non_renderable_textures);
598 void RestoreStateForNonRenderableTextures();
599
[email protected]07f54fcc2009-12-22 02:46:30600 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:50601 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:30602 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:50603 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
604 bound_array_buffer_ : bound_element_array_buffer_;
605 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:30606 }
607
[email protected]a93bb842010-02-16 23:03:47608 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:50609 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
610 TextureUnit& unit = texture_units_[active_texture_unit_];
611 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:47612 switch (target) {
613 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:50614 info = unit.bound_texture_2d;
615 break;
[email protected]a93bb842010-02-16 23:03:47616 case GL_TEXTURE_CUBE_MAP:
617 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
618 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
619 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
620 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
621 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
622 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:50623 info = unit.bound_texture_cube_map;
624 break;
[email protected]1aef98132010-02-23 18:00:07625 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
626 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
627 // because |texture_| is used by the FBO rendering mechanism for readback
628 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:47629 default:
630 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:50631 return NULL;
[email protected]a93bb842010-02-16 23:03:47632 }
[email protected]3916c97e2010-02-25 03:20:50633 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47634 }
635
[email protected]f7b85372010-02-03 01:11:37636 // Validates the program and location for a glGetUniform call and returns
637 // a SizeResult setup to receive the result. Returns true if glGetUniform
638 // should be called.
639 bool GetUniformSetup(
640 GLuint program, GLint location,
641 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:25642 error::Error* error, GLuint* service_id, void** result);
[email protected]f7b85372010-02-03 01:11:37643
[email protected]86093972010-03-11 00:13:56644 bool ValidateGLenumCompressedTextureInternalFormat(GLenum format);
645
[email protected]96449d2c2009-11-25 00:01:32646 // Generate a member function prototype for each command in an automated and
647 // typesafe way.
648 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:14649 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:19650 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:32651 const gles2::name& args); \
652
653 GLES2_COMMAND_LIST(GLES2_CMD_OP)
654
655 #undef GLES2_CMD_OP
656
657 // Current GL error bits.
658 uint32 error_bits_;
659
[email protected]96449d2c2009-11-25 00:01:32660 // Util to help with GL.
661 GLES2Util util_;
662
663 // pack alignment as last set by glPixelStorei
664 GLint pack_alignment_;
665
666 // unpack alignment as last set by glPixelStorei
667 GLint unpack_alignment_;
668
669 // The currently bound array buffer. If this is 0 it is illegal to call
670 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:50671 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:32672
673 // The currently bound element array buffer. If this is 0 it is illegal
674 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:50675 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:30676
677 // Info for each vertex attribute saved so we can check at glDrawXXX time
678 // if it is safe to draw.
679 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
680
[email protected]3916c97e2010-02-25 03:20:50681 // Current active texture by 0 - n index.
682 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
683 // be 2.
684 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:30685
[email protected]3916c97e2010-02-25 03:20:50686 // Which textures are bound to texture units through glActiveTexture.
687 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:47688
[email protected]3916c97e2010-02-25 03:20:50689 // Black (0,0,0,0) textures for when non-renderable textures are used.
690 // NOTE: There is no corresponding TextureInfo for these textures.
691 // TextureInfos are only for textures the client side can access.
692 GLuint black_2d_texture_id_;
693 GLuint black_cube_texture_id_;
[email protected]45bf5152010-02-12 00:11:31694
[email protected]1d32bc82010-01-13 22:06:46695 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:50696 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:30697
[email protected]86093972010-03-11 00:13:56698 // The currently bound framebuffer
699 GLuint bound_framebuffer_;
700
701 // The currently bound renderbuffer
702 GLuint bound_renderbuffer_;
703
[email protected]69d80ae2009-12-23 08:57:42704#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59705#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:42706#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:50707 static int pixel_format_;
708 HDC gl_device_context_;
[email protected]96449d2c2009-11-25 00:01:32709 HGLRC gl_context_;
[email protected]246a70452010-03-05 21:53:50710 HPBUFFERARB pbuffer_;
[email protected]43f28f832010-02-03 02:28:48711#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:35712 AcceleratedSurface surface_;
[email protected]96449d2c2009-11-25 00:01:32713#endif
714
715 bool anti_aliased_;
716
[email protected]43f28f832010-02-03 02:28:48717 scoped_ptr<Callback0::Type> swap_buffers_callback_;
718
[email protected]96449d2c2009-11-25 00:01:32719 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
720};
721
[email protected]3916c97e2010-02-25 03:20:50722GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
723 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:32724}
725
[email protected]246a70452010-03-05 21:53:50726#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59727#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]246a70452010-03-05 21:53:50728#elif defined(OS_WIN)
729int GLES2DecoderImpl::pixel_format_;
730#endif
731
[email protected]3916c97e2010-02-25 03:20:50732GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
733 : GLES2Decoder(group),
[email protected]96449d2c2009-11-25 00:01:32734 error_bits_(0),
735 util_(0), // TODO(gman): Set to actual num compress texture formats.
736 pack_alignment_(4),
737 unpack_alignment_(4),
[email protected]3916c97e2010-02-25 03:20:50738 active_texture_unit_(0),
739 black_2d_texture_id_(0),
740 black_cube_texture_id_(0),
[email protected]86093972010-03-11 00:13:56741 bound_framebuffer_(0),
742 bound_renderbuffer_(0),
[email protected]69d80ae2009-12-23 08:57:42743#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59744#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:42745#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:50746 gl_device_context_(NULL),
[email protected]96449d2c2009-11-25 00:01:32747 gl_context_(NULL),
[email protected]246a70452010-03-05 21:53:50748 pbuffer_(NULL),
[email protected]96449d2c2009-11-25 00:01:32749#endif
750 anti_aliased_(false) {
751}
752
753bool GLES2DecoderImpl::Initialize() {
[email protected]246a70452010-03-05 21:53:50754 if (!InitPlatformSpecific()) {
755 Destroy();
756 return false;
757 }
758 if (!MakeCurrent()) {
759 Destroy();
760 return false;
[email protected]eb54a562010-01-20 21:55:18761 }
762
[email protected]246a70452010-03-05 21:53:50763 // This happens in InitializeOneOff in windows. TODO(apatrick): generalize to
764 // other platforms.
765#if !defined(OS_WIN)
766 if (!InitGlew()) {
767 Destroy();
768 return false;
769 }
770#endif
771
772 CHECK_GL_ERROR();
773
774 if (!group_->Initialize()) {
775 Destroy();
776 return false;
777 }
778
779 vertex_attrib_infos_.reset(
780 new VertexAttribInfo[group_->max_vertex_attribs()]);
781 texture_units_.reset(
782 new TextureUnit[group_->max_texture_units()]);
783 GLuint ids[2];
784 glGenTextures(2, ids);
785 // Make black textures for replacing non-renderable textures.
786 black_2d_texture_id_ = ids[0];
787 black_cube_texture_id_ = ids[1];
788 static int8 black[] = {0, 0, 0, 0};
789 glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
790 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
791 GL_UNSIGNED_BYTE, black);
792 glBindTexture(GL_TEXTURE_2D, 0);
793 glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
794 static GLenum faces[] = {
795 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
796 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
797 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
798 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
799 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
800 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
801 };
802 for (size_t ii = 0; ii < arraysize(faces); ++ii) {
803 glTexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA,
804 GL_UNSIGNED_BYTE, black);
805 }
806 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
807 CHECK_GL_ERROR();
808
809 return true;
[email protected]96449d2c2009-11-25 00:01:32810}
811
[email protected]43f28f832010-02-03 02:28:48812// TODO(kbr): the use of this anonymous namespace core dumps the
813// linker on Mac OS X 10.6 when the symbol ordering file is used
814// namespace {
[email protected]96449d2c2009-11-25 00:01:32815
[email protected]69d80ae2009-12-23 08:57:42816#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59817#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:42818#elif defined(OS_WIN)
819
[email protected]96449d2c2009-11-25 00:01:32820const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
821 sizeof(kPixelFormatDescriptor), // Size of structure.
822 1, // Default version.
823 PFD_DRAW_TO_WINDOW | // Window drawing support.
824 PFD_SUPPORT_OPENGL | // OpenGL support.
825 PFD_DOUBLEBUFFER, // Double buffering support (not stereo).
826 PFD_TYPE_RGBA, // RGBA color mode (not indexed).
827 24, // 24 bit color mode.
828 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts.
829 8, 0, // 8 bit alpha
830 0, // No accumulation buffer.
831 0, 0, 0, 0, // Ignore accumulation bits.
832 24, // 24 bit z-buffer size.
833 8, // 8-bit stencil buffer.
834 0, // No aux buffer.
835 PFD_MAIN_PLANE, // Main drawing plane (not overlay).
836 0, // Reserved.
837 0, 0, 0, // Layer masks ignored.
838};
839
840LRESULT CALLBACK IntermediateWindowProc(HWND window,
841 UINT message,
842 WPARAM w_param,
843 LPARAM l_param) {
844 return ::DefWindowProc(window, message, w_param, l_param);
845}
846
[email protected]246a70452010-03-05 21:53:50847// Helper routine that does one-off initialization like determining the
848// pixel format and initializing glew.
849bool GLES2DecoderImpl::InitializeOneOff(bool anti_aliased) {
[email protected]96449d2c2009-11-25 00:01:32850 // We must initialize a GL context before we can determine the multi-sampling
851 // supported on the current hardware, so we create an intermediate window
852 // and context here.
853 HINSTANCE module_handle;
854 if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
855 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
856 reinterpret_cast<wchar_t*>(IntermediateWindowProc),
857 &module_handle)) {
858 return false;
859 }
860
861 WNDCLASS intermediate_class;
862 intermediate_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
863 intermediate_class.lpfnWndProc = IntermediateWindowProc;
864 intermediate_class.cbClsExtra = 0;
865 intermediate_class.cbWndExtra = 0;
866 intermediate_class.hInstance = module_handle;
867 intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
868 intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
869 intermediate_class.hbrBackground = NULL;
870 intermediate_class.lpszMenuName = NULL;
871 intermediate_class.lpszClassName = L"Intermediate GL Window";
872
873 ATOM class_registration = ::RegisterClass(&intermediate_class);
874 if (!class_registration) {
875 return false;
876 }
877
878 HWND intermediate_window = ::CreateWindow(
879 reinterpret_cast<wchar_t*>(class_registration),
880 L"",
881 WS_OVERLAPPEDWINDOW,
882 0, 0,
883 CW_USEDEFAULT, CW_USEDEFAULT,
884 NULL,
885 NULL,
886 NULL,
887 NULL);
888
889 if (!intermediate_window) {
890 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
891 module_handle);
892 return false;
893 }
894
895 HDC intermediate_dc = ::GetDC(intermediate_window);
[email protected]246a70452010-03-05 21:53:50896 pixel_format_ = ::ChoosePixelFormat(intermediate_dc,
897 &kPixelFormatDescriptor);
898 if (pixel_format_ == 0) {
[email protected]96449d2c2009-11-25 00:01:32899 DLOG(ERROR) << "Unable to get the pixel format for GL context.";
900 ::ReleaseDC(intermediate_window, intermediate_dc);
901 ::DestroyWindow(intermediate_window);
902 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
903 module_handle);
904 return false;
905 }
[email protected]246a70452010-03-05 21:53:50906 if (!::SetPixelFormat(intermediate_dc, pixel_format_,
[email protected]96449d2c2009-11-25 00:01:32907 &kPixelFormatDescriptor)) {
908 DLOG(ERROR) << "Unable to set the pixel format for GL context.";
909 ::ReleaseDC(intermediate_window, intermediate_dc);
910 ::DestroyWindow(intermediate_window);
911 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
912 module_handle);
913 return false;
914 }
915
[email protected]246a70452010-03-05 21:53:50916 // Create a temporary GL context to query for multisampled pixel formats.
[email protected]96449d2c2009-11-25 00:01:32917 HGLRC gl_context = ::wglCreateContext(intermediate_dc);
918 if (::wglMakeCurrent(intermediate_dc, gl_context)) {
919 // GL context was successfully created and applied to the window's DC.
920 // Startup GLEW, the GL extensions wrangler.
[email protected]246a70452010-03-05 21:53:50921 if (InitGlew()) {
[email protected]96449d2c2009-11-25 00:01:32922 DLOG(INFO) << "Initialized GLEW " << ::glewGetString(GLEW_VERSION);
923 } else {
[email protected]96449d2c2009-11-25 00:01:32924 ::wglMakeCurrent(intermediate_dc, NULL);
925 ::wglDeleteContext(gl_context);
926 ::ReleaseDC(intermediate_window, intermediate_dc);
927 ::DestroyWindow(intermediate_window);
928 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
929 module_handle);
930 return false;
931 }
932
933 // If the multi-sample extensions are present, query the api to determine
934 // the pixel format.
935 if (anti_aliased && WGLEW_ARB_pixel_format && WGLEW_ARB_multisample) {
936 int pixel_attributes[] = {
937 WGL_SAMPLES_ARB, 4,
938 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
939 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
940 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
941 WGL_COLOR_BITS_ARB, 24,
942 WGL_ALPHA_BITS_ARB, 8,
943 WGL_DEPTH_BITS_ARB, 24,
944 WGL_STENCIL_BITS_ARB, 8,
945 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
946 WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
947 0, 0};
948
949 float pixel_attributes_f[] = {0, 0};
950 int msaa_pixel_format;
951 unsigned int num_formats;
952
953 // Query for the highest sampling rate supported, starting at 4x.
954 static const int kSampleCount[] = {4, 2};
955 static const int kNumSamples = 2;
956 for (int sample = 0; sample < kNumSamples; ++sample) {
957 pixel_attributes[1] = kSampleCount[sample];
958 if (GL_TRUE == ::wglChoosePixelFormatARB(intermediate_dc,
959 pixel_attributes,
960 pixel_attributes_f,
961 1,
962 &msaa_pixel_format,
963 &num_formats)) {
[email protected]246a70452010-03-05 21:53:50964 pixel_format_ = msaa_pixel_format;
[email protected]96449d2c2009-11-25 00:01:32965 break;
966 }
967 }
968 }
969 }
970
971 ::wglMakeCurrent(intermediate_dc, NULL);
972 ::wglDeleteContext(gl_context);
973 ::ReleaseDC(intermediate_window, intermediate_dc);
974 ::DestroyWindow(intermediate_window);
975 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
976 module_handle);
977 return true;
978}
979
[email protected]69d80ae2009-12-23 08:57:42980#endif // OS_WIN
981
[email protected]07f54fcc2009-12-22 02:46:30982// These commands convert from c calls to local os calls.
983void GLGenBuffersHelper(
[email protected]a93bb842010-02-16 23:03:47984 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:30985 glGenBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:47986 // TODO(gman): handle error
987 for (GLsizei ii = 0; ii < n; ++ii) {
988 decoder->CreateBufferInfo(ids[ii]);
989 }
[email protected]07f54fcc2009-12-22 02:46:30990}
991
992void GLGenFramebuffersHelper(
[email protected]a25fa872010-03-25 02:57:58993 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:30994 glGenFramebuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:58995 // TODO(gman): handle error
996 for (GLsizei ii = 0; ii < n; ++ii) {
997 decoder->CreateFramebufferInfo(ids[ii]);
998 }
[email protected]07f54fcc2009-12-22 02:46:30999}
1000
1001void GLGenRenderbuffersHelper(
[email protected]a25fa872010-03-25 02:57:581002 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301003 glGenRenderbuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:581004 // TODO(gman): handle error
1005 for (GLsizei ii = 0; ii < n; ++ii) {
1006 decoder->CreateRenderbufferInfo(ids[ii]);
1007 }
[email protected]07f54fcc2009-12-22 02:46:301008}
1009
1010void GLGenTexturesHelper(
[email protected]a93bb842010-02-16 23:03:471011 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301012 glGenTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:471013 // TODO(gman): handle error
1014 for (GLsizei ii = 0; ii < n; ++ii) {
1015 decoder->CreateTextureInfo(ids[ii]);
1016 }
[email protected]07f54fcc2009-12-22 02:46:301017}
1018
1019void GLDeleteBuffersHelper(
1020 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
1021 glDeleteBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:471022 // TODO(gman): handle error
[email protected]07f54fcc2009-12-22 02:46:301023 for (GLsizei ii = 0; ii < n; ++ii) {
1024 decoder->RemoveBufferInfo(ids[ii]);
1025 }
1026}
1027
1028void GLDeleteFramebuffersHelper(
[email protected]a25fa872010-03-25 02:57:581029 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301030 glDeleteFramebuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:581031 // TODO(gman): handle error
1032 for (GLsizei ii = 0; ii < n; ++ii) {
1033 decoder->RemoveFramebufferInfo(ids[ii]);
1034 }
[email protected]07f54fcc2009-12-22 02:46:301035}
1036
1037void GLDeleteRenderbuffersHelper(
[email protected]a25fa872010-03-25 02:57:581038 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301039 glDeleteRenderbuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:581040 // TODO(gman): handle error
1041 for (GLsizei ii = 0; ii < n; ++ii) {
1042 decoder->RemoveRenderbufferInfo(ids[ii]);
1043 }
[email protected]07f54fcc2009-12-22 02:46:301044}
1045
1046void GLDeleteTexturesHelper(
[email protected]a93bb842010-02-16 23:03:471047 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301048 glDeleteTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:471049 // TODO(gman): handle error
1050 for (GLsizei ii = 0; ii < n; ++ii) {
1051 decoder->RemoveTextureInfo(ids[ii]);
1052 }
[email protected]07f54fcc2009-12-22 02:46:301053}
1054
[email protected]43f28f832010-02-03 02:28:481055// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:321056
[email protected]eb54a562010-01-20 21:55:181057bool GLES2DecoderImpl::MakeCurrent() {
1058#if defined(UNIT_TEST)
1059 return true;
[email protected]b5f1aa032010-03-11 00:07:591060#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1061 return true;
[email protected]eb54a562010-01-20 21:55:181062#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:501063 if (::wglGetCurrentDC() == gl_device_context_ &&
[email protected]eb54a562010-01-20 21:55:181064 ::wglGetCurrentContext() == gl_context_) {
1065 return true;
1066 }
[email protected]246a70452010-03-05 21:53:501067 if (!::wglMakeCurrent(gl_device_context_, gl_context_)) {
[email protected]eb54a562010-01-20 21:55:181068 DLOG(ERROR) << "Unable to make gl context current.";
1069 return false;
1070 }
1071 return true;
1072#elif defined(OS_LINUX)
1073 return window()->MakeCurrent();
[email protected]43f28f832010-02-03 02:28:481074#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:351075 return surface_.MakeCurrent();
[email protected]eb54a562010-01-20 21:55:181076#else
1077 NOTREACHED();
1078 return false;
1079#endif
1080}
1081
[email protected]8a837bb2010-01-05 00:21:241082uint32 GLES2DecoderImpl::GetServiceIdForTesting(uint32 client_id) {
1083#if defined(UNIT_TEST)
1084 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501085 bool result = id_manager()->GetServiceId(client_id, &service_id);
[email protected]8a837bb2010-01-05 00:21:241086 return result ? service_id : 0u;
1087#else
1088 DCHECK(false);
1089 return 0u;
1090#endif
1091}
1092
1093bool GLES2DecoderImpl::ValidateIdsAreUnused(
1094 GLsizei n, const GLuint* client_ids) {
1095 for (GLsizei ii = 0; ii < n; ++ii) {
1096 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501097 if (id_manager()->GetServiceId(client_ids[ii], &service_id)) {
[email protected]8a837bb2010-01-05 00:21:241098 return false;
1099 }
1100 }
1101 return true;
1102}
1103
[email protected]07f54fcc2009-12-22 02:46:301104bool GLES2DecoderImpl::RegisterObjects(
1105 GLsizei n, const GLuint* client_ids, const GLuint* service_ids) {
1106 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501107 if (!id_manager()->AddMapping(client_ids[ii], service_ids[ii])) {
[email protected]8a837bb2010-01-05 00:21:241108 NOTREACHED();
1109 return false;
[email protected]07f54fcc2009-12-22 02:46:301110 }
1111 }
1112 return true;
1113}
1114
1115void GLES2DecoderImpl::UnregisterObjects(
1116 GLsizei n, const GLuint* client_ids, GLuint* service_ids) {
[email protected]07f54fcc2009-12-22 02:46:301117 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501118 if (id_manager()->GetServiceId(client_ids[ii], &service_ids[ii])) {
1119 id_manager()->RemoveMapping(client_ids[ii], service_ids[ii]);
[email protected]07f54fcc2009-12-22 02:46:301120 } else {
1121 service_ids[ii] = 0;
1122 }
1123 }
1124}
1125
[email protected]96449d2c2009-11-25 00:01:321126bool GLES2DecoderImpl::InitPlatformSpecific() {
[email protected]69d80ae2009-12-23 08:57:421127#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591128#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:421129#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:501130 // Do one-off initialization.
1131 static bool success = InitializeOneOff(anti_aliased_);
1132 if (!success)
[email protected]96449d2c2009-11-25 00:01:321133 return false;
[email protected]246a70452010-03-05 21:53:501134
1135 if (hwnd()) {
1136 // The GL context will render to this window.
1137 gl_device_context_ = ::GetDC(hwnd());
1138
1139 if (!::SetPixelFormat(gl_device_context_,
1140 pixel_format_,
1141 &kPixelFormatDescriptor)) {
1142 DLOG(ERROR) << "Unable to set the pixel format for GL context.";
1143 DestroyPlatformSpecific();
1144 return false;
1145 }
1146 } else {
1147 // Create a device context compatible with the primary display.
1148 HDC display_device_context = ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
1149
1150 // Create a 1 x 1 pbuffer suitable for use with the device.
1151 const int kNoAttributes[] = { 0 };
1152 pbuffer_ = ::wglCreatePbufferARB(display_device_context,
1153 pixel_format_,
1154 1, 1,
1155 kNoAttributes);
1156 ::DeleteDC(display_device_context);
1157 if (!pbuffer_) {
1158 DLOG(ERROR) << "Unable to create pbuffer.";
1159 DestroyPlatformSpecific();
1160 return false;
1161 }
1162
1163 gl_device_context_ = ::wglGetPbufferDCARB(pbuffer_);
1164 if (!gl_device_context_) {
1165 DLOG(ERROR) << "Unable to get pbuffer device context.";
1166 DestroyPlatformSpecific();
1167 return false;
1168 }
[email protected]96449d2c2009-11-25 00:01:321169 }
1170
[email protected]246a70452010-03-05 21:53:501171 gl_context_ = ::wglCreateContext(gl_device_context_);
[email protected]96449d2c2009-11-25 00:01:321172 if (!gl_context_) {
1173 DLOG(ERROR) << "Failed to create GL context.";
[email protected]246a70452010-03-05 21:53:501174 DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:321175 return false;
1176 }
[email protected]96449d2c2009-11-25 00:01:321177#elif defined(OS_LINUX)
1178 DCHECK(window());
1179 if (!window()->Initialize())
1180 return false;
[email protected]43f28f832010-02-03 02:28:481181#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:351182 return surface_.Initialize();
[email protected]96449d2c2009-11-25 00:01:321183#endif
1184
1185 return true;
1186}
1187
1188bool GLES2DecoderImpl::InitGlew() {
[email protected]b5f1aa032010-03-11 00:07:591189#if !defined(UNIT_TEST) && !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]96449d2c2009-11-25 00:01:321190 DLOG(INFO) << "Initializing GL and GLEW for GLES2Decoder.";
1191
1192 GLenum glew_error = glewInit();
1193 if (glew_error != GLEW_OK) {
1194 DLOG(ERROR) << "Unable to initialise GLEW : "
1195 << ::glewGetErrorString(glew_error);
1196 return false;
1197 }
1198
1199 // Check to see that we can use the OpenGL vertex attribute APIs
1200 // TODO(petersont): Return false if this check fails, but because some
1201 // Intel hardware does not support OpenGL 2.0, yet does support all of the
1202 // extensions we require, we only log an error. A future CL should change
1203 // this check to ensure that all of the extension strings we require are
1204 // present.
1205 if (!GLEW_VERSION_2_0) {
1206 DLOG(ERROR) << "GL drivers do not have OpenGL 2.0 functionality.";
1207 }
1208
1209 bool extensions_found = true;
1210 if (!GLEW_ARB_vertex_buffer_object) {
1211 // NOTE: Linux NVidia drivers claim to support OpenGL 2.0 when using
1212 // indirect rendering (e.g. remote X), but it is actually lying. The
1213 // ARB_vertex_buffer_object functions silently no-op (!) when using
1214 // indirect rendering, leading to crashes. Fortunately, in that case, the
1215 // driver claims to not support ARB_vertex_buffer_object, so fail in that
1216 // case.
1217 DLOG(ERROR) << "GL drivers do not support vertex buffer objects.";
1218 extensions_found = false;
1219 }
1220 if (!GLEW_EXT_framebuffer_object) {
1221 DLOG(ERROR) << "GL drivers do not support framebuffer objects.";
1222 extensions_found = false;
1223 }
1224 // Check for necessary extensions
1225 if (!GLEW_VERSION_2_0 && !GLEW_EXT_stencil_two_side) {
1226 DLOG(ERROR) << "Two sided stencil extension missing.";
1227 extensions_found = false;
1228 }
1229 if (!GLEW_VERSION_1_4 && !GLEW_EXT_blend_func_separate) {
1230 DLOG(ERROR) <<"Separate blend func extension missing.";
1231 extensions_found = false;
1232 }
1233 if (!GLEW_VERSION_2_0 && !GLEW_EXT_blend_equation_separate) {
1234 DLOG(ERROR) << "Separate blend function extension missing.";
1235 extensions_found = false;
1236 }
1237 if (!extensions_found)
1238 return false;
[email protected]69d80ae2009-12-23 08:57:421239#endif
[email protected]96449d2c2009-11-25 00:01:321240
1241 return true;
1242}
1243
[email protected]246a70452010-03-05 21:53:501244void GLES2DecoderImpl::DestroyPlatformSpecific() {
1245#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591246#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]246a70452010-03-05 21:53:501247#elif defined(OS_WIN)
1248 if (gl_context_) {
1249 ::wglDeleteContext(gl_context_);
1250 }
1251
1252 if (gl_device_context_) {
1253 if (hwnd())
1254 ::ReleaseDC(hwnd(), gl_device_context_);
1255 else
1256 ::wglReleasePbufferDCARB(pbuffer_, gl_device_context_);
1257
1258 gl_device_context_ = NULL;
1259 }
1260
1261 if (pbuffer_) {
1262 ::wglDestroyPbufferARB(pbuffer_);
1263 pbuffer_ = NULL;
1264 }
1265#endif
1266}
1267
[email protected]6098b712010-02-09 17:59:341268#if defined(OS_MACOSX)
[email protected]1aef98132010-02-23 18:00:071269
1270uint64 GLES2DecoderImpl::SetWindowSizeForIOSurface(int32 width, int32 height) {
[email protected]6098b712010-02-09 17:59:341271#if defined(UNIT_TEST)
1272 return 0;
[email protected]b5f1aa032010-03-11 00:07:591273#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1274 return 0;
[email protected]6098b712010-02-09 17:59:341275#else
[email protected]3d1e89d2010-03-10 20:01:351276 return surface_.SetSurfaceSize(width, height);
[email protected]6098b712010-02-09 17:59:341277#endif // !defined(UNIT_TEST)
[email protected]43f28f832010-02-03 02:28:481278}
[email protected]1aef98132010-02-23 18:00:071279
1280TransportDIB::Handle GLES2DecoderImpl::SetWindowSizeForTransportDIB(
1281 int32 width, int32 height) {
1282#if defined(UNIT_TEST)
1283 return TransportDIB::DefaultHandleValue();
[email protected]b5f1aa032010-03-11 00:07:591284#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1285 return TransportDIB::DefaultHandleValue();
[email protected]1aef98132010-02-23 18:00:071286#else
[email protected]3d1e89d2010-03-10 20:01:351287 return surface_.SetTransportDIBSize(width, height);
[email protected]1aef98132010-02-23 18:00:071288#endif // !defined(UNIT_TEST)
1289}
1290
1291void GLES2DecoderImpl::SetTransportDIBAllocAndFree(
1292 Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
1293 Callback1<TransportDIB::Id>::Type* deallocator) {
[email protected]3d1e89d2010-03-10 20:01:351294 surface_.SetTransportDIBAllocAndFree(allocator, deallocator);
[email protected]1aef98132010-02-23 18:00:071295}
[email protected]6098b712010-02-09 17:59:341296#endif // defined(OS_MACOSX)
[email protected]43f28f832010-02-03 02:28:481297
1298void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
1299 swap_buffers_callback_.reset(callback);
1300}
1301
[email protected]96449d2c2009-11-25 00:01:321302void GLES2DecoderImpl::Destroy() {
[email protected]69d80ae2009-12-23 08:57:421303#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591304#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:421305#elif defined(OS_LINUX)
[email protected]96449d2c2009-11-25 00:01:321306 DCHECK(window());
1307 window()->Destroy();
[email protected]43f28f832010-02-03 02:28:481308#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:351309 surface_.Destroy();
[email protected]96449d2c2009-11-25 00:01:321310#endif
[email protected]246a70452010-03-05 21:53:501311
1312 DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:321313}
1314
1315const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
1316 if (command_id > kStartPoint && command_id < kNumCommands) {
1317 return gles2::GetCommandName(static_cast<CommandId>(command_id));
1318 }
1319 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
1320}
1321
1322// Decode command with its arguments, and call the corresponding GL function.
1323// Note: args is a pointer to the command buffer. As such, it could be changed
1324// by a (malicious) client at any time, so if validation has to happen, it
1325// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:141326error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:321327 unsigned int command,
1328 unsigned int arg_count,
1329 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:141330 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191331 if (debug()) {
1332 // TODO(gman): Change output to something useful for NaCl.
[email protected]b9849abf2009-11-25 19:13:191333 printf("cmd: %s\n", GetCommandName(command));
1334 }
[email protected]96449d2c2009-11-25 00:01:321335 unsigned int command_index = command - kStartPoint - 1;
1336 if (command_index < arraysize(g_command_info)) {
1337 const CommandInfo& info = g_command_info[command_index];
1338 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
1339 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
1340 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:191341 uint32 immediate_data_size =
1342 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:321343 switch (command) {
1344 #define GLES2_CMD_OP(name) \
1345 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:191346 result = Handle ## name( \
1347 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321348 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:191349 break; \
[email protected]96449d2c2009-11-25 00:01:321350
1351 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:321352 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:381353 }
1354 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:301355 GLenum error;
1356 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:381357 // TODO(gman): Change output to something useful for NaCl.
[email protected]07f54fcc2009-12-22 02:46:301358 SetGLError(error);
[email protected]bf0985e2009-12-17 03:04:381359 printf("GL ERROR b4: %s\n", GetCommandName(command));
[email protected]b9849abf2009-11-25 19:13:191360 }
[email protected]96449d2c2009-11-25 00:01:321361 }
1362 } else {
[email protected]f7a64ee2010-02-01 22:24:141363 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:321364 }
[email protected]b9849abf2009-11-25 19:13:191365 } else {
1366 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:321367 }
[email protected]b9849abf2009-11-25 19:13:191368 return result;
[email protected]96449d2c2009-11-25 00:01:321369}
1370
[email protected]3916c97e2010-02-25 03:20:501371void GLES2DecoderImpl::RemoveBufferInfo(GLuint buffer_id) {
1372 buffer_manager()->RemoveBufferInfo(buffer_id);
1373 // TODO(gman): See if we can remove the rest of this function as
1374 // buffers are now reference counted and have a "IsDeleted" function.
1375 if (bound_array_buffer_ && bound_array_buffer_->buffer_id() == buffer_id) {
1376 bound_array_buffer_ = NULL;
1377 }
1378 if (bound_element_array_buffer_ &&
1379 bound_element_array_buffer_->buffer_id() == buffer_id) {
1380 bound_element_array_buffer_ = NULL;
1381 }
1382
1383 // go through VertexAttribInfo and update any info that references the buffer.
1384 for (GLuint ii = 0; ii < group_->max_vertex_attribs(); ++ii) {
1385 VertexAttribInfo& info = vertex_attrib_infos_[ii];
1386 if (info.buffer() && info.buffer()->buffer_id() == buffer_id) {
1387 info.ClearBuffer();
1388 }
1389 }
1390}
1391
[email protected]96449d2c2009-11-25 00:01:321392void GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
1393 // TODO(gman): verify client_id is unused.
1394 GLuint service_id = glCreateProgram();
1395 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501396 id_manager()->AddMapping(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:471397 CreateProgramInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321398 }
1399}
1400
1401void GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
1402 // TODO(gman): verify client_id is unused.
1403 GLuint service_id = glCreateShader(type);
1404 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501405 id_manager()->AddMapping(client_id, service_id);
[email protected]45bf5152010-02-12 00:11:311406 CreateShaderInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321407 }
1408}
1409
[email protected]86093972010-03-11 00:13:561410bool GLES2DecoderImpl::ValidateGLenumCompressedTextureInternalFormat(GLenum) {
1411 // TODO(gman): Add support for compressed texture formats.
1412 return false;
1413}
1414
[email protected]3916c97e2010-02-25 03:20:501415void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:451416 GLuint texture_index = texture_unit - GL_TEXTURE0;
1417 if (texture_index > group_->max_texture_units()) {
[email protected]3916c97e2010-02-25 03:20:501418 SetGLError(GL_INVALID_ENUM);
1419 return;
1420 }
[email protected]36cef8ce2010-03-16 07:34:451421 active_texture_unit_ = texture_index;
1422 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:501423}
1424
[email protected]96449d2c2009-11-25 00:01:321425void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:501426 BufferManager::BufferInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471427 if (buffer) {
[email protected]3916c97e2010-02-25 03:20:501428 info = GetBufferInfo(buffer);
[email protected]0c86dbf2010-03-05 08:14:111429 // Check the buffer exists
1430 // Check that we are not trying to bind it to a different target.
1431 if (!info || (info->target() != 0 && info->target() != target)) {
[email protected]a93bb842010-02-16 23:03:471432 SetGLError(GL_INVALID_OPERATION);
1433 return;
1434 }
[email protected]0c86dbf2010-03-05 08:14:111435 if (info->target() == 0) {
1436 info->set_target(target);
1437 }
[email protected]a93bb842010-02-16 23:03:471438 }
[email protected]96449d2c2009-11-25 00:01:321439 switch (target) {
1440 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501441 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321442 break;
1443 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501444 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321445 break;
1446 default:
[email protected]a93bb842010-02-16 23:03:471447 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:321448 break;
1449 }
1450 glBindBuffer(target, buffer);
1451}
1452
[email protected]86093972010-03-11 00:13:561453void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint framebuffer) {
1454 bound_framebuffer_ = framebuffer;
1455 glBindFramebufferEXT(target, framebuffer);
1456}
1457
1458void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint renderbuffer) {
1459 bound_renderbuffer_ = renderbuffer;
1460 glBindRenderbufferEXT(target, renderbuffer);
1461}
1462
[email protected]a93bb842010-02-16 23:03:471463void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:501464 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471465 if (texture) {
[email protected]3916c97e2010-02-25 03:20:501466 info = GetTextureInfo(texture);
1467 // Check the texture exists
1468 // Check that we are not trying to bind it to a different target.
[email protected]a93bb842010-02-16 23:03:471469 if (!info || (info->target() != 0 && info->target() != target)) {
1470 SetGLError(GL_INVALID_OPERATION);
1471 return;
1472 }
1473 if (info->target() == 0) {
[email protected]3916c97e2010-02-25 03:20:501474 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:471475 }
1476 }
1477 glBindTexture(target, texture);
[email protected]3916c97e2010-02-25 03:20:501478 TextureUnit& unit = texture_units_[active_texture_unit_];
1479 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:471480 switch (target) {
1481 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501482 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:471483 break;
1484 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:501485 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:471486 break;
1487 default:
1488 NOTREACHED(); // Validation should prevent us getting here.
1489 break;
1490 }
1491}
1492
[email protected]07f54fcc2009-12-22 02:46:301493void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501494 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301495 vertex_attrib_infos_[index].set_enabled(false);
[email protected]8a837bb2010-01-05 00:21:241496 glDisableVertexAttribArray(index);
[email protected]07f54fcc2009-12-22 02:46:301497 } else {
1498 SetGLError(GL_INVALID_VALUE);
1499 }
1500}
1501
1502void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501503 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301504 vertex_attrib_infos_[index].set_enabled(true);
1505 glEnableVertexAttribArray(index);
1506 } else {
1507 SetGLError(GL_INVALID_VALUE);
1508 }
1509}
1510
[email protected]a93bb842010-02-16 23:03:471511void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:501512 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1513 if (!info || !info->MarkMipmapsGenerated()) {
[email protected]a93bb842010-02-16 23:03:471514 SetGLError(GL_INVALID_OPERATION);
1515 return;
1516 }
1517 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:471518}
1519
[email protected]558847a2010-03-24 07:02:541520error::Error GLES2DecoderImpl::HandleBindAttribLocation(
1521 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
1522 GLuint program;
1523 if (!id_manager()->GetServiceId(c.program, &program)) {
1524 SetGLError(GL_INVALID_VALUE);
1525 return error::kNoError;
1526 }
1527 GLuint index = static_cast<GLuint>(c.index);
1528 uint32 name_size = c.data_size;
1529 const char* name = GetSharedMemoryAs<const char*>(
1530 c.name_shm_id, c.name_shm_offset, name_size);
1531 if (name == NULL) {
1532 return error::kOutOfBounds;
1533 }
1534 String name_str(name, name_size);
1535 glBindAttribLocation(program, index, name_str.c_str());
1536 return error::kNoError;
1537}
1538
1539error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
1540 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
1541 GLuint program;
1542 if (!id_manager()->GetServiceId(c.program, &program)) {
1543 SetGLError(GL_INVALID_VALUE);
1544 return error::kNoError;
1545 }
1546 GLuint index = static_cast<GLuint>(c.index);
1547 uint32 name_size = c.data_size;
1548 const char* name = GetImmediateDataAs<const char*>(
1549 c, name_size, immediate_data_size);
1550 if (name == NULL) {
1551 return error::kOutOfBounds;
1552 }
1553 String name_str(name, name_size);
1554 glBindAttribLocation(program, index, name_str.c_str());
1555 return error::kNoError;
1556}
1557
1558error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
1559 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
1560 GLuint program;
1561 if (!id_manager()->GetServiceId(c.program, &program)) {
1562 SetGLError(GL_INVALID_VALUE);
1563 return error::kNoError;
1564 }
1565 GLuint index = static_cast<GLuint>(c.index);
1566 Bucket* bucket = GetBucket(c.name_bucket_id);
1567 if (!bucket || bucket->size() == 0) {
1568 return error::kInvalidArguments;
1569 }
1570 std::string name_str;
1571 bucket->GetAsString(&name_str);
1572 glBindAttribLocation(program, index, name_str.c_str());
1573 return error::kNoError;
1574}
1575
[email protected]f7a64ee2010-02-01 22:24:141576error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:461577 uint32 immediate_data_size, const gles2::DeleteShader& c) {
1578 GLuint shader = c.shader;
[email protected]96449d2c2009-11-25 00:01:321579 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501580 if (!id_manager()->GetServiceId(shader, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:461581 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141582 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321583 }
[email protected]45bf5152010-02-12 00:11:311584 RemoveShaderInfo(service_id);
[email protected]07f54fcc2009-12-22 02:46:301585 glDeleteShader(service_id);
[email protected]3916c97e2010-02-25 03:20:501586 id_manager()->RemoveMapping(shader, service_id);
[email protected]f7a64ee2010-02-01 22:24:141587 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321588}
1589
[email protected]f7a64ee2010-02-01 22:24:141590error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:461591 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
1592 GLuint program = c.program;
[email protected]96449d2c2009-11-25 00:01:321593 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501594 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:461595 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141596 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321597 }
[email protected]1d32bc82010-01-13 22:06:461598 RemoveProgramInfo(service_id);
[email protected]ba3176a2009-12-16 18:19:461599 glDeleteProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:501600 id_manager()->RemoveMapping(program, service_id);
[email protected]f7a64ee2010-02-01 22:24:141601 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321602}
1603
[email protected]07f54fcc2009-12-22 02:46:301604void GLES2DecoderImpl::DoDrawArrays(
1605 GLenum mode, GLint first, GLsizei count) {
1606 if (IsDrawValid(first + count - 1)) {
[email protected]3916c97e2010-02-25 03:20:501607 bool has_non_renderable_textures;
1608 SetBlackTextureForNonRenderableTextures(&has_non_renderable_textures);
[email protected]07f54fcc2009-12-22 02:46:301609 glDrawArrays(mode, first, count);
[email protected]3916c97e2010-02-25 03:20:501610 if (has_non_renderable_textures) {
1611 RestoreStateForNonRenderableTextures();
1612 }
[email protected]07f54fcc2009-12-22 02:46:301613 }
1614}
1615
[email protected]36cef8ce2010-03-16 07:34:451616void GLES2DecoderImpl::DoFramebufferRenderbuffer(
1617 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1618 GLuint renderbuffer) {
1619 if (bound_framebuffer_ == 0) {
1620 SetGLError(GL_INVALID_OPERATION);
1621 return;
1622 }
1623 glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget,
1624 renderbuffer);
1625}
1626
1627GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
1628 if (bound_framebuffer_ == 0) {
1629 return GL_FRAMEBUFFER_COMPLETE;
1630 }
1631 return glCheckFramebufferStatusEXT(target);
1632}
1633
1634void GLES2DecoderImpl::DoFramebufferTexture2D(
1635 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1636 GLint level) {
1637 if (bound_framebuffer_ == 0) {
1638 SetGLError(GL_INVALID_OPERATION);
1639 return;
1640 }
1641 glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
1642}
1643
1644void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
1645 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
1646 if (bound_framebuffer_ == 0) {
1647 SetGLError(GL_INVALID_OPERATION);
1648 return;
1649 }
1650 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
1651}
1652
1653void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
1654 GLenum target, GLenum pname, GLint* params) {
1655 if (bound_renderbuffer_ == 0) {
1656 SetGLError(GL_INVALID_OPERATION);
1657 return;
1658 }
1659 glGetRenderbufferParameterivEXT(target, pname, params);
1660}
1661
1662void GLES2DecoderImpl::DoRenderbufferStorage(
1663 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
1664 if (bound_renderbuffer_ == 0) {
1665 SetGLError(GL_INVALID_OPERATION);
1666 return;
1667 }
1668 glRenderbufferStorageEXT(target, internalformat, width, height);
1669}
1670
[email protected]07f54fcc2009-12-22 02:46:301671void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]a93bb842010-02-16 23:03:471672 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
1673 if (!info) {
1674 SetGLError(GL_INVALID_OPERATION);
1675 return;
1676 }
[email protected]07f54fcc2009-12-22 02:46:301677 CopyRealGLErrorsToWrapper();
1678 glLinkProgram(program);
1679 GLenum error = glGetError();
1680 if (error != GL_NO_ERROR) {
1681 RemoveProgramInfo(program);
1682 SetGLError(error);
1683 } else {
[email protected]a93bb842010-02-16 23:03:471684 info->Update();
[email protected]07f54fcc2009-12-22 02:46:301685 }
1686};
1687
[email protected]96449d2c2009-11-25 00:01:321688void GLES2DecoderImpl::DoSwapBuffers() {
[email protected]69d80ae2009-12-23 08:57:421689#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591690#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:421691#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:501692 ::SwapBuffers(gl_device_context_);
[email protected]69d80ae2009-12-23 08:57:421693#elif defined(OS_LINUX)
[email protected]96449d2c2009-11-25 00:01:321694 DCHECK(window());
1695 window()->SwapBuffers();
[email protected]43f28f832010-02-03 02:28:481696#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:351697 // TODO(kbr): Need to property hook up and track the OpenGL state and hook
1698 // up the notion of the currently bound FBO.
1699 surface_.SwapBuffers();
[email protected]96449d2c2009-11-25 00:01:321700#endif
[email protected]43f28f832010-02-03 02:28:481701 if (swap_buffers_callback_.get()) {
1702 swap_buffers_callback_->Run();
1703 }
[email protected]96449d2c2009-11-25 00:01:321704}
1705
[email protected]3916c97e2010-02-25 03:20:501706void GLES2DecoderImpl::DoTexParameterf(
1707 GLenum target, GLenum pname, GLfloat param) {
1708 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:301709 if (!info) {
[email protected]3916c97e2010-02-25 03:20:501710 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:301711 } else {
[email protected]3916c97e2010-02-25 03:20:501712 info->SetParameter(pname, static_cast<GLint>(param));
1713 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:301714 }
1715}
1716
[email protected]3916c97e2010-02-25 03:20:501717void GLES2DecoderImpl::DoTexParameteri(
1718 GLenum target, GLenum pname, GLint param) {
1719 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1720 if (!info) {
1721 SetGLError(GL_INVALID_VALUE);
1722 } else {
1723 info->SetParameter(pname, param);
1724 glTexParameteri(target, pname, param);
1725 }
1726}
1727
1728void GLES2DecoderImpl::DoTexParameterfv(
1729 GLenum target, GLenum pname, const GLfloat* params) {
1730 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1731 if (!info) {
1732 SetGLError(GL_INVALID_VALUE);
1733 } else {
1734 info->SetParameter(pname, *reinterpret_cast<const GLint*>(params));
1735 glTexParameterfv(target, pname, params);
1736 }
1737}
1738
1739void GLES2DecoderImpl::DoTexParameteriv(
1740 GLenum target, GLenum pname, const GLint* params) {
1741 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1742 if (!info) {
1743 SetGLError(GL_INVALID_VALUE);
1744 } else {
1745 info->SetParameter(pname, *params);
1746 glTexParameteriv(target, pname, params);
1747 }
1748}
1749
1750void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
1751 if (!current_program_ || current_program_->IsDeleted()) {
1752 // The program does not exist.
1753 SetGLError(GL_INVALID_OPERATION);
1754 return;
1755 }
1756 current_program_->SetSamplers(location, 1, &v0);
1757 glUniform1i(location, v0);
1758}
1759
1760void GLES2DecoderImpl::DoUniform1iv(
1761 GLint location, GLsizei count, const GLint *value) {
1762 if (!current_program_ || current_program_->IsDeleted()) {
1763 // The program does not exist.
1764 SetGLError(GL_INVALID_OPERATION);
1765 return;
1766 }
1767 current_program_->SetSamplers(location, count, value);
1768 glUniform1iv(location, count, value);
1769}
1770
1771void GLES2DecoderImpl::DoUseProgram(GLuint program) {
1772 ProgramManager::ProgramInfo* info = NULL;
1773 if (program) {
1774 info = GetProgramInfo(program);
1775 if (!info) {
1776 // Program was not linked successfully. (ie, glLinkProgram)
1777 SetGLError(GL_INVALID_OPERATION);
1778 return;
1779 }
1780 }
1781 current_program_ = info;
1782 glUseProgram(program);
1783}
1784
[email protected]96449d2c2009-11-25 00:01:321785GLenum GLES2DecoderImpl::GetGLError() {
1786 // Check the GL error first, then our wrapped error.
1787 GLenum error = glGetError();
1788 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:371789 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:321790 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:291791 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:321792 break;
1793 }
1794 }
1795 }
1796
1797 if (error != GL_NO_ERROR) {
1798 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:291799 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:321800 }
1801 return error;
1802}
1803
1804void GLES2DecoderImpl::SetGLError(GLenum error) {
[email protected]ddd968b82010-03-02 00:44:291805 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:321806}
1807
[email protected]07f54fcc2009-12-22 02:46:301808void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
1809 GLenum error;
1810 while ((error = glGetError()) != GL_NO_ERROR) {
1811 SetGLError(error);
1812 }
1813}
1814
[email protected]07f54fcc2009-12-22 02:46:301815bool GLES2DecoderImpl::VertexAttribInfo::CanAccess(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501816 if (!enabled_) {
1817 return true;
1818 }
1819
1820 if (!buffer_ || buffer_->IsDeleted()) {
1821 return false;
1822 }
1823
1824 // The number of elements that can be accessed.
1825 GLsizeiptr buffer_size = buffer_->size();
1826 if (offset_ > buffer_size || real_stride_ == 0) {
1827 return false;
1828 }
1829
1830 uint32 usable_size = buffer_size - offset_;
1831 GLuint num_elements = usable_size / real_stride_ +
1832 ((usable_size % real_stride_) >=
1833 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
1834 return index < num_elements;
1835}
1836
1837void GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures(
1838 bool* has_non_renderable_textures) {
1839 DCHECK(has_non_renderable_textures);
1840 DCHECK(current_program_);
1841 DCHECK(!current_program_->IsDeleted());
1842 *has_non_renderable_textures = false;
1843 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
1844 current_program_->sampler_indices();
1845 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
1846 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
1847 current_program_->GetUniformInfo(sampler_indices[ii]);
1848 DCHECK(uniform_info);
1849 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
1850 GLuint texture_unit_index = uniform_info->texture_units[jj];
1851 if (texture_unit_index < group_->max_texture_units()) {
1852 TextureUnit& texture_unit = texture_units_[texture_unit_index];
1853 TextureManager::TextureInfo* texture_info =
1854 uniform_info->type == GL_SAMPLER_2D ?
1855 texture_unit.bound_texture_2d :
1856 texture_unit.bound_texture_cube_map;
1857 if (!texture_info || !texture_info->CanRender()) {
1858 *has_non_renderable_textures = true;
1859 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
1860 glBindTexture(
1861 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
1862 GL_TEXTURE_CUBE_MAP,
1863 uniform_info->type == GL_SAMPLER_2D ? black_2d_texture_id_ :
1864 black_cube_texture_id_);
1865 }
1866 }
1867 // else: should this be an error?
1868 }
1869 }
1870}
1871
1872void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
1873 DCHECK(current_program_);
1874 DCHECK(!current_program_->IsDeleted());
1875 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
1876 current_program_->sampler_indices();
1877 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
1878 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
1879 current_program_->GetUniformInfo(sampler_indices[ii]);
1880 DCHECK(uniform_info);
1881 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
1882 GLuint texture_unit_index = uniform_info->texture_units[jj];
1883 if (texture_unit_index < group_->max_texture_units()) {
1884 TextureUnit& texture_unit = texture_units_[texture_unit_index];
1885 TextureManager::TextureInfo* texture_info =
1886 uniform_info->type == GL_SAMPLER_2D ?
1887 texture_unit.bound_texture_2d :
1888 texture_unit.bound_texture_cube_map;
1889 if (!texture_info || !texture_info->CanRender()) {
1890 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
1891 // Get the texture info that was previously bound here.
1892 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
1893 texture_unit.bound_texture_2d :
1894 texture_unit.bound_texture_cube_map;
1895 glBindTexture(texture_unit.bind_target,
1896 texture_info ? texture_info->texture_id() : 0);
1897 }
1898 }
1899 }
1900 }
1901 // Set the active texture back to whatever the user had it as.
1902 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:301903}
1904
1905bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]3916c97e2010-02-25 03:20:501906 if (!current_program_ || current_program_->IsDeleted()) {
1907 // The program does not exist.
1908 // But GL says no ERROR.
1909 return false;
1910 }
1911 // Validate that all attribs current program needs are setup correctly.
1912 const ProgramManager::ProgramInfo::AttribInfoVector& infos =
1913 current_program_->GetAttribInfos();
1914 for (size_t ii = 0; ii < infos.size(); ++ii) {
1915 GLint location = infos[ii].location;
1916 if (location < 0) {
1917 return false;
1918 }
1919 DCHECK_LT(static_cast<GLuint>(location), group_->max_vertex_attribs());
1920 if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:461921 SetGLError(GL_INVALID_OPERATION);
1922 return false;
1923 }
[email protected]07f54fcc2009-12-22 02:46:301924 }
[email protected]3916c97e2010-02-25 03:20:501925 return true;
[email protected]07f54fcc2009-12-22 02:46:301926};
1927
[email protected]f7a64ee2010-02-01 22:24:141928error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:191929 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:501930 if (!bound_element_array_buffer_ ||
1931 bound_element_array_buffer_->IsDeleted()) {
1932 SetGLError(GL_INVALID_OPERATION);
1933 } else {
[email protected]96449d2c2009-11-25 00:01:321934 GLenum mode = c.mode;
1935 GLsizei count = c.count;
1936 GLenum type = c.type;
[email protected]1d32bc82010-01-13 22:06:461937 int32 offset = c.index_offset;
[email protected]a76b0052010-03-05 00:33:181938 if (count < 0 || offset < 0) {
[email protected]d2cf0a2d2010-02-25 21:36:121939 SetGLError(GL_INVALID_VALUE);
1940 } else if (!ValidateGLenumDrawMode(mode) ||
1941 !ValidateGLenumIndexType(type)) {
[email protected]1d32bc82010-01-13 22:06:461942 SetGLError(GL_INVALID_ENUM);
[email protected]ba3176a2009-12-16 18:19:461943 } else {
[email protected]0c86dbf2010-03-05 08:14:111944 GLuint max_vertex_accessed;
1945 if (!bound_element_array_buffer_->GetMaxValueForRange(
1946 offset, count, type, &max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:461947 SetGLError(GL_INVALID_OPERATION);
1948 } else {
[email protected]0c86dbf2010-03-05 08:14:111949 if (IsDrawValid(max_vertex_accessed)) {
1950 bool has_non_renderable_textures;
1951 SetBlackTextureForNonRenderableTextures(
1952 &has_non_renderable_textures);
[email protected]3916c97e2010-02-25 03:20:501953 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]0c86dbf2010-03-05 08:14:111954 glDrawElements(mode, count, type, indices);
1955 if (has_non_renderable_textures) {
1956 RestoreStateForNonRenderableTextures();
[email protected]1d32bc82010-01-13 22:06:461957 }
1958 }
[email protected]07f54fcc2009-12-22 02:46:301959 }
[email protected]ba3176a2009-12-16 18:19:461960 }
[email protected]96449d2c2009-11-25 00:01:321961 }
[email protected]f7a64ee2010-02-01 22:24:141962 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321963}
1964
[email protected]96449d2c2009-11-25 00:01:321965// Calls glShaderSource for the various versions of the ShaderSource command.
1966// Assumes that data / data_size points to a piece of memory that is in range
1967// of whatever context it came from (shared memory, immediate memory, bucket
1968// memory.)
[email protected]45bf5152010-02-12 00:11:311969error::Error GLES2DecoderImpl::ShaderSourceHelper(
1970 GLuint shader, const char* data, uint32 data_size) {
1971 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
1972 if (!info) {
1973 SetGLError(GL_INVALID_OPERATION);
1974 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321975 }
[email protected]45bf5152010-02-12 00:11:311976 // Note: We don't actually call glShaderSource here. We wait until
1977 // the call to glCompileShader.
1978 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:141979 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321980}
1981
[email protected]f7a64ee2010-02-01 22:24:141982error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:191983 uint32 immediate_data_size, const gles2::ShaderSource& c) {
1984 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:501985 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:191986 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141987 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191988 }
[email protected]96449d2c2009-11-25 00:01:321989 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:311990 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:321991 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:461992 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:141993 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:321994 }
[email protected]45bf5152010-02-12 00:11:311995 return ShaderSourceHelper(shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:321996}
1997
[email protected]f7a64ee2010-02-01 22:24:141998error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:191999 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
2000 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:502001 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:192002 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142003 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192004 }
[email protected]96449d2c2009-11-25 00:01:322005 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:312006 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:302007 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462008 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142009 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:322010 }
[email protected]45bf5152010-02-12 00:11:312011 return ShaderSourceHelper(shader, data, data_size);
2012}
2013
[email protected]558847a2010-03-24 07:02:542014error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
2015 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
2016 GLuint shader;
2017 if (!id_manager()->GetServiceId(c.shader, &shader)) {
2018 SetGLError(GL_INVALID_VALUE);
2019 return error::kNoError;
2020 }
2021 Bucket* bucket = GetBucket(c.data_bucket_id);
2022 if (!bucket || bucket->size() == 0) {
2023 return error::kInvalidArguments;
2024 }
2025 return ShaderSourceHelper(
2026 shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
2027 bucket->size() - 1);
2028}
2029
[email protected]45bf5152010-02-12 00:11:312030void GLES2DecoderImpl::DoCompileShader(GLuint shader) {
2031 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2032 if (!info) {
2033 SetGLError(GL_INVALID_OPERATION);
2034 return;
2035 }
2036 // TODO(gman): Run shader through compiler that converts GL ES 2.0 shader
2037 // to DesktopGL shader and pass that to glShaderSource and then
2038 // glCompileShader.
2039 const char* ptr = info->source().c_str();
2040 glShaderSource(shader, 1, &ptr, NULL);
2041 glCompileShader(shader);
2042};
2043
[email protected]ddd968b82010-03-02 00:44:292044void GLES2DecoderImpl::DoGetShaderiv(
2045 GLuint shader, GLenum pname, GLint* params) {
2046 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2047 if (!info) {
2048 SetGLError(GL_INVALID_OPERATION);
2049 return;
2050 }
2051 if (pname == GL_SHADER_SOURCE_LENGTH) {
2052 *params = info->source().size();
2053 } else {
2054 glGetShaderiv(shader, pname, params);
2055 }
2056}
2057
[email protected]45bf5152010-02-12 00:11:312058void GLES2DecoderImpl::DoGetShaderSource(
2059 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst) {
2060 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2061 if (!info) {
2062 SetGLError(GL_INVALID_OPERATION);
2063 return;
2064 }
[email protected]a76b0052010-03-05 00:33:182065 // bufsize is set by the service side code and should always be positive.
2066 DCHECK_GT(bufsize, 0);
[email protected]45bf5152010-02-12 00:11:312067 const std::string& source = info->source();
2068 GLsizei size = std::min(bufsize - 1, static_cast<GLsizei>(source.size()));
2069 if (length) {
2070 *length = size;
2071 }
2072 memcpy(dst, source.c_str(), size);
2073 dst[size] = '\0';
[email protected]96449d2c2009-11-25 00:01:322074}
2075
[email protected]f7a64ee2010-02-01 22:24:142076error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:192077 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]3916c97e2010-02-25 03:20:502078 if (bound_array_buffer_ && !bound_array_buffer_->IsDeleted()) {
[email protected]96449d2c2009-11-25 00:01:322079 GLuint indx = c.indx;
2080 GLint size = c.size;
2081 GLenum type = c.type;
2082 GLboolean normalized = c.normalized;
2083 GLsizei stride = c.stride;
[email protected]07f54fcc2009-12-22 02:46:302084 GLsizei offset = c.offset;
2085 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]ba3176a2009-12-16 18:19:462086 if (!ValidateGLenumVertexAttribType(type) ||
[email protected]d2cf0a2d2010-02-25 21:36:122087 !ValidateGLintVertexAttribSize(size)) {
2088 SetGLError(GL_INVALID_ENUM);
2089 return error::kNoError;
2090 }
2091 if (indx >= group_->max_vertex_attribs() ||
2092 stride < 0 ||
2093 offset < 0) {
[email protected]ba3176a2009-12-16 18:19:462094 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142095 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322096 }
[email protected]3916c97e2010-02-25 03:20:502097 GLsizei component_size =
2098 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]07f54fcc2009-12-22 02:46:302099 GLsizei real_stride = stride != 0 ? stride : component_size * size;
2100 if (offset % component_size > 0) {
2101 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142102 return error::kNoError;
[email protected]07f54fcc2009-12-22 02:46:302103 }
2104 vertex_attrib_infos_[indx].SetInfo(
2105 bound_array_buffer_,
[email protected]07f54fcc2009-12-22 02:46:302106 size,
2107 type,
2108 real_stride,
2109 offset);
[email protected]96449d2c2009-11-25 00:01:322110 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
2111 } else {
2112 SetGLError(GL_INVALID_VALUE);
2113 }
[email protected]f7a64ee2010-02-01 22:24:142114 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322115}
2116
[email protected]f7a64ee2010-02-01 22:24:142117error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:192118 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:312119 GLint x = c.x;
2120 GLint y = c.y;
2121 GLsizei width = c.width;
2122 GLsizei height = c.height;
2123 GLenum format = c.format;
2124 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:562125 if (width < 0 || height < 0) {
2126 SetGLError(GL_INVALID_VALUE);
2127 return error::kNoError;
2128 }
[email protected]a51788e2010-02-24 21:54:252129 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:182130 uint32 pixels_size;
2131 if (!GLES2Util::ComputeImageDataSize(
2132 width, height, format, type, pack_alignment_, &pixels_size)) {
2133 return error::kOutOfBounds;
2134 }
[email protected]612d2f82009-12-08 20:49:312135 void* pixels = GetSharedMemoryAs<void*>(
2136 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:252137 Result* result = GetSharedMemoryAs<Result*>(
2138 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2139 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:142140 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462141 }
[email protected]a51788e2010-02-24 21:54:252142
[email protected]ba3176a2009-12-16 18:19:462143 if (!ValidateGLenumReadPixelFormat(format) ||
2144 !ValidateGLenumPixelType(type)) {
[email protected]d2cf0a2d2010-02-25 21:36:122145 SetGLError(GL_INVALID_ENUM);
2146 return error::kNoError;
2147 }
[email protected]57f223832010-03-19 01:57:562148 if (width == 0 || height == 0) {
2149 return error::kNoError;
2150 }
2151
2152 CopyRealGLErrorsToWrapper();
2153
2154 // Get the size of the current fbo or backbuffer.
2155 GLsizei max_width = 0;
2156 GLsizei max_height = 0;
2157 if (bound_framebuffer_ != 0) {
2158 // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
2159 // stencil.
2160 GLint fb_type = 0;
2161 glGetFramebufferAttachmentParameterivEXT(
2162 GL_FRAMEBUFFER,
2163 GL_COLOR_ATTACHMENT0,
2164 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
2165 &fb_type);
2166 switch (fb_type) {
2167 case GL_RENDERBUFFER:
2168 {
2169 GLint renderbuffer_id = 0;
2170 glGetFramebufferAttachmentParameterivEXT(
2171 GL_FRAMEBUFFER,
2172 GL_COLOR_ATTACHMENT0,
2173 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
2174 &renderbuffer_id);
2175 if (renderbuffer_id != 0) {
2176 glGetRenderbufferParameterivEXT(
2177 GL_RENDERBUFFER,
2178 GL_RENDERBUFFER_WIDTH,
2179 &max_width);
2180 glGetRenderbufferParameterivEXT(
2181 GL_RENDERBUFFER,
2182 GL_RENDERBUFFER_HEIGHT,
2183 &max_height);
2184 }
2185 break;
2186 }
2187 case GL_TEXTURE:
2188 {
2189 GLint texture_id = 0;
2190 glGetFramebufferAttachmentParameterivEXT(
2191 GL_FRAMEBUFFER,
2192 GL_COLOR_ATTACHMENT0,
2193 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
2194 &texture_id);
2195 if (texture_id != 0) {
2196 TextureManager::TextureInfo* texture_info =
2197 GetTextureInfo(texture_id);
2198 if (texture_info) {
2199 GLint level = 0;
2200 GLint face = 0;
2201 glGetFramebufferAttachmentParameterivEXT(
2202 GL_FRAMEBUFFER,
2203 GL_COLOR_ATTACHMENT0,
2204 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
2205 &level);
2206 glGetFramebufferAttachmentParameterivEXT(
2207 GL_FRAMEBUFFER,
2208 GL_COLOR_ATTACHMENT0,
2209 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
2210 &face);
2211 texture_info->GetLevelSize(
2212 face ? face : GL_TEXTURE_2D, level, &max_width, &max_height);
2213 }
2214 }
2215 break;
2216 }
2217 default:
2218 // unknown so assume max_width = 0.
2219 break;
2220 }
2221 } else {
2222 // TODO(gman): Get these values from the proper place.
2223 max_width = 300;
2224 max_height = 150;
2225 }
2226
2227 GLint max_x;
2228 GLint max_y;
2229 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]ba3176a2009-12-16 18:19:462230 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142231 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:312232 }
[email protected]57f223832010-03-19 01:57:562233
2234 if (x < 0 || y < 0 || max_x > max_width || max_y > max_height) {
2235 // The user requested an out of range area. Get the results 1 line
2236 // at a time.
2237 uint32 temp_size;
2238 if (!GLES2Util::ComputeImageDataSize(
2239 width, 1, format, type, pack_alignment_, &temp_size)) {
2240 SetGLError(GL_INVALID_VALUE);
2241 return error::kNoError;
2242 }
2243 GLsizei unpadded_row_size = temp_size;
2244 if (!GLES2Util::ComputeImageDataSize(
2245 width, 2, format, type, pack_alignment_, &temp_size)) {
2246 SetGLError(GL_INVALID_VALUE);
2247 return error::kNoError;
2248 }
2249 GLsizei padded_row_size = temp_size - unpadded_row_size;
2250 if (padded_row_size < 0 || unpadded_row_size < 0) {
2251 SetGLError(GL_INVALID_VALUE);
2252 return error::kNoError;
2253 }
2254
2255 GLint dest_x_offset = std::max(-x, 0);
2256 uint32 dest_row_offset;
2257 if (!GLES2Util::ComputeImageDataSize(
2258 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
2259 SetGLError(GL_INVALID_VALUE);
2260 return error::kNoError;
2261 }
2262
2263 // Copy each row into the larger dest rect.
2264 int8* dst = static_cast<int8*>(pixels);
2265 GLint read_x = std::max(0, x);
2266 GLint read_end_x = std::max(0, std::min(max_width, max_x));
2267 GLint read_width = read_end_x - read_x;
2268 for (GLint yy = 0; yy < height; ++yy) {
2269 GLint ry = y + yy;
2270
2271 // Clear the row.
2272 memset(dst, 0, unpadded_row_size);
2273
2274 // If the row is in range, copy it.
2275 if (ry >= 0 && ry < max_height && read_width > 0) {
2276 glReadPixels(
2277 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
2278 }
2279 dst += padded_row_size;
2280 }
2281 } else {
2282 glReadPixels(x, y, width, height, format, type, pixels);
2283 }
[email protected]a51788e2010-02-24 21:54:252284 GLenum error = glGetError();
2285 if (error == GL_NO_ERROR) {
2286 *result = true;
2287 } else {
2288 SetGLError(error);
2289 }
[email protected]f7a64ee2010-02-01 22:24:142290 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322291}
2292
[email protected]f7a64ee2010-02-01 22:24:142293error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:192294 uint32 immediate_data_size, const gles2::PixelStorei& c) {
2295 GLenum pname = c.pname;
2296 GLenum param = c.param;
[email protected]d2cf0a2d2010-02-25 21:36:122297 if (!ValidateGLenumPixelStore(pname)) {
2298 SetGLError(GL_INVALID_ENUM);
2299 return error::kNoError;
2300 }
2301 if (!ValidateGLintPixelStoreAlignment(param)) {
[email protected]ba3176a2009-12-16 18:19:462302 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142303 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192304 }
2305 glPixelStorei(pname, param);
2306 switch (pname) {
2307 case GL_PACK_ALIGNMENT:
2308 pack_alignment_ = param;
2309 break;
2310 case GL_UNPACK_ALIGNMENT:
2311 unpack_alignment_ = param;
2312 break;
2313 default:
2314 // Validation should have prevented us from getting here.
2315 DCHECK(false);
2316 break;
2317 }
[email protected]f7a64ee2010-02-01 22:24:142318 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192319}
2320
[email protected]558847a2010-03-24 07:02:542321error::Error GLES2DecoderImpl::GetAttribLocationHelper(
2322 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
2323 const std::string& name_str) {
[email protected]b9849abf2009-11-25 19:13:192324 GLuint program;
[email protected]558847a2010-03-24 07:02:542325 if (!id_manager()->GetServiceId(client_id, &program)) {
[email protected]b9849abf2009-11-25 19:13:192326 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142327 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192328 }
[email protected]0bfd9882010-02-05 23:02:252329 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2330 if (!info) {
2331 // Program was not linked successfully. (ie, glLinkProgram)
2332 SetGLError(GL_INVALID_OPERATION);
2333 return error::kNoError;
2334 }
[email protected]b9849abf2009-11-25 19:13:192335 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:542336 location_shm_id, location_shm_offset, sizeof(GLint));
2337 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:142338 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192339 }
[email protected]558847a2010-03-24 07:02:542340 // Require the client to init this incase the context is lost and we are no
2341 // longer executing commands.
2342 if (*location != -1) {
2343 return error::kGenericError;
2344 }
[email protected]0bfd9882010-02-05 23:02:252345 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142346 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192347}
2348
[email protected]558847a2010-03-24 07:02:542349error::Error GLES2DecoderImpl::HandleGetAttribLocation(
2350 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
2351 uint32 name_size = c.data_size;
2352 const char* name = GetSharedMemoryAs<const char*>(
2353 c.name_shm_id, c.name_shm_offset, name_size);
2354 if (!name) {
2355 return error::kOutOfBounds;
2356 }
2357 String name_str(name, name_size);
2358 return GetAttribLocationHelper(
2359 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2360}
2361
[email protected]f7a64ee2010-02-01 22:24:142362error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192363 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:542364 uint32 name_size = c.data_size;
2365 const char* name = GetImmediateDataAs<const char*>(
2366 c, name_size, immediate_data_size);
2367 if (!name) {
2368 return error::kOutOfBounds;
2369 }
2370 String name_str(name, name_size);
2371 return GetAttribLocationHelper(
2372 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2373}
2374
2375error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
2376 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
2377 Bucket* bucket = GetBucket(c.name_bucket_id);
2378 if (!bucket) {
2379 return error::kInvalidArguments;
2380 }
2381 std::string name_str;
2382 bucket->GetAsString(&name_str);
2383 return GetAttribLocationHelper(
2384 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2385}
2386
2387error::Error GLES2DecoderImpl::GetUniformLocationHelper(
2388 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
2389 const std::string& name_str) {
[email protected]b9849abf2009-11-25 19:13:192390 GLuint program;
[email protected]558847a2010-03-24 07:02:542391 if (!id_manager()->GetServiceId(client_id, &program)) {
[email protected]b9849abf2009-11-25 19:13:192392 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142393 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192394 }
[email protected]0bfd9882010-02-05 23:02:252395 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2396 if (!info) {
2397 // Program was not linked successfully. (ie, glLinkProgram)
2398 SetGLError(GL_INVALID_OPERATION);
2399 return error::kNoError;
2400 }
[email protected]b9849abf2009-11-25 19:13:192401 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:542402 location_shm_id, location_shm_offset, sizeof(GLint));
2403 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:142404 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192405 }
[email protected]558847a2010-03-24 07:02:542406 // Require the client to init this incase the context is lost an we are no
2407 // longer executing commands.
2408 if (*location != -1) {
2409 return error::kGenericError;
2410 }
2411 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142412 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192413}
2414
[email protected]f7a64ee2010-02-01 22:24:142415error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:192416 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:192417 uint32 name_size = c.data_size;
2418 const char* name = GetSharedMemoryAs<const char*>(
2419 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:542420 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:142421 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192422 }
2423 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:542424 return GetUniformLocationHelper(
2425 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:192426}
2427
[email protected]f7a64ee2010-02-01 22:24:142428error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192429 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:192430 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:302431 const char* name = GetImmediateDataAs<const char*>(
2432 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:542433 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:142434 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192435 }
2436 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:542437 return GetUniformLocationHelper(
2438 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2439}
2440
2441error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
2442 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
2443 Bucket* bucket = GetBucket(c.name_bucket_id);
2444 if (!bucket) {
2445 return error::kInvalidArguments;
2446 }
2447 std::string name_str;
2448 bucket->GetAsString(&name_str);
2449 return GetUniformLocationHelper(
2450 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:192451}
2452
[email protected]ddd968b82010-03-02 00:44:292453error::Error GLES2DecoderImpl::HandleGetString(
2454 uint32 immediate_data_size, const gles2::GetString& c) {
2455 GLenum name = static_cast<GLenum>(c.name);
2456 if (!ValidateGLenumStringType(name)) {
2457 SetGLError(GL_INVALID_ENUM);
2458 return error::kNoError;
2459 }
2460 Bucket* bucket = CreateBucket(c.bucket_id);
2461 bucket->SetFromString(reinterpret_cast<const char*>(glGetString(name)));
2462 return error::kNoError;
2463}
2464
[email protected]0c86dbf2010-03-05 08:14:112465void GLES2DecoderImpl::DoBufferData(
2466 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]3b6ec202010-03-05 05:16:232467 if (!ValidateGLenumBufferTarget(target) ||
2468 !ValidateGLenumBufferUsage(usage)) {
2469 SetGLError(GL_INVALID_ENUM);
[email protected]0c86dbf2010-03-05 08:14:112470 return;
[email protected]3b6ec202010-03-05 05:16:232471 }
2472 if (size < 0) {
2473 SetGLError(GL_INVALID_VALUE);
[email protected]0c86dbf2010-03-05 08:14:112474 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232475 }
2476 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
2477 if (!info) {
2478 SetGLError(GL_INVALID_OPERATION);
[email protected]0c86dbf2010-03-05 08:14:112479 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232480 }
2481 // Clear the buffer to 0 if no initial data was passed in.
2482 scoped_array<int8> zero;
2483 if (!data) {
2484 zero.reset(new int8[size]);
2485 memset(zero.get(), 0, size);
2486 data = zero.get();
2487 }
2488 CopyRealGLErrorsToWrapper();
2489 glBufferData(target, size, data, usage);
2490 GLenum error = glGetError();
2491 if (error != GL_NO_ERROR) {
2492 SetGLError(error);
2493 } else {
[email protected]0c86dbf2010-03-05 08:14:112494 info->SetSize(size);
2495 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:232496 }
[email protected]0c86dbf2010-03-05 08:14:112497}
2498
2499error::Error GLES2DecoderImpl::HandleBufferData(
2500 uint32 immediate_data_size, const gles2::BufferData& c) {
2501 GLenum target = static_cast<GLenum>(c.target);
2502 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
2503 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
2504 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
2505 GLenum usage = static_cast<GLenum>(c.usage);
2506 const void* data = NULL;
2507 if (data_shm_id != 0 || data_shm_offset != 0) {
2508 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
2509 if (!data) {
2510 return error::kOutOfBounds;
2511 }
2512 }
2513 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:142514 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192515}
2516
[email protected]f7a64ee2010-02-01 22:24:142517error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:192518 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
2519 GLenum target = static_cast<GLenum>(c.target);
2520 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:302521 const void* data = GetImmediateDataAs<const void*>(
2522 c, size, immediate_data_size);
2523 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142524 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:302525 }
[email protected]b9849abf2009-11-25 19:13:192526 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:112527 DoBufferData(target, size, data, usage);
2528 return error::kNoError;
2529}
2530
2531void GLES2DecoderImpl::DoBufferSubData(
2532 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:502533 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472534 if (!info) {
2535 SetGLError(GL_INVALID_OPERATION);
[email protected]a93bb842010-02-16 23:03:472536 }
[email protected]0c86dbf2010-03-05 08:14:112537 if (!info->SetRange(offset, size, data)) {
2538 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:302539 } else {
[email protected]0c86dbf2010-03-05 08:14:112540 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:302541 }
[email protected]b9849abf2009-11-25 19:13:192542}
2543
[email protected]a93bb842010-02-16 23:03:472544error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
2545 GLenum target,
2546 GLint level,
2547 GLenum internal_format,
2548 GLsizei width,
2549 GLsizei height,
2550 GLint border,
2551 GLsizei image_size,
2552 const void* data) {
[email protected]a93bb842010-02-16 23:03:472553 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]86093972010-03-11 00:13:562554 if (!ValidateGLenumTextureTarget(target) ||
2555 !ValidateGLenumCompressedTextureInternalFormat(internal_format)) {
[email protected]a93bb842010-02-16 23:03:472556 SetGLError(GL_INVALID_ENUM);
2557 return error::kNoError;
2558 }
[email protected]3916c97e2010-02-25 03:20:502559 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:472560 border != 0) {
2561 SetGLError(GL_INVALID_VALUE);
2562 return error::kNoError;
2563 }
[email protected]3916c97e2010-02-25 03:20:502564 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472565 if (!info) {
2566 SetGLError(GL_INVALID_OPERATION);
2567 return error::kNoError;
2568 }
2569 scoped_array<int8> zero;
2570 if (!data) {
2571 zero.reset(new int8[image_size]);
2572 memset(zero.get(), 0, image_size);
2573 data = zero.get();
2574 }
2575 info->SetLevelInfo(
2576 target, level, internal_format, width, height, 1, border, 0, 0);
2577 glCompressedTexImage2D(
2578 target, level, internal_format, width, height, border, image_size, data);
2579 return error::kNoError;
2580}
2581
[email protected]f7a64ee2010-02-01 22:24:142582error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192583 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
2584 GLenum target = static_cast<GLenum>(c.target);
2585 GLint level = static_cast<GLint>(c.level);
2586 GLenum internal_format = static_cast<GLenum>(c.internalformat);
2587 GLsizei width = static_cast<GLsizei>(c.width);
2588 GLsizei height = static_cast<GLsizei>(c.height);
2589 GLint border = static_cast<GLint>(c.border);
2590 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
2591 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
2592 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
2593 const void* data = NULL;
2594 if (data_shm_id != 0 || data_shm_offset != 0) {
2595 data = GetSharedMemoryAs<const void*>(
2596 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:462597 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142598 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192599 }
2600 }
[email protected]a93bb842010-02-16 23:03:472601 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192602 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:192603}
2604
[email protected]f7a64ee2010-02-01 22:24:142605error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:192606 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
2607 GLenum target = static_cast<GLenum>(c.target);
2608 GLint level = static_cast<GLint>(c.level);
2609 GLenum internal_format = static_cast<GLenum>(c.internalformat);
2610 GLsizei width = static_cast<GLsizei>(c.width);
2611 GLsizei height = static_cast<GLsizei>(c.height);
2612 GLint border = static_cast<GLint>(c.border);
2613 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:302614 const void* data = GetImmediateDataAs<const void*>(
2615 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462616 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142617 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462618 }
[email protected]a93bb842010-02-16 23:03:472619 return DoCompressedTexImage2D(
2620 target, level, internal_format, width, height, border, image_size, data);
2621}
2622
[email protected]a93bb842010-02-16 23:03:472623error::Error GLES2DecoderImpl::DoTexImage2D(
2624 GLenum target,
2625 GLint level,
2626 GLenum internal_format,
2627 GLsizei width,
2628 GLsizei height,
2629 GLint border,
2630 GLenum format,
2631 GLenum type,
2632 const void* pixels,
2633 uint32 pixels_size) {
2634 if (!ValidateGLenumTextureTarget(target) ||
2635 !ValidateGLenumTextureFormat(internal_format) ||
2636 !ValidateGLenumTextureFormat(format) ||
2637 !ValidateGLenumPixelType(type)) {
[email protected]8bf5a3e2010-01-29 04:21:362638 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:142639 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192640 }
[email protected]3916c97e2010-02-25 03:20:502641 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:472642 border != 0) {
2643 SetGLError(GL_INVALID_VALUE);
2644 return error::kNoError;
2645 }
[email protected]3916c97e2010-02-25 03:20:502646 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472647 if (!info) {
2648 SetGLError(GL_INVALID_OPERATION);
2649 return error::kNoError;
2650 }
2651 scoped_array<int8> zero;
2652 if (!pixels) {
2653 zero.reset(new int8[pixels_size]);
2654 memset(zero.get(), 0, pixels_size);
2655 pixels = zero.get();
2656 }
2657 info->SetLevelInfo(
2658 target, level, internal_format, width, height, 1, border, format, type);
2659 glTexImage2D(
2660 target, level, internal_format, width, height, border, format, type,
2661 pixels);
[email protected]f7a64ee2010-02-01 22:24:142662 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192663}
2664
[email protected]f7a64ee2010-02-01 22:24:142665error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192666 uint32 immediate_data_size, const gles2::TexImage2D& c) {
2667 GLenum target = static_cast<GLenum>(c.target);
2668 GLint level = static_cast<GLint>(c.level);
2669 GLint internal_format = static_cast<GLint>(c.internalformat);
2670 GLsizei width = static_cast<GLsizei>(c.width);
2671 GLsizei height = static_cast<GLsizei>(c.height);
2672 GLint border = static_cast<GLint>(c.border);
2673 GLenum format = static_cast<GLenum>(c.format);
2674 GLenum type = static_cast<GLenum>(c.type);
2675 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
2676 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:182677 uint32 pixels_size;
2678 if (!GLES2Util::ComputeImageDataSize(
2679 width, height, format, type, unpack_alignment_, &pixels_size)) {
2680 return error::kOutOfBounds;
2681 }
[email protected]b9849abf2009-11-25 19:13:192682 const void* pixels = NULL;
2683 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
2684 pixels = GetSharedMemoryAs<const void*>(
2685 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:462686 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:142687 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192688 }
2689 }
[email protected]a93bb842010-02-16 23:03:472690 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192691 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:472692 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:192693}
2694
[email protected]f7a64ee2010-02-01 22:24:142695error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:192696 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
2697 GLenum target = static_cast<GLenum>(c.target);
2698 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:462699 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:192700 GLsizei width = static_cast<GLsizei>(c.width);
2701 GLsizei height = static_cast<GLsizei>(c.height);
2702 GLint border = static_cast<GLint>(c.border);
2703 GLenum format = static_cast<GLenum>(c.format);
2704 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:182705 uint32 size;
2706 if (!GLES2Util::ComputeImageDataSize(
2707 width, height, format, type, unpack_alignment_, &size)) {
2708 return error::kOutOfBounds;
2709 }
[email protected]07f54fcc2009-12-22 02:46:302710 const void* pixels = GetImmediateDataAs<const void*>(
2711 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462712 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:142713 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462714 }
[email protected]a93bb842010-02-16 23:03:472715 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:462716 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:472717 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:142718 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322719}
2720
[email protected]f7a64ee2010-02-01 22:24:142721error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:192722 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:362723 GLuint index = static_cast<GLuint>(c.index);
2724 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:252725 typedef gles2::GetVertexAttribPointerv::Result Result;
2726 Result* result = GetSharedMemoryAs<Result*>(
2727 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:362728 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:142729 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:362730 }
[email protected]07d0cc82010-02-17 04:51:402731 // Check that the client initialized the result.
2732 if (result->size != 0) {
2733 return error::kInvalidArguments;
2734 }
[email protected]8bf5a3e2010-01-29 04:21:362735 if (!ValidateGLenumVertexPointer(pname)) {
2736 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:142737 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:362738 }
[email protected]3916c97e2010-02-25 03:20:502739 if (index >= group_->max_vertex_attribs()) {
[email protected]8bf5a3e2010-01-29 04:21:362740 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142741 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:362742 }
[email protected]0bfd9882010-02-05 23:02:252743 result->SetNumResults(1);
2744 *result->GetData() = vertex_attrib_infos_[index].offset();
[email protected]f7a64ee2010-02-01 22:24:142745 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322746}
2747
[email protected]f7b85372010-02-03 01:11:372748bool GLES2DecoderImpl::GetUniformSetup(
2749 GLuint program, GLint location,
2750 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:252751 error::Error* error, GLuint* service_id, void** result_pointer) {
[email protected]f7b85372010-02-03 01:11:372752 *error = error::kNoError;
2753 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:252754 SizedResult<GLint>* result;
2755 result = GetSharedMemoryAs<SizedResult<GLint>*>(
2756 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
2757 if (!result) {
[email protected]f7b85372010-02-03 01:11:372758 *error = error::kOutOfBounds;
2759 return false;
2760 }
[email protected]0bfd9882010-02-05 23:02:252761 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:372762 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:252763 result->SetNumResults(0);
[email protected]3916c97e2010-02-25 03:20:502764 if (!id_manager()->GetServiceId(program, service_id)) {
[email protected]f7b85372010-02-03 01:11:372765 SetGLError(GL_INVALID_VALUE);
2766 return error::kNoError;
2767 }
2768 ProgramManager::ProgramInfo* info = GetProgramInfo(*service_id);
2769 if (!info) {
2770 // Program was not linked successfully. (ie, glLinkProgram)
2771 SetGLError(GL_INVALID_OPERATION);
2772 return false;
2773 }
[email protected]0bfd9882010-02-05 23:02:252774 GLenum type;
2775 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:372776 // No such location.
2777 SetGLError(GL_INVALID_OPERATION);
2778 return false;
2779 }
[email protected]3916c97e2010-02-25 03:20:502780 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:372781 if (size == 0) {
2782 SetGLError(GL_INVALID_OPERATION);
2783 return false;
2784 }
[email protected]0bfd9882010-02-05 23:02:252785 result = GetSharedMemoryAs<SizedResult<GLint>*>(
2786 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
2787 if (!result) {
[email protected]f7b85372010-02-03 01:11:372788 *error = error::kOutOfBounds;
2789 return false;
2790 }
[email protected]0bfd9882010-02-05 23:02:252791 result->size = size;
[email protected]f7b85372010-02-03 01:11:372792 return true;
2793}
2794
[email protected]f7a64ee2010-02-01 22:24:142795error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:192796 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:372797 GLuint program = c.program;
2798 GLint location = c.location;
2799 GLuint service_id;
2800 Error error;
[email protected]0bfd9882010-02-05 23:02:252801 void* result;
[email protected]f7b85372010-02-03 01:11:372802 if (GetUniformSetup(
2803 program, location, c.params_shm_id, c.params_shm_offset,
2804 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:252805 glGetUniformiv(
2806 service_id, location,
2807 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:372808 }
2809 return error;
[email protected]96449d2c2009-11-25 00:01:322810}
2811
[email protected]f7a64ee2010-02-01 22:24:142812error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:192813 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:372814 GLuint program = c.program;
2815 GLint location = c.location;
2816 GLuint service_id;
2817 Error error;
[email protected]0bfd9882010-02-05 23:02:252818 void* result;
2819 typedef gles2::GetUniformfv::Result Result;
[email protected]f7b85372010-02-03 01:11:372820 if (GetUniformSetup(
2821 program, location, c.params_shm_id, c.params_shm_offset,
2822 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:252823 glGetUniformfv(
2824 service_id,
2825 location,
2826 static_cast<gles2::GetUniformfv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:372827 }
2828 return error;
[email protected]96449d2c2009-11-25 00:01:322829}
2830
[email protected]f7a64ee2010-02-01 22:24:142831error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:192832 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:252833 GLenum shader_type = static_cast<GLenum>(c.shadertype);
2834 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
2835 typedef gles2::GetShaderPrecisionFormat::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]0bfd9882010-02-05 23:02:252845 if (!ValidateGLenumShaderType(shader_type) ||
2846 !ValidateGLenumShaderPrecision(precision_type)) {
[email protected]0bfd9882010-02-05 23:02:252847 SetGLError(GL_INVALID_ENUM);
2848 } else {
2849 result->success = 1; // true
2850 switch (precision_type) {
2851 case GL_LOW_INT:
2852 case GL_MEDIUM_INT:
2853 case GL_HIGH_INT:
2854 result->min_range = -31;
2855 result->max_range = 31;
2856 result->precision = 0;
2857 case GL_LOW_FLOAT:
2858 case GL_MEDIUM_FLOAT:
2859 case GL_HIGH_FLOAT:
2860 result->min_range = -62;
2861 result->max_range = 62;
2862 result->precision = -16;
2863 break;
2864 default:
2865 NOTREACHED();
2866 break;
2867 }
2868 }
[email protected]f7a64ee2010-02-01 22:24:142869 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322870}
2871
[email protected]f7a64ee2010-02-01 22:24:142872error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:192873 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:252874 GLuint service_id;
2875 uint32 result_size = c.result_size;
[email protected]3916c97e2010-02-25 03:20:502876 if (!id_manager()->GetServiceId(c.program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252877 SetGLError(GL_INVALID_VALUE);
2878 return error::kNoError;
2879 }
2880 typedef gles2::GetAttachedShaders::Result Result;
2881 uint32 max_count = Result::ComputeMaxResults(result_size);
2882 Result* result = GetSharedMemoryAs<Result*>(
2883 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
2884 if (!result) {
2885 return error::kOutOfBounds;
2886 }
[email protected]07d0cc82010-02-17 04:51:402887 // Check that the client initialized the result.
2888 if (result->size != 0) {
2889 return error::kInvalidArguments;
2890 }
[email protected]0bfd9882010-02-05 23:02:252891 GLsizei count = 0;
2892 glGetAttachedShaders(service_id, max_count, &count, result->GetData());
2893 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]3916c97e2010-02-25 03:20:502894 if (!id_manager()->GetClientId(result->GetData()[ii],
[email protected]0bfd9882010-02-05 23:02:252895 &result->GetData()[ii])) {
2896 NOTREACHED();
2897 return error::kGenericError;
2898 }
2899 }
2900 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:142901 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322902}
2903
[email protected]f7a64ee2010-02-01 22:24:142904error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:192905 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:252906 GLuint program = c.program;
2907 GLuint index = c.index;
2908 uint32 name_bucket_id = c.name_bucket_id;
2909 GLuint service_id;
2910 typedef gles2::GetActiveUniform::Result Result;
2911 Result* result = GetSharedMemoryAs<Result*>(
2912 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2913 if (!result) {
2914 return error::kOutOfBounds;
2915 }
[email protected]07d0cc82010-02-17 04:51:402916 // Check that the client initialized the result.
2917 if (result->success != 0) {
2918 return error::kInvalidArguments;
2919 }
[email protected]3916c97e2010-02-25 03:20:502920 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252921 SetGLError(GL_INVALID_VALUE);
2922 return error::kNoError;
2923 }
2924 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
2925 if (!info) {
2926 // Program was not linked successfully. (ie, glLinkProgram)
2927 SetGLError(GL_INVALID_OPERATION);
2928 return error::kNoError;
2929 }
2930 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2931 info->GetUniformInfo(index);
2932 if (!uniform_info) {
2933 SetGLError(GL_INVALID_VALUE);
2934 return error::kNoError;
2935 }
2936 result->success = 1; // true.
2937 result->size = uniform_info->size;
2938 result->type = uniform_info->type;
2939 Bucket* bucket = CreateBucket(name_bucket_id);
2940 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:142941 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322942}
2943
[email protected]f7a64ee2010-02-01 22:24:142944error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:192945 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:252946 GLuint program = c.program;
2947 GLuint index = c.index;
2948 uint32 name_bucket_id = c.name_bucket_id;
2949 GLuint service_id;
2950 typedef gles2::GetActiveAttrib::Result Result;
2951 Result* result = GetSharedMemoryAs<Result*>(
2952 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2953 if (!result) {
2954 return error::kOutOfBounds;
2955 }
[email protected]07d0cc82010-02-17 04:51:402956 // Check that the client initialized the result.
2957 if (result->success != 0) {
2958 return error::kInvalidArguments;
2959 }
[email protected]3916c97e2010-02-25 03:20:502960 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252961 SetGLError(GL_INVALID_VALUE);
2962 return error::kNoError;
2963 }
2964 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
2965 if (!info) {
2966 // Program was not linked successfully. (ie, glLinkProgram)
2967 SetGLError(GL_INVALID_OPERATION);
2968 return error::kNoError;
2969 }
2970 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
2971 info->GetAttribInfo(index);
2972 if (!attrib_info) {
2973 SetGLError(GL_INVALID_VALUE);
2974 return error::kNoError;
2975 }
2976 result->success = 1; // true.
2977 result->size = attrib_info->size;
2978 result->type = attrib_info->type;
2979 Bucket* bucket = CreateBucket(name_bucket_id);
2980 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:142981 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322982}
2983
2984// Include the auto-generated part of this file. We split this because it means
2985// we can easily edit the non-auto generated parts right here in this file
2986// instead of having to edit some template or the code generator.
2987#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
2988
2989} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:252990} // namespace gpu