blob: 706407a3b1aaf52cf8958b8776c9d922c71af11d [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]2041cf342010-02-19 03:15:5913#include "base/callback.h"
[email protected]a93bb842010-02-16 23:03:4714#include "base/linked_ptr.h"
[email protected]96449d2c2009-11-25 00:01:3215#include "base/scoped_ptr.h"
[email protected]6217d392010-03-25 22:08:3516#include "base/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0217#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3218#define GLES2_GPU_SERVICE 1
19#include "gpu/command_buffer/common/gles2_cmd_format.h"
20#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]3916c97e2010-02-25 03:20:5021#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3222#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5023#include "gpu/command_buffer/service/context_group.h"
[email protected]a25fa872010-03-25 02:57:5824#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]d37231fa2010-04-09 21:16:0225#include "gpu/command_buffer/service/gl_context.h"
[email protected]96449d2c2009-11-25 00:01:3226#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4627#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4728#include "gpu/command_buffer/service/id_manager.h"
29#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5830#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4731#include "gpu/command_buffer/service/shader_manager.h"
32#include "gpu/command_buffer/service/texture_manager.h"
[email protected]96449d2c2009-11-25 00:01:3233
[email protected]6217d392010-03-25 22:08:3534#if !defined(GL_DEPTH24_STENCIL8)
35#define GL_DEPTH24_STENCIL8 0x88F0
36#endif
37
[email protected]a7a27ace2009-12-12 00:11:2538namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3239namespace gles2 {
40
[email protected]6217d392010-03-25 22:08:3541class GLES2DecoderImpl;
42
[email protected]07f54fcc2009-12-22 02:46:3043// Check that certain assumptions the code makes are true. There are places in
44// the code where shared memory is passed direclty to GL. Example, glUniformiv,
45// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
46// a few others) are 32bits. If they are not 32bits the code will have to change
47// to call those GL functions with service side memory and then copy the results
48// to shared memory, converting the sizes.
49COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
50 GLint_not_same_size_as_uint32);
51COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
52 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3753COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
54 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3055
[email protected]43f28f832010-02-03 02:28:4856// TODO(kbr): the use of this anonymous namespace core dumps the
57// linker on Mac OS X 10.6 when the symbol ordering file is used
58// namespace {
[email protected]96449d2c2009-11-25 00:01:3259
60// Returns the address of the first byte after a struct.
61template <typename T>
62const void* AddressAfterStruct(const T& pod) {
63 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
64}
65
[email protected]07f54fcc2009-12-22 02:46:3066// Returns the address of the frst byte after the struct or NULL if size >
67// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3268template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3069RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
70 uint32 size,
71 uint32 immediate_data_size) {
72 return (size <= immediate_data_size) ?
73 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
74 NULL;
[email protected]96449d2c2009-11-25 00:01:3275}
76
[email protected]07f54fcc2009-12-22 02:46:3077// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1878bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3279 GLuint count,
80 size_t size,
[email protected]a76b0052010-03-05 00:33:1881 unsigned int elements_per_unit,
82 uint32* dst) {
83 uint32 value;
84 if (!SafeMultiplyUint32(count, size, &value)) {
85 return false;
86 }
87 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
88 return false;
89 }
90 *dst = value;
91 return true;
[email protected]96449d2c2009-11-25 00:01:3292}
93
94// A struct to hold info about each command.
95struct CommandInfo {
96 int arg_flags; // How to handle the arguments for this command
97 int arg_count; // How many arguments are expected for this command.
98};
99
100// A table of CommandInfo for all the commands.
101const CommandInfo g_command_info[] = {
102 #define GLES2_CMD_OP(name) { \
103 name::kArgFlags, \
104 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
105
106 GLES2_COMMAND_LIST(GLES2_CMD_OP)
107
108 #undef GLES2_CMD_OP
109};
110
[email protected]6217d392010-03-25 22:08:35111// This class prevents any GL errors that occur when it is in scope from
112// being reported to the client.
113class ScopedGLErrorSuppressor {
114 public:
115 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
116 ~ScopedGLErrorSuppressor();
117 private:
118 GLES2DecoderImpl* decoder_;
119 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
120};
121
122// Temporarily changes a decoder's bound 2D texture and restore it when this
123// object goes out of scope. Also temporarily switches to using active texture
124// unit zero in case the client has changed that to something invalid.
125class ScopedTexture2DBinder {
126 public:
127 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
128 ~ScopedTexture2DBinder();
129
130 private:
131 GLES2DecoderImpl* decoder_;
132 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
133};
134
135// Temporarily changes a decoder's bound render buffer and restore it when this
136// object goes out of scope.
137class ScopedRenderBufferBinder {
138 public:
139 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
140 ~ScopedRenderBufferBinder();
141
142 private:
143 GLES2DecoderImpl* decoder_;
144 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
145};
146
147// Temporarily changes a decoder's bound frame buffer and restore it when this
148// object goes out of scope.
149class ScopedFrameBufferBinder {
150 public:
151 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
152 ~ScopedFrameBufferBinder();
153
154 private:
155 GLES2DecoderImpl* decoder_;
156 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
157};
158
159// Encapsulates an OpenGL texture.
160class Texture {
161 public:
162 explicit Texture(GLES2DecoderImpl* decoder);
163 ~Texture();
164
165 // Create a new render texture.
166 void Create();
167
168 // Set the initial size and format of a render texture or resize it.
169 bool AllocateStorage(const gfx::Size& size);
170
171 // Copy the contents of the currently bound frame buffer.
172 void Copy(const gfx::Size& size);
173
174 // Destroy the render texture. This must be explicitly called before
175 // destroying this object.
176 void Destroy();
177
178 GLuint id() const {
179 return id_;
180 }
181
[email protected]d37231fa2010-04-09 21:16:02182 gfx::Size size() const {
183 return size_;
184 }
185
[email protected]6217d392010-03-25 22:08:35186 private:
187 GLES2DecoderImpl* decoder_;
188 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02189 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35190 DISALLOW_COPY_AND_ASSIGN(Texture);
191};
192
193// Encapsulates an OpenGL render buffer of any format.
194class RenderBuffer {
195 public:
196 explicit RenderBuffer(GLES2DecoderImpl* decoder);
197 ~RenderBuffer();
198
199 // Create a new render buffer.
200 void Create();
201
202 // Set the initial size and format of a render buffer or resize it.
203 bool AllocateStorage(const gfx::Size& size, GLenum format);
204
205 // Destroy the render buffer. This must be explicitly called before destroying
206 // this object.
207 void Destroy();
208
209 GLuint id() const {
210 return id_;
211 }
212
213 private:
214 GLES2DecoderImpl* decoder_;
215 GLuint id_;
216 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
217};
218
219// Encapsulates an OpenGL frame buffer.
220class FrameBuffer {
221 public:
222 explicit FrameBuffer(GLES2DecoderImpl* decoder);
223 ~FrameBuffer();
224
225 // Create a new frame buffer.
226 void Create();
227
228 // Attach a color render buffer to a frame buffer.
229 void AttachRenderTexture(Texture* texture);
230
231 // Attach a depth stencil render buffer to a frame buffer. Note that
232 // this unbinds any currently bound frame buffer.
233 void AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer);
234
235 // Clear the given attached buffers.
236 void Clear(GLbitfield buffers);
237
238 // Destroy the frame buffer. This must be explicitly called before destroying
239 // this object.
240 void Destroy();
241
242 // See glCheckFramebufferStatusEXT.
243 GLenum CheckStatus();
244
245 GLuint id() const {
246 return id_;
247 }
248
249 private:
250 GLES2DecoderImpl* decoder_;
251 GLuint id_;
252 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
253};
[email protected]43f28f832010-02-03 02:28:48254// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32255
[email protected]3916c97e2010-02-25 03:20:50256GLES2Decoder::GLES2Decoder(ContextGroup* group)
257 : group_(group),
[email protected]3916c97e2010-02-25 03:20:50258 debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32259}
260
[email protected]3916c97e2010-02-25 03:20:50261GLES2Decoder::~GLES2Decoder() {
262}
263
[email protected]96449d2c2009-11-25 00:01:32264// This class implements GLES2Decoder so we don't have to expose all the GLES2
265// cmd stuff to outside this class.
[email protected]6217d392010-03-25 22:08:35266class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
267 public GLES2Decoder {
[email protected]96449d2c2009-11-25 00:01:32268 public:
[email protected]3916c97e2010-02-25 03:20:50269 explicit GLES2DecoderImpl(ContextGroup* group);
270
[email protected]07f54fcc2009-12-22 02:46:30271 // Info about Vertex Attributes. This is used to track what the user currently
272 // has bound on each Vertex Attribute so that checking can be done at
273 // glDrawXXX time.
274 class VertexAttribInfo {
275 public:
276 VertexAttribInfo()
277 : enabled_(false),
278 size_(0),
279 type_(0),
280 offset_(0),
[email protected]3916c97e2010-02-25 03:20:50281 real_stride_(0) {
[email protected]07f54fcc2009-12-22 02:46:30282 }
[email protected]3916c97e2010-02-25 03:20:50283
[email protected]07f54fcc2009-12-22 02:46:30284 // Returns true if this VertexAttrib can access index.
285 bool CanAccess(GLuint index);
286
287 void set_enabled(bool enabled) {
288 enabled_ = enabled;
289 }
290
[email protected]3916c97e2010-02-25 03:20:50291 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30292 return buffer_;
293 }
294
[email protected]8bf5a3e2010-01-29 04:21:36295 GLsizei offset() const {
296 return offset_;
297 }
298
[email protected]07f54fcc2009-12-22 02:46:30299 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50300 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30301 GLint size,
302 GLenum type,
303 GLsizei real_stride,
304 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24305 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30306 buffer_ = buffer;
307 size_ = size;
308 type_ = type;
309 real_stride_ = real_stride;
310 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50311 }
312
313 void ClearBuffer() {
314 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30315 }
316
317 private:
318 // Whether or not this attribute is enabled.
319 bool enabled_;
320
321 // number of components (1, 2, 3, 4)
322 GLint size_;
323
324 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
325 GLenum type_;
326
327 // The offset into the buffer.
328 GLsizei offset_;
329
330 // The stride that will be used to access the buffer. This is the actual
331 // stide, NOT the GL bogus stride. In other words there is never a stride
332 // of 0.
333 GLsizei real_stride_;
334
[email protected]3916c97e2010-02-25 03:20:50335 // The buffer bound to this attribute.
336 BufferManager::BufferInfo::Ref buffer_;
[email protected]07f54fcc2009-12-22 02:46:30337 };
338
[email protected]96449d2c2009-11-25 00:01:32339 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14340 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50341 unsigned int arg_count,
342 const void* args);
[email protected]96449d2c2009-11-25 00:01:32343
344 // Overridden from AsyncAPIInterface.
345 virtual const char* GetCommandName(unsigned int command_id) const;
346
347 // Overridden from GLES2Decoder.
[email protected]d37231fa2010-04-09 21:16:02348 virtual bool Initialize(GLContext* context,
[email protected]6217d392010-03-25 22:08:35349 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:02350 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35351 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32352 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35353 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]eb54a562010-01-20 21:55:18354 virtual bool MakeCurrent();
[email protected]8a837bb2010-01-05 00:21:24355 virtual uint32 GetServiceIdForTesting(uint32 client_id);
[email protected]56ac89b2010-03-17 21:16:55356 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]d37231fa2010-04-09 21:16:02357 virtual GLContext* GetGLContext() { return context_; }
[email protected]43f28f832010-02-03 02:28:48358
359 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
360
[email protected]96449d2c2009-11-25 00:01:32361 private:
[email protected]6217d392010-03-25 22:08:35362 friend class ScopedGLErrorSuppressor;
363 friend class ScopedTexture2DBinder;
364 friend class ScopedFrameBufferBinder;
365 friend class ScopedRenderBufferBinder;
366 friend class RenderBuffer;
367 friend class FrameBuffer;
368
[email protected]3916c97e2010-02-25 03:20:50369 // State associated with each texture unit.
370 struct TextureUnit {
371 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
372
373 // The last target that was bound to this texture unit.
374 GLenum bind_target;
375
376 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
377 TextureManager::TextureInfo::Ref bound_texture_2d;
378
379 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
380 // glBindTexture
381 TextureManager::TextureInfo::Ref bound_texture_cube_map;
382 };
383
[email protected]a93bb842010-02-16 23:03:47384 friend void GLGenTexturesHelper(
385 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
386 friend void GLDeleteTexturesHelper(
387 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
388 friend void GLGenBuffersHelper(
389 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
390 friend void GLDeleteBuffersHelper(
391 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
[email protected]a25fa872010-03-25 02:57:58392 friend void GLGenFramebuffersHelper(
393 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
394 friend void GLDeleteFramebuffersHelper(
395 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
396 friend void GLGenRenderbuffersHelper(
397 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
398 friend void GLDeleteRenderbuffersHelper(
399 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
[email protected]a93bb842010-02-16 23:03:47400
[email protected]3916c97e2010-02-25 03:20:50401 // TODO(gman): Cache these pointers?
402 IdManager* id_manager() {
403 return group_->id_manager();
404 }
405
406 BufferManager* buffer_manager() {
407 return group_->buffer_manager();
408 }
409
[email protected]a25fa872010-03-25 02:57:58410 RenderbufferManager* renderbuffer_manager() {
411 return group_->renderbuffer_manager();
412 }
413
414 FramebufferManager* framebuffer_manager() {
415 return group_->framebuffer_manager();
416 }
417
[email protected]3916c97e2010-02-25 03:20:50418 ProgramManager* program_manager() {
419 return group_->program_manager();
420 }
421
422 ShaderManager* shader_manager() {
423 return group_->shader_manager();
424 }
425
426 TextureManager* texture_manager() {
427 return group_->texture_manager();
428 }
429
[email protected]6217d392010-03-25 22:08:35430 bool UpdateOffscreenFrameBufferSize();
431
[email protected]96449d2c2009-11-25 00:01:32432 // Template to help call glGenXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30433 template <void gl_gen_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32434 bool GenGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12435 DCHECK_GE(n, 0);
[email protected]8a837bb2010-01-05 00:21:24436 if (!ValidateIdsAreUnused(n, client_ids)) {
437 return false;
438 }
[email protected]96449d2c2009-11-25 00:01:32439 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30440 gl_gen_function(this, n, temp.get());
[email protected]07f54fcc2009-12-22 02:46:30441 return RegisterObjects(n, client_ids, temp.get());
[email protected]96449d2c2009-11-25 00:01:32442 }
443
444 // Template to help call glDeleteXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30445 template <void gl_delete_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32446 bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12447 DCHECK_GE(n, 0);
[email protected]96449d2c2009-11-25 00:01:32448 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30449 UnregisterObjects(n, client_ids, temp.get());
450 gl_delete_function(this, n, temp.get());
[email protected]96449d2c2009-11-25 00:01:32451 return true;
452 }
453
[email protected]8a837bb2010-01-05 00:21:24454 // Check that the given ids are not used.
455 bool ValidateIdsAreUnused(GLsizei n, const GLuint* client_ids);
456
[email protected]07f54fcc2009-12-22 02:46:30457 // Register client ids with generated service ids.
458 bool RegisterObjects(
459 GLsizei n, const GLuint* client_ids, const GLuint* service_ids);
460
461 // Unregisters client ids with service ids.
462 void UnregisterObjects(
463 GLsizei n, const GLuint* client_ids, GLuint* service_ids);
464
[email protected]a93bb842010-02-16 23:03:47465 // Creates a TextureInfo for the given texture.
[email protected]6217d392010-03-25 22:08:35466 TextureManager::TextureInfo* CreateTextureInfo(GLuint texture) {
467 return texture_manager()->CreateTextureInfo(texture);
[email protected]a93bb842010-02-16 23:03:47468 }
469
470 // Gets the texture info for the given texture. Returns NULL if none exists.
471 TextureManager::TextureInfo* GetTextureInfo(GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:50472 TextureManager::TextureInfo* info =
473 texture_manager()->GetTextureInfo(texture);
474 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47475 }
476
477 // Deletes the texture info for the given texture.
[email protected]3916c97e2010-02-25 03:20:50478 void RemoveTextureInfo(GLuint texture) {
479 texture_manager()->RemoveTextureInfo(texture);
480 }
[email protected]a93bb842010-02-16 23:03:47481
[email protected]d37231fa2010-04-09 21:16:02482 // Get the size (in pixels) of the currently bound frame buffer (either FBO
483 // or regular back buffer).
484 gfx::Size GetBoundFrameBufferSize();
485
[email protected]a93bb842010-02-16 23:03:47486 // Wrapper for CompressedTexImage2D commands.
487 error::Error DoCompressedTexImage2D(
488 GLenum target,
489 GLint level,
490 GLenum internal_format,
491 GLsizei width,
492 GLsizei height,
493 GLint border,
494 GLsizei image_size,
495 const void* data);
496
497 // Wrapper for TexImage2D commands.
498 error::Error DoTexImage2D(
499 GLenum target,
500 GLint level,
501 GLenum internal_format,
502 GLsizei width,
503 GLsizei height,
504 GLint border,
505 GLenum format,
506 GLenum type,
507 const void* pixels,
508 uint32 pixels_size);
509
510 // Creates a ProgramInfo for the given program.
511 void CreateProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50512 program_manager()->CreateProgramInfo(program);
[email protected]a93bb842010-02-16 23:03:47513 }
514
[email protected]07f54fcc2009-12-22 02:46:30515 // Gets the program info for the given program. Returns NULL if none exists.
516 // Programs that have no had glLinkProgram succesfully called on them will
517 // not exist.
[email protected]1d32bc82010-01-13 22:06:46518 ProgramManager::ProgramInfo* GetProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50519 ProgramManager::ProgramInfo* info =
520 program_manager()->GetProgramInfo(program);
521 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46522 }
[email protected]07f54fcc2009-12-22 02:46:30523
[email protected]07f54fcc2009-12-22 02:46:30524 // Deletes the program info for the given program.
[email protected]1d32bc82010-01-13 22:06:46525 void RemoveProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50526 program_manager()->RemoveProgramInfo(program);
[email protected]1d32bc82010-01-13 22:06:46527 }
[email protected]07f54fcc2009-12-22 02:46:30528
[email protected]45bf5152010-02-12 00:11:31529 // Creates a ShaderInfo for the given shader.
530 void CreateShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50531 shader_manager()->CreateShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31532 }
533
534 // Gets the shader info for the given shader. Returns NULL if none exists.
535 ShaderManager::ShaderInfo* GetShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50536 ShaderManager::ShaderInfo* info = shader_manager()->GetShaderInfo(shader);
537 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]45bf5152010-02-12 00:11:31538 }
539
540 // Deletes the shader info for the given shader.
541 void RemoveShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50542 shader_manager()->RemoveShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31543 }
544
[email protected]a93bb842010-02-16 23:03:47545 // Creates a buffer info for the given buffer.
546 void CreateBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50547 return buffer_manager()->CreateBufferInfo(buffer);
[email protected]a93bb842010-02-16 23:03:47548 }
549
[email protected]07f54fcc2009-12-22 02:46:30550 // Gets the buffer info for the given buffer.
[email protected]1d32bc82010-01-13 22:06:46551 BufferManager::BufferInfo* GetBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50552 BufferManager::BufferInfo* info = buffer_manager()->GetBufferInfo(buffer);
553 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46554 }
[email protected]07f54fcc2009-12-22 02:46:30555
[email protected]a93bb842010-02-16 23:03:47556 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
557 // on glDeleteBuffers so we can make sure the user does not try to render
558 // with deleted buffers.
559 void RemoveBufferInfo(GLuint buffer_id);
560
[email protected]a25fa872010-03-25 02:57:58561 // Creates a framebuffer info for the given framebuffer.
562 void CreateFramebufferInfo(GLuint framebuffer) {
563 return framebuffer_manager()->CreateFramebufferInfo(framebuffer);
564 }
565
566 // Gets the framebuffer info for the given framebuffer.
567 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
568 GLuint framebuffer) {
569 FramebufferManager::FramebufferInfo* info =
570 framebuffer_manager()->GetFramebufferInfo(framebuffer);
571 return (info && !info->IsDeleted()) ? info : NULL;
572 }
573
574 // Removes the framebuffer info for the given framebuffer.
575 void RemoveFramebufferInfo(GLuint framebuffer_id) {
576 framebuffer_manager()->RemoveFramebufferInfo(framebuffer_id);
577 }
578
579 // Creates a renderbuffer info for the given renderbuffer.
580 void CreateRenderbufferInfo(GLuint renderbuffer) {
581 return renderbuffer_manager()->CreateRenderbufferInfo(renderbuffer);
582 }
583
584 // Gets the renderbuffer info for the given renderbuffer.
585 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
586 GLuint renderbuffer) {
587 RenderbufferManager::RenderbufferInfo* info =
588 renderbuffer_manager()->GetRenderbufferInfo(renderbuffer);
589 return (info && !info->IsDeleted()) ? info : NULL;
590 }
591
592 // Removes the renderbuffer info for the given renderbuffer.
593 void RemoveRenderbufferInfo(GLuint renderbuffer_id) {
594 renderbuffer_manager()->RemoveRenderbufferInfo(renderbuffer_id);
595 }
596
[email protected]558847a2010-03-24 07:02:54597 error::Error GetAttribLocationHelper(
598 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
599 const std::string& name_str);
600
601 error::Error GetUniformLocationHelper(
602 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
603 const std::string& name_str);
604
[email protected]3916c97e2010-02-25 03:20:50605 // Helper for glShaderSource.
606 error::Error ShaderSourceHelper(
607 GLuint shader, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30608
[email protected]b273e432010-04-12 17:23:58609 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
610 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
611
[email protected]96449d2c2009-11-25 00:01:32612 // Wrapper for glCreateProgram
613 void CreateProgramHelper(GLuint client_id);
614
615 // Wrapper for glCreateShader
616 void CreateShaderHelper(GLenum type, GLuint client_id);
617
[email protected]3916c97e2010-02-25 03:20:50618 // Wrapper for glActiveTexture
619 void DoActiveTexture(GLenum texture_unit);
620
[email protected]96449d2c2009-11-25 00:01:32621 // Wrapper for glBindBuffer since we need to track the current targets.
622 void DoBindBuffer(GLenum target, GLuint buffer);
623
[email protected]86093972010-03-11 00:13:56624 // Wrapper for glBindFramebuffer since we need to track the current targets.
625 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
626
627 // Wrapper for glBindRenderbuffer since we need to track the current targets.
628 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
629
[email protected]a93bb842010-02-16 23:03:47630 // Wrapper for glBindTexture since we need to track the current targets.
631 void DoBindTexture(GLenum target, GLuint texture);
632
[email protected]36cef8ce2010-03-16 07:34:45633 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11634 void DoBufferData(
635 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
636
[email protected]36cef8ce2010-03-16 07:34:45637 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11638 void DoBufferSubData(
639 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
640
[email protected]36cef8ce2010-03-16 07:34:45641 // Wrapper for glCheckFramebufferStatus
642 GLenum DoCheckFramebufferStatus(GLenum target);
643
[email protected]45bf5152010-02-12 00:11:31644 // Wrapper for glCompileShader.
645 void DoCompileShader(GLuint shader);
646
[email protected]07f54fcc2009-12-22 02:46:30647 // Wrapper for glDrawArrays.
648 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
649
650 // Wrapper for glDisableVertexAttribArray.
651 void DoDisableVertexAttribArray(GLuint index);
652
653 // Wrapper for glEnableVertexAttribArray.
654 void DoEnableVertexAttribArray(GLuint index);
655
[email protected]36cef8ce2010-03-16 07:34:45656 // Wrapper for glFramebufferRenderbufffer.
657 void DoFramebufferRenderbuffer(
658 GLenum target, GLenum attachment, GLenum renderbuffertarget,
659 GLuint renderbuffer);
660
661 // Wrapper for glFramebufferTexture2D.
662 void DoFramebufferTexture2D(
663 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
664 GLint level);
665
[email protected]a93bb842010-02-16 23:03:47666 // Wrapper for glGenerateMipmap
667 void DoGenerateMipmap(GLenum target);
668
[email protected]b273e432010-04-12 17:23:58669 // Wrapper for DoGetBooleanv.
670 void DoGetBooleanv(GLenum pname, GLboolean* params);
671
672 // Wrapper for DoGetFloatv.
673 void DoGetFloatv(GLenum pname, GLfloat* params);
674
[email protected]36cef8ce2010-03-16 07:34:45675 // Wrapper for glGetFramebufferAttachmentParameteriv.
676 void DoGetFramebufferAttachmentParameteriv(
677 GLenum target, GLenum attachment, GLenum pname, GLint* params);
678
[email protected]b273e432010-04-12 17:23:58679 // Wrapper for DoGetIntegerv.
680 void DoGetIntegerv(GLenum pname, GLint* params);
681
[email protected]36cef8ce2010-03-16 07:34:45682 // Wrapper for glRenderbufferParameteriv.
683 void DoGetRenderbufferParameteriv(
684 GLenum target, GLenum pname, GLint* params);
685
[email protected]ddd968b82010-03-02 00:44:29686 // Wrapper for glGetShaderiv
687 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
688
[email protected]45bf5152010-02-12 00:11:31689 // Wrapper for glGetShaderSource.
690 void DoGetShaderSource(
691 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst);
692
[email protected]07f54fcc2009-12-22 02:46:30693 // Wrapper for glLinkProgram
694 void DoLinkProgram(GLuint program);
695
[email protected]36cef8ce2010-03-16 07:34:45696 // Wrapper for glRenderbufferStorage.
697 void DoRenderbufferStorage(
698 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
699
[email protected]b273e432010-04-12 17:23:58700 // Wrapper for glReleaseShaderCompiler.
701 void DoReleaseShaderCompiler() { }
702
[email protected]3916c97e2010-02-25 03:20:50703 // Wrappers for glTexParameter functions.
704 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
705 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
706 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
707 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
708
709 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
710 // spec only these 2 functions can be used to set sampler uniforms.
711 void DoUniform1i(GLint location, GLint v0);
712 void DoUniform1iv(GLint location, GLsizei count, const GLint *value);
713
[email protected]07f54fcc2009-12-22 02:46:30714 // Wrapper for glUseProgram
715 void DoUseProgram(GLuint program);
716
[email protected]96449d2c2009-11-25 00:01:32717 // Gets the GLError through our wrapper.
718 GLenum GetGLError();
719
720 // Sets our wrapper for the GLError.
721 void SetGLError(GLenum error);
722
[email protected]07f54fcc2009-12-22 02:46:30723 // Copies the real GL errors to the wrapper. This is so we can
724 // make sure there are no native GL errors before calling some GL function
725 // so that on return we know any error generated was for that specific
726 // command.
727 void CopyRealGLErrorsToWrapper();
728
[email protected]6217d392010-03-25 22:08:35729 // Clear all real GL errors. This is to prevent the client from seeing any
730 // errors caused by GL calls that it was not responsible for issuing.
731 void ClearRealGLErrors();
732
[email protected]07f54fcc2009-12-22 02:46:30733 // Checks if the current program and vertex attributes are valid for drawing.
734 bool IsDrawValid(GLuint max_vertex_accessed);
735
[email protected]3916c97e2010-02-25 03:20:50736 void SetBlackTextureForNonRenderableTextures(
737 bool* has_non_renderable_textures);
738 void RestoreStateForNonRenderableTextures();
739
[email protected]07f54fcc2009-12-22 02:46:30740 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:50741 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:30742 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:50743 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
744 bound_array_buffer_ : bound_element_array_buffer_;
745 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:30746 }
747
[email protected]a93bb842010-02-16 23:03:47748 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:50749 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
750 TextureUnit& unit = texture_units_[active_texture_unit_];
751 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:47752 switch (target) {
753 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:50754 info = unit.bound_texture_2d;
755 break;
[email protected]a93bb842010-02-16 23:03:47756 case GL_TEXTURE_CUBE_MAP:
757 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
758 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
759 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
760 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
761 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
762 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:50763 info = unit.bound_texture_cube_map;
764 break;
[email protected]1aef98132010-02-23 18:00:07765 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
766 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
767 // because |texture_| is used by the FBO rendering mechanism for readback
768 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:47769 default:
770 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:50771 return NULL;
[email protected]a93bb842010-02-16 23:03:47772 }
[email protected]3916c97e2010-02-25 03:20:50773 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47774 }
775
[email protected]f7b85372010-02-03 01:11:37776 // Validates the program and location for a glGetUniform call and returns
777 // a SizeResult setup to receive the result. Returns true if glGetUniform
778 // should be called.
779 bool GetUniformSetup(
780 GLuint program, GLint location,
781 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:25782 error::Error* error, GLuint* service_id, void** result);
[email protected]f7b85372010-02-03 01:11:37783
[email protected]86093972010-03-11 00:13:56784 bool ValidateGLenumCompressedTextureInternalFormat(GLenum format);
785
[email protected]96449d2c2009-11-25 00:01:32786 // Generate a member function prototype for each command in an automated and
787 // typesafe way.
788 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:14789 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:19790 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:32791 const gles2::name& args); \
792
793 GLES2_COMMAND_LIST(GLES2_CMD_OP)
794
795 #undef GLES2_CMD_OP
796
[email protected]d37231fa2010-04-09 21:16:02797 // The GL context this decoder renders to.
798 GLContext* context_;
799
[email protected]6217d392010-03-25 22:08:35800 // A parent decoder can access this decoders saved offscreen frame buffer.
801 // The parent pointer is reset if the parent is destroyed.
802 base::WeakPtr<GLES2DecoderImpl> parent_;
803
804 // Width and height to which an offscreen frame buffer should be resized on
805 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:02806 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:35807
[email protected]96449d2c2009-11-25 00:01:32808 // Current GL error bits.
809 uint32 error_bits_;
810
[email protected]96449d2c2009-11-25 00:01:32811 // Util to help with GL.
812 GLES2Util util_;
813
814 // pack alignment as last set by glPixelStorei
815 GLint pack_alignment_;
816
817 // unpack alignment as last set by glPixelStorei
818 GLint unpack_alignment_;
819
820 // The currently bound array buffer. If this is 0 it is illegal to call
821 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:50822 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:32823
824 // The currently bound element array buffer. If this is 0 it is illegal
825 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:50826 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:30827
828 // Info for each vertex attribute saved so we can check at glDrawXXX time
829 // if it is safe to draw.
830 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
831
[email protected]3916c97e2010-02-25 03:20:50832 // Current active texture by 0 - n index.
833 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
834 // be 2.
835 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:30836
[email protected]3916c97e2010-02-25 03:20:50837 // Which textures are bound to texture units through glActiveTexture.
838 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:47839
[email protected]3916c97e2010-02-25 03:20:50840 // Black (0,0,0,0) textures for when non-renderable textures are used.
841 // NOTE: There is no corresponding TextureInfo for these textures.
842 // TextureInfos are only for textures the client side can access.
843 GLuint black_2d_texture_id_;
844 GLuint black_cube_texture_id_;
[email protected]45bf5152010-02-12 00:11:31845
[email protected]1d32bc82010-01-13 22:06:46846 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:50847 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:30848
[email protected]86093972010-03-11 00:13:56849 // The currently bound framebuffer
[email protected]051b1372010-04-12 02:42:08850 FramebufferManager::FramebufferInfo::Ref bound_framebuffer_;
[email protected]86093972010-03-11 00:13:56851
852 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:08853 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:56854
[email protected]96449d2c2009-11-25 00:01:32855 bool anti_aliased_;
856
[email protected]6217d392010-03-25 22:08:35857 // The offscreen frame buffer that the client renders to.
858 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
859 scoped_ptr<Texture> offscreen_target_color_texture_;
860 scoped_ptr<RenderBuffer> offscreen_target_depth_stencil_render_buffer_;
861
862 // The copy that is saved when SwapBuffers is called.
863 scoped_ptr<Texture> offscreen_saved_color_texture_;
864
865 // A frame buffer used for rendering to render textures and render buffers
866 // without concern about any state the client might have changed on the frame
867 // buffers it has access to.
868 scoped_ptr<FrameBuffer> temporary_frame_buffer_;
869
[email protected]43f28f832010-02-03 02:28:48870 scoped_ptr<Callback0::Type> swap_buffers_callback_;
871
[email protected]96449d2c2009-11-25 00:01:32872 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
873};
874
[email protected]6217d392010-03-25 22:08:35875ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
876 : decoder_(decoder) {
877 decoder_->CopyRealGLErrorsToWrapper();
878}
879
880ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
881 decoder_->ClearRealGLErrors();
882}
883
884ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
885 GLuint id)
886 : decoder_(decoder) {
887 ScopedGLErrorSuppressor suppressor(decoder_);
888
889 // TODO(apatrick): Check if there are any other states that need to be reset
890 // before binding a new texture.
891 glActiveTexture(GL_TEXTURE0);
892 glBindTexture(GL_TEXTURE_2D, id);
893}
894
895ScopedTexture2DBinder::~ScopedTexture2DBinder() {
896 ScopedGLErrorSuppressor suppressor(decoder_);
897 GLES2DecoderImpl::TextureUnit& info = decoder_->texture_units_[0];
898 GLuint last_id;
899 if (info.bound_texture_2d)
900 last_id = info.bound_texture_2d->texture_id();
901 else
902 last_id = 0;
903
904 glBindTexture(GL_TEXTURE_2D, last_id);
905 glActiveTexture(GL_TEXTURE0 + decoder_->active_texture_unit_);
906}
907
908ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
909 GLuint id)
910 : decoder_(decoder) {
911 ScopedGLErrorSuppressor suppressor(decoder_);
912 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
913}
914
915ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
916 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:08917 glBindRenderbufferEXT(
918 GL_RENDERBUFFER,
919 decoder_->bound_renderbuffer_ ?
920 decoder_->bound_renderbuffer_->renderbuffer_id() : 0);
[email protected]6217d392010-03-25 22:08:35921}
922
923ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
924 GLuint id)
925 : decoder_(decoder) {
926 ScopedGLErrorSuppressor suppressor(decoder_);
927 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
928}
929
930ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
931 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:08932 FramebufferManager::FramebufferInfo* info =
933 decoder_->bound_framebuffer_.get();
934 GLuint framebuffer_id = info ? info->framebuffer_id() : 0;
935 if (framebuffer_id == 0 &&
[email protected]6217d392010-03-25 22:08:35936 decoder_->offscreen_target_frame_buffer_.get()) {
937 glBindFramebufferEXT(GL_FRAMEBUFFER,
938 decoder_->offscreen_target_frame_buffer_->id());
939 } else {
[email protected]051b1372010-04-12 02:42:08940 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_id);
[email protected]6217d392010-03-25 22:08:35941 }
942}
943
944Texture::Texture(GLES2DecoderImpl* decoder)
945 : decoder_(decoder),
946 id_(0) {
947}
948
949Texture::~Texture() {
950 // This does not destroy the render texture because that would require that
951 // the associated GL context was current. Just check that it was explicitly
952 // destroyed.
953 DCHECK_EQ(id_, 0u);
954}
955
956void Texture::Create() {
957 ScopedGLErrorSuppressor suppressor(decoder_);
958 Destroy();
959 glGenTextures(1, &id_);
960}
961
962bool Texture::AllocateStorage(const gfx::Size& size) {
963 DCHECK_NE(id_, 0u);
964 ScopedGLErrorSuppressor suppressor(decoder_);
965 ScopedTexture2DBinder binder(decoder_, id_);
966 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
967 glTexParameteri(
968 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
969 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
970 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
971 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
972
973 glTexImage2D(GL_TEXTURE_2D,
974 0, // mip level
975 GL_RGBA,
976 size.width(),
977 size.height(),
978 0, // border
979 GL_RGBA,
980 GL_UNSIGNED_BYTE,
981 NULL);
982
[email protected]d37231fa2010-04-09 21:16:02983 size_ = size;
984
[email protected]6217d392010-03-25 22:08:35985 return glGetError() == GL_NO_ERROR;
986}
987
988void Texture::Copy(const gfx::Size& size) {
989 DCHECK_NE(id_, 0u);
990 ScopedGLErrorSuppressor suppressor(decoder_);
991 ScopedTexture2DBinder binder(decoder_, id_);
992 glCopyTexImage2D(GL_TEXTURE_2D,
993 0, // level
994 GL_RGBA,
995 0, 0,
996 size.width(),
997 size.height(),
998 0); // border
999}
1000
1001void Texture::Destroy() {
1002 if (id_ != 0) {
1003 ScopedGLErrorSuppressor suppressor(decoder_);
1004 glDeleteTextures(1, &id_);
1005 id_ = 0;
1006 }
1007}
1008
1009RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1010 : decoder_(decoder),
1011 id_(0) {
1012}
1013
1014RenderBuffer::~RenderBuffer() {
1015 // This does not destroy the render buffer because that would require that
1016 // the associated GL context was current. Just check that it was explicitly
1017 // destroyed.
1018 DCHECK_EQ(id_, 0u);
1019}
1020
1021void RenderBuffer::Create() {
1022 ScopedGLErrorSuppressor suppressor(decoder_);
1023 Destroy();
1024 glGenRenderbuffersEXT(1, &id_);
1025}
1026
1027bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format) {
1028 ScopedGLErrorSuppressor suppressor(decoder_);
1029 ScopedRenderBufferBinder binder(decoder_, id_);
1030 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1031 format,
1032 size.width(),
1033 size.height());
1034 return glGetError() == GL_NO_ERROR;
1035}
1036
1037void RenderBuffer::Destroy() {
1038 if (id_ != 0) {
1039 ScopedGLErrorSuppressor suppressor(decoder_);
1040 glDeleteRenderbuffersEXT(1, &id_);
1041 id_ = 0;
1042 }
1043}
1044
1045FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1046 : decoder_(decoder),
1047 id_(0) {
1048}
1049
1050FrameBuffer::~FrameBuffer() {
1051 // This does not destroy the frame buffer because that would require that
1052 // the associated GL context was current. Just check that it was explicitly
1053 // destroyed.
1054 DCHECK_EQ(id_, 0u);
1055}
1056
1057void FrameBuffer::Create() {
1058 ScopedGLErrorSuppressor suppressor(decoder_);
1059 Destroy();
1060 glGenFramebuffersEXT(1, &id_);
1061}
1062
1063void FrameBuffer::AttachRenderTexture(Texture* texture) {
1064 DCHECK_NE(id_, 0u);
1065 ScopedGLErrorSuppressor suppressor(decoder_);
1066 ScopedFrameBufferBinder binder(decoder_, id_);
1067 GLuint attach_id = texture ? texture->id() : 0;
1068 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1069 GL_COLOR_ATTACHMENT0,
1070 GL_TEXTURE_2D,
1071 attach_id,
1072 0);
1073}
1074
1075void FrameBuffer::AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer) {
1076 DCHECK_NE(id_, 0u);
1077 ScopedGLErrorSuppressor suppressor(decoder_);
1078 ScopedFrameBufferBinder binder(decoder_, id_);
1079 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1080 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
1081 GL_DEPTH_ATTACHMENT,
1082 GL_RENDERBUFFER,
1083 attach_id);
1084 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
1085 GL_STENCIL_ATTACHMENT,
1086 GL_RENDERBUFFER,
1087 attach_id);
1088}
1089
1090void FrameBuffer::Clear(GLbitfield buffers) {
1091 ScopedGLErrorSuppressor suppressor(decoder_);
1092 ScopedFrameBufferBinder binder(decoder_, id_);
1093 glClear(buffers);
1094}
1095
1096void FrameBuffer::Destroy() {
1097 if (id_ != 0) {
1098 ScopedGLErrorSuppressor suppressor(decoder_);
1099 glDeleteFramebuffersEXT(1, &id_);
1100 id_ = 0;
1101 }
1102}
1103
1104GLenum FrameBuffer::CheckStatus() {
1105 DCHECK_NE(id_, 0u);
1106 ScopedGLErrorSuppressor suppressor(decoder_);
1107 ScopedFrameBufferBinder binder(decoder_, id_);
1108 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1109}
1110
[email protected]3916c97e2010-02-25 03:20:501111GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1112 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321113}
1114
[email protected]3916c97e2010-02-25 03:20:501115GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
1116 : GLES2Decoder(group),
[email protected]d37231fa2010-04-09 21:16:021117 context_(NULL),
[email protected]96449d2c2009-11-25 00:01:321118 error_bits_(0),
1119 util_(0), // TODO(gman): Set to actual num compress texture formats.
1120 pack_alignment_(4),
1121 unpack_alignment_(4),
[email protected]3916c97e2010-02-25 03:20:501122 active_texture_unit_(0),
1123 black_2d_texture_id_(0),
1124 black_cube_texture_id_(0),
[email protected]96449d2c2009-11-25 00:01:321125 anti_aliased_(false) {
1126}
1127
[email protected]d37231fa2010-04-09 21:16:021128bool GLES2DecoderImpl::Initialize(GLContext* context,
[email protected]6217d392010-03-25 22:08:351129 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:021130 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:351131 uint32 parent_client_texture_id) {
[email protected]d37231fa2010-04-09 21:16:021132 DCHECK(!context_);
1133 context_ = context;
1134
[email protected]6217d392010-03-25 22:08:351135 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021136 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351137 if (parent)
1138 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1139
[email protected]246a70452010-03-05 21:53:501140 if (!MakeCurrent()) {
1141 Destroy();
1142 return false;
[email protected]eb54a562010-01-20 21:55:181143 }
1144
[email protected]246a70452010-03-05 21:53:501145 CHECK_GL_ERROR();
1146
1147 if (!group_->Initialize()) {
1148 Destroy();
1149 return false;
1150 }
1151
1152 vertex_attrib_infos_.reset(
1153 new VertexAttribInfo[group_->max_vertex_attribs()]);
1154 texture_units_.reset(
1155 new TextureUnit[group_->max_texture_units()]);
1156 GLuint ids[2];
1157 glGenTextures(2, ids);
1158 // Make black textures for replacing non-renderable textures.
1159 black_2d_texture_id_ = ids[0];
1160 black_cube_texture_id_ = ids[1];
1161 static int8 black[] = {0, 0, 0, 0};
1162 glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
1163 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
1164 GL_UNSIGNED_BYTE, black);
1165 glBindTexture(GL_TEXTURE_2D, 0);
1166 glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
1167 static GLenum faces[] = {
1168 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
1169 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
1170 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
1171 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
1172 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
1173 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
1174 };
1175 for (size_t ii = 0; ii < arraysize(faces); ++ii) {
1176 glTexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA,
1177 GL_UNSIGNED_BYTE, black);
1178 }
1179 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
1180 CHECK_GL_ERROR();
1181
[email protected]d37231fa2010-04-09 21:16:021182#if !defined(UNIT_TEST)
1183 if (context_->IsOffscreen()) {
[email protected]6217d392010-03-25 22:08:351184 // Create the target frame buffer. This is the one that the client renders
1185 // directly to.
1186 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1187 offscreen_target_frame_buffer_->Create();
1188 offscreen_target_color_texture_.reset(new Texture(this));
1189 offscreen_target_color_texture_->Create();
1190 offscreen_target_depth_stencil_render_buffer_.reset(
1191 new RenderBuffer(this));
1192 offscreen_target_depth_stencil_render_buffer_->Create();
1193
1194 // Create the saved offscreen texture. The target frame buffer is copied
1195 // here when SwapBuffers is called.
1196 offscreen_saved_color_texture_.reset(new Texture(this));
1197 offscreen_saved_color_texture_->Create();
1198
1199 // Create the temporary frame buffer, used to operate on render textures
1200 // without concern for state the client might have changed on the frame
1201 // buffers it has access to, like the clear color and the color mask.
1202 temporary_frame_buffer_.reset(new FrameBuffer(this));
1203 temporary_frame_buffer_->Create();
1204
1205 // Map the ID of the saved offscreen texture into the parent so that
1206 // it can reference it.
1207 if (parent_) {
1208 GLuint service_id = offscreen_saved_color_texture_->id();
1209 parent_->id_manager()->AddMapping(parent_client_texture_id,
1210 service_id);
1211 TextureManager::TextureInfo* info =
1212 parent_->CreateTextureInfo(service_id);
1213 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
1214 }
1215
1216 // Allocate the render buffers at their initial size and check the status
1217 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021218 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351219 if (!UpdateOffscreenFrameBufferSize()) {
1220 DLOG(ERROR) << "Could not allocate offscreen buffer storage.";
1221 Destroy();
1222 return false;
1223 }
1224
1225 // Bind to the new default frame buffer (the offscreen target frame buffer).
1226 // This should now be associated with ID zero.
1227 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
1228 }
[email protected]d37231fa2010-04-09 21:16:021229#endif // UNIT_TEST
[email protected]6217d392010-03-25 22:08:351230
[email protected]76a0ee102010-04-07 21:03:041231#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1232 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1233 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1234 // isn't well documented; it was discovered in the Khronos OpenGL ES
1235 // mailing list archives.
1236 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
1237#endif
1238
[email protected]246a70452010-03-05 21:53:501239 return true;
[email protected]96449d2c2009-11-25 00:01:321240}
1241
[email protected]07f54fcc2009-12-22 02:46:301242// These commands convert from c calls to local os calls.
1243void GLGenBuffersHelper(
[email protected]a93bb842010-02-16 23:03:471244 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301245 glGenBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:471246 // TODO(gman): handle error
1247 for (GLsizei ii = 0; ii < n; ++ii) {
1248 decoder->CreateBufferInfo(ids[ii]);
1249 }
[email protected]07f54fcc2009-12-22 02:46:301250}
1251
1252void GLGenFramebuffersHelper(
[email protected]a25fa872010-03-25 02:57:581253 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301254 glGenFramebuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:581255 // TODO(gman): handle error
1256 for (GLsizei ii = 0; ii < n; ++ii) {
1257 decoder->CreateFramebufferInfo(ids[ii]);
1258 }
[email protected]07f54fcc2009-12-22 02:46:301259}
1260
1261void GLGenRenderbuffersHelper(
[email protected]a25fa872010-03-25 02:57:581262 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301263 glGenRenderbuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:581264 // TODO(gman): handle error
1265 for (GLsizei ii = 0; ii < n; ++ii) {
1266 decoder->CreateRenderbufferInfo(ids[ii]);
1267 }
[email protected]07f54fcc2009-12-22 02:46:301268}
1269
1270void GLGenTexturesHelper(
[email protected]a93bb842010-02-16 23:03:471271 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301272 glGenTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:471273 // TODO(gman): handle error
1274 for (GLsizei ii = 0; ii < n; ++ii) {
1275 decoder->CreateTextureInfo(ids[ii]);
1276 }
[email protected]07f54fcc2009-12-22 02:46:301277}
1278
1279void GLDeleteBuffersHelper(
1280 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
1281 glDeleteBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:471282 // TODO(gman): handle error
[email protected]07f54fcc2009-12-22 02:46:301283 for (GLsizei ii = 0; ii < n; ++ii) {
1284 decoder->RemoveBufferInfo(ids[ii]);
1285 }
1286}
1287
1288void GLDeleteFramebuffersHelper(
[email protected]a25fa872010-03-25 02:57:581289 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301290 glDeleteFramebuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:581291 // TODO(gman): handle error
1292 for (GLsizei ii = 0; ii < n; ++ii) {
1293 decoder->RemoveFramebufferInfo(ids[ii]);
1294 }
[email protected]07f54fcc2009-12-22 02:46:301295}
1296
1297void GLDeleteRenderbuffersHelper(
[email protected]a25fa872010-03-25 02:57:581298 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301299 glDeleteRenderbuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:581300 // TODO(gman): handle error
1301 for (GLsizei ii = 0; ii < n; ++ii) {
1302 decoder->RemoveRenderbufferInfo(ids[ii]);
1303 }
[email protected]07f54fcc2009-12-22 02:46:301304}
1305
1306void GLDeleteTexturesHelper(
[email protected]a93bb842010-02-16 23:03:471307 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301308 glDeleteTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:471309 // TODO(gman): handle error
1310 for (GLsizei ii = 0; ii < n; ++ii) {
1311 decoder->RemoveTextureInfo(ids[ii]);
1312 }
[email protected]07f54fcc2009-12-22 02:46:301313}
1314
[email protected]43f28f832010-02-03 02:28:481315// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:321316
[email protected]eb54a562010-01-20 21:55:181317bool GLES2DecoderImpl::MakeCurrent() {
1318#if defined(UNIT_TEST)
1319 return true;
[email protected]eb54a562010-01-20 21:55:181320#else
[email protected]d37231fa2010-04-09 21:16:021321 return context_->MakeCurrent();
[email protected]eb54a562010-01-20 21:55:181322#endif
1323}
1324
[email protected]8a837bb2010-01-05 00:21:241325uint32 GLES2DecoderImpl::GetServiceIdForTesting(uint32 client_id) {
1326#if defined(UNIT_TEST)
1327 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501328 bool result = id_manager()->GetServiceId(client_id, &service_id);
[email protected]8a837bb2010-01-05 00:21:241329 return result ? service_id : 0u;
1330#else
1331 DCHECK(false);
1332 return 0u;
1333#endif
1334}
1335
1336bool GLES2DecoderImpl::ValidateIdsAreUnused(
1337 GLsizei n, const GLuint* client_ids) {
1338 for (GLsizei ii = 0; ii < n; ++ii) {
1339 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501340 if (id_manager()->GetServiceId(client_ids[ii], &service_id)) {
[email protected]8a837bb2010-01-05 00:21:241341 return false;
1342 }
1343 }
1344 return true;
1345}
1346
[email protected]07f54fcc2009-12-22 02:46:301347bool GLES2DecoderImpl::RegisterObjects(
1348 GLsizei n, const GLuint* client_ids, const GLuint* service_ids) {
1349 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501350 if (!id_manager()->AddMapping(client_ids[ii], service_ids[ii])) {
[email protected]8a837bb2010-01-05 00:21:241351 NOTREACHED();
1352 return false;
[email protected]07f54fcc2009-12-22 02:46:301353 }
1354 }
1355 return true;
1356}
1357
1358void GLES2DecoderImpl::UnregisterObjects(
1359 GLsizei n, const GLuint* client_ids, GLuint* service_ids) {
[email protected]07f54fcc2009-12-22 02:46:301360 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501361 if (id_manager()->GetServiceId(client_ids[ii], &service_ids[ii])) {
1362 id_manager()->RemoveMapping(client_ids[ii], service_ids[ii]);
[email protected]07f54fcc2009-12-22 02:46:301363 } else {
1364 service_ids[ii] = 0;
1365 }
1366 }
1367}
1368
[email protected]d37231fa2010-04-09 21:16:021369gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() {
1370 if (bound_framebuffer_ != 0) {
1371 int width = 0;
1372 int height = 0;
[email protected]246a70452010-03-05 21:53:501373
[email protected]d37231fa2010-04-09 21:16:021374 // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
1375 // stencil.
1376 GLint fb_type = 0;
1377 glGetFramebufferAttachmentParameterivEXT(
1378 GL_FRAMEBUFFER,
1379 GL_COLOR_ATTACHMENT0,
1380 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
1381 &fb_type);
1382 switch (fb_type) {
1383 case GL_RENDERBUFFER:
1384 {
1385 GLint renderbuffer_id = 0;
1386 glGetFramebufferAttachmentParameterivEXT(
1387 GL_FRAMEBUFFER,
1388 GL_COLOR_ATTACHMENT0,
1389 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1390 &renderbuffer_id);
1391 if (renderbuffer_id != 0) {
1392 glGetRenderbufferParameterivEXT(
1393 GL_RENDERBUFFER,
1394 GL_RENDERBUFFER_WIDTH,
1395 &width);
1396 glGetRenderbufferParameterivEXT(
1397 GL_RENDERBUFFER,
1398 GL_RENDERBUFFER_HEIGHT,
1399 &height);
1400 }
1401 break;
1402 }
1403 case GL_TEXTURE:
1404 {
1405 GLint texture_id = 0;
1406 glGetFramebufferAttachmentParameterivEXT(
1407 GL_FRAMEBUFFER,
1408 GL_COLOR_ATTACHMENT0,
1409 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1410 &texture_id);
1411 if (texture_id != 0) {
1412 TextureManager::TextureInfo* texture_info =
1413 GetTextureInfo(texture_id);
1414 if (texture_info) {
1415 GLint level = 0;
1416 GLint face = 0;
1417 glGetFramebufferAttachmentParameterivEXT(
1418 GL_FRAMEBUFFER,
1419 GL_COLOR_ATTACHMENT0,
1420 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
1421 &level);
1422 glGetFramebufferAttachmentParameterivEXT(
1423 GL_FRAMEBUFFER,
1424 GL_COLOR_ATTACHMENT0,
1425 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
1426 &face);
1427 texture_info->GetLevelSize(
1428 face ? face : GL_TEXTURE_2D, level, &width, &height);
1429 }
1430 }
1431 break;
1432 }
1433 default:
1434 // unknown so assume width and height are zero.
1435 break;
[email protected]246a70452010-03-05 21:53:501436 }
1437
[email protected]d37231fa2010-04-09 21:16:021438 return gfx::Size(width, height);
1439 } else if (offscreen_target_color_texture_.get()) {
1440 return offscreen_target_color_texture_->size();
[email protected]6217d392010-03-25 22:08:351441 } else {
[email protected]246a70452010-03-05 21:53:501442#if defined(UNIT_TEST)
[email protected]d37231fa2010-04-09 21:16:021443 return gfx::Size(INT_MAX, INT_MAX);
1444#else
1445 return context_->GetSize();
[email protected]246a70452010-03-05 21:53:501446#endif
[email protected]d37231fa2010-04-09 21:16:021447 }
[email protected]246a70452010-03-05 21:53:501448}
1449
[email protected]6217d392010-03-25 22:08:351450bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]d37231fa2010-04-09 21:16:021451 if (offscreen_target_color_texture_->size() == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:351452 return true;
1453
1454 // Reallocate the offscreen target buffers.
[email protected]d37231fa2010-04-09 21:16:021455 if (!offscreen_target_color_texture_->AllocateStorage(
1456 pending_offscreen_size_)) {
[email protected]6217d392010-03-25 22:08:351457 return false;
1458 }
1459
1460 if (!offscreen_target_depth_stencil_render_buffer_->AllocateStorage(
[email protected]d37231fa2010-04-09 21:16:021461 pending_offscreen_size_, GL_DEPTH24_STENCIL8)) {
[email protected]6217d392010-03-25 22:08:351462 return false;
1463 }
1464
1465 // Attach the offscreen target buffers to the temporary frame buffer
1466 // so they can be cleared using that frame buffer's clear parameters (all
1467 // zero, no color mask, etc).
1468 temporary_frame_buffer_->AttachRenderTexture(
1469 offscreen_target_color_texture_.get());
1470 temporary_frame_buffer_->AttachDepthStencilRenderBuffer(
1471 offscreen_target_depth_stencil_render_buffer_.get());
1472 if (temporary_frame_buffer_->CheckStatus() !=
1473 GL_FRAMEBUFFER_COMPLETE) {
1474 return false;
1475 }
1476
1477 // Clear the offscreen target buffers to all zero (using the saved frame
1478 // buffer they are temporarily attached to).
1479 temporary_frame_buffer_->Clear(
1480 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1481
1482 // Detach the offscreen target buffer.
1483 temporary_frame_buffer_->AttachRenderTexture(NULL);
1484 temporary_frame_buffer_->AttachDepthStencilRenderBuffer(NULL);
1485
1486 // Attach the offscreen target buffers to the proper frame buffer.
1487 offscreen_target_frame_buffer_->AttachRenderTexture(
1488 offscreen_target_color_texture_.get());
1489 offscreen_target_frame_buffer_->AttachDepthStencilRenderBuffer(
1490 offscreen_target_depth_stencil_render_buffer_.get());
1491 if (offscreen_target_frame_buffer_->CheckStatus() !=
1492 GL_FRAMEBUFFER_COMPLETE) {
1493 return false;
1494 }
1495
[email protected]6217d392010-03-25 22:08:351496 // Update the info about the offscreen saved color texture in the parent.
1497 // The reference to the parent is a weak pointer and will become null if the
1498 // parent is later destroyed.
1499 if (parent_) {
[email protected]d37231fa2010-04-09 21:16:021500 // Create the saved offscreen color texture (only accessible to parent).
1501 offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
1502
1503 // Clear the offscreen saved color texture by copying the cleared target
1504 // frame buffer into it.
1505 {
1506 ScopedFrameBufferBinder binder(this,
1507 offscreen_target_frame_buffer_->id());
1508 offscreen_saved_color_texture_->Copy(pending_offscreen_size_);
1509 }
1510
[email protected]6217d392010-03-25 22:08:351511 GLuint service_id = offscreen_saved_color_texture_->id();
1512
1513 TextureManager::TextureInfo* info =
1514 parent_->texture_manager()->GetTextureInfo(service_id);
1515 DCHECK(info);
1516
1517 info->SetLevelInfo(GL_TEXTURE_2D,
1518 0, // level
1519 GL_RGBA,
[email protected]d37231fa2010-04-09 21:16:021520 pending_offscreen_size_.width(),
1521 pending_offscreen_size_.height(),
[email protected]6217d392010-03-25 22:08:351522 1, // depth
1523 0, // border
1524 GL_RGBA,
1525 GL_UNSIGNED_BYTE);
1526 }
1527
[email protected]6217d392010-03-25 22:08:351528 return true;
1529}
1530
[email protected]43f28f832010-02-03 02:28:481531void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
1532 swap_buffers_callback_.reset(callback);
1533}
1534
[email protected]96449d2c2009-11-25 00:01:321535void GLES2DecoderImpl::Destroy() {
[email protected]6217d392010-03-25 22:08:351536 MakeCurrent();
1537
1538 // Remove the saved frame buffer mapping from the parent decoder. The
1539 // parent pointer is a weak pointer so it will be null if the parent has
1540 // already been destroyed.
1541 if (parent_) {
1542 // First check the texture has been mapped into the parent. This might not
1543 // be the case if initialization failed midway through.
1544 GLuint service_id = offscreen_saved_color_texture_->id();
1545 GLuint client_id;
1546 if (parent_->id_manager()->GetClientId(service_id, &client_id)) {
1547 parent_->texture_manager()->RemoveTextureInfo(service_id);
1548 parent_->id_manager()->RemoveMapping(client_id, service_id);
1549 }
1550 }
1551
[email protected]d37231fa2010-04-09 21:16:021552 if (offscreen_target_frame_buffer_.get()) {
[email protected]6217d392010-03-25 22:08:351553 offscreen_target_frame_buffer_->Destroy();
[email protected]d37231fa2010-04-09 21:16:021554 offscreen_target_frame_buffer_.reset();
1555 }
[email protected]6217d392010-03-25 22:08:351556
[email protected]d37231fa2010-04-09 21:16:021557 if (offscreen_target_color_texture_.get()) {
[email protected]6217d392010-03-25 22:08:351558 offscreen_target_color_texture_->Destroy();
[email protected]d37231fa2010-04-09 21:16:021559 offscreen_target_color_texture_.reset();
1560 }
[email protected]6217d392010-03-25 22:08:351561
[email protected]d37231fa2010-04-09 21:16:021562 if (offscreen_target_depth_stencil_render_buffer_.get()) {
[email protected]6217d392010-03-25 22:08:351563 offscreen_target_depth_stencil_render_buffer_->Destroy();
[email protected]d37231fa2010-04-09 21:16:021564 offscreen_target_depth_stencil_render_buffer_.reset();
1565 }
[email protected]6217d392010-03-25 22:08:351566
[email protected]d37231fa2010-04-09 21:16:021567 if (temporary_frame_buffer_.get()) {
[email protected]6217d392010-03-25 22:08:351568 temporary_frame_buffer_->Destroy();
[email protected]d37231fa2010-04-09 21:16:021569 temporary_frame_buffer_.reset();
1570 }
[email protected]6217d392010-03-25 22:08:351571
[email protected]d37231fa2010-04-09 21:16:021572 if (offscreen_saved_color_texture_.get()) {
[email protected]6217d392010-03-25 22:08:351573 offscreen_saved_color_texture_->Destroy();
[email protected]d37231fa2010-04-09 21:16:021574 offscreen_saved_color_texture_.reset();
1575 }
[email protected]96449d2c2009-11-25 00:01:321576}
1577
[email protected]6217d392010-03-25 22:08:351578void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
1579 // We can't resize the render buffers immediately because there might be a
1580 // partial frame rendered into them and we don't want the tail end of that
1581 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021582 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351583}
1584
[email protected]96449d2c2009-11-25 00:01:321585const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
1586 if (command_id > kStartPoint && command_id < kNumCommands) {
1587 return gles2::GetCommandName(static_cast<CommandId>(command_id));
1588 }
1589 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
1590}
1591
1592// Decode command with its arguments, and call the corresponding GL function.
1593// Note: args is a pointer to the command buffer. As such, it could be changed
1594// by a (malicious) client at any time, so if validation has to happen, it
1595// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:141596error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:321597 unsigned int command,
1598 unsigned int arg_count,
1599 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:141600 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191601 if (debug()) {
1602 // TODO(gman): Change output to something useful for NaCl.
[email protected]b9849abf2009-11-25 19:13:191603 printf("cmd: %s\n", GetCommandName(command));
1604 }
[email protected]96449d2c2009-11-25 00:01:321605 unsigned int command_index = command - kStartPoint - 1;
1606 if (command_index < arraysize(g_command_info)) {
1607 const CommandInfo& info = g_command_info[command_index];
1608 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
1609 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
1610 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:191611 uint32 immediate_data_size =
1612 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:321613 switch (command) {
1614 #define GLES2_CMD_OP(name) \
1615 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:191616 result = Handle ## name( \
1617 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321618 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:191619 break; \
[email protected]96449d2c2009-11-25 00:01:321620
1621 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:321622 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:381623 }
1624 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:301625 GLenum error;
1626 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:381627 // TODO(gman): Change output to something useful for NaCl.
[email protected]07f54fcc2009-12-22 02:46:301628 SetGLError(error);
[email protected]bf0985e2009-12-17 03:04:381629 printf("GL ERROR b4: %s\n", GetCommandName(command));
[email protected]b9849abf2009-11-25 19:13:191630 }
[email protected]96449d2c2009-11-25 00:01:321631 }
1632 } else {
[email protected]f7a64ee2010-02-01 22:24:141633 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:321634 }
[email protected]b9849abf2009-11-25 19:13:191635 } else {
1636 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:321637 }
[email protected]b9849abf2009-11-25 19:13:191638 return result;
[email protected]96449d2c2009-11-25 00:01:321639}
1640
[email protected]3916c97e2010-02-25 03:20:501641void GLES2DecoderImpl::RemoveBufferInfo(GLuint buffer_id) {
1642 buffer_manager()->RemoveBufferInfo(buffer_id);
1643 // TODO(gman): See if we can remove the rest of this function as
1644 // buffers are now reference counted and have a "IsDeleted" function.
1645 if (bound_array_buffer_ && bound_array_buffer_->buffer_id() == buffer_id) {
1646 bound_array_buffer_ = NULL;
1647 }
1648 if (bound_element_array_buffer_ &&
1649 bound_element_array_buffer_->buffer_id() == buffer_id) {
1650 bound_element_array_buffer_ = NULL;
1651 }
1652
1653 // go through VertexAttribInfo and update any info that references the buffer.
1654 for (GLuint ii = 0; ii < group_->max_vertex_attribs(); ++ii) {
1655 VertexAttribInfo& info = vertex_attrib_infos_[ii];
1656 if (info.buffer() && info.buffer()->buffer_id() == buffer_id) {
1657 info.ClearBuffer();
1658 }
1659 }
1660}
1661
[email protected]96449d2c2009-11-25 00:01:321662void GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
1663 // TODO(gman): verify client_id is unused.
1664 GLuint service_id = glCreateProgram();
1665 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501666 id_manager()->AddMapping(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:471667 CreateProgramInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321668 }
1669}
1670
1671void GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
1672 // TODO(gman): verify client_id is unused.
1673 GLuint service_id = glCreateShader(type);
1674 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501675 id_manager()->AddMapping(client_id, service_id);
[email protected]45bf5152010-02-12 00:11:311676 CreateShaderInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321677 }
1678}
1679
[email protected]86093972010-03-11 00:13:561680bool GLES2DecoderImpl::ValidateGLenumCompressedTextureInternalFormat(GLenum) {
1681 // TODO(gman): Add support for compressed texture formats.
1682 return false;
1683}
1684
[email protected]3916c97e2010-02-25 03:20:501685void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:451686 GLuint texture_index = texture_unit - GL_TEXTURE0;
1687 if (texture_index > group_->max_texture_units()) {
[email protected]3916c97e2010-02-25 03:20:501688 SetGLError(GL_INVALID_ENUM);
1689 return;
1690 }
[email protected]36cef8ce2010-03-16 07:34:451691 active_texture_unit_ = texture_index;
1692 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:501693}
1694
[email protected]051b1372010-04-12 02:42:081695void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:501696 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:081697 GLuint service_id = 0;
1698 if (client_id != 0 && !id_manager()->GetServiceId(client_id, &service_id)) {
1699 // It's a new id so make a buffer info for it.
1700 glGenBuffersARB(1, &service_id);
1701 RegisterObjects(1, &client_id, &service_id);
1702 CreateBufferInfo(service_id);
1703 }
1704 if (service_id) {
1705 info = GetBufferInfo(service_id);
[email protected]0c86dbf2010-03-05 08:14:111706 // Check the buffer exists
1707 // Check that we are not trying to bind it to a different target.
1708 if (!info || (info->target() != 0 && info->target() != target)) {
[email protected]a93bb842010-02-16 23:03:471709 SetGLError(GL_INVALID_OPERATION);
1710 return;
1711 }
[email protected]0c86dbf2010-03-05 08:14:111712 if (info->target() == 0) {
1713 info->set_target(target);
1714 }
[email protected]a93bb842010-02-16 23:03:471715 }
[email protected]96449d2c2009-11-25 00:01:321716 switch (target) {
1717 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501718 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321719 break;
1720 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501721 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321722 break;
1723 default:
[email protected]a93bb842010-02-16 23:03:471724 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:321725 break;
1726 }
[email protected]051b1372010-04-12 02:42:081727 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:321728}
1729
[email protected]051b1372010-04-12 02:42:081730void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
1731 FramebufferManager::FramebufferInfo* info = NULL;
1732 GLuint service_id = 0;
1733 if (client_id != 0 && !id_manager()->GetServiceId(client_id, &service_id)) {
1734 // It's a new id so make a framebuffer info for it.
1735 glGenFramebuffersEXT(1, &service_id);
1736 RegisterObjects(1, &client_id, &service_id);
1737 CreateFramebufferInfo(service_id);
1738 }
1739 if (service_id) {
1740 info = GetFramebufferInfo(service_id);
1741 // Check the framebuffer exists
1742 if (!info) {
1743 SetGLError(GL_INVALID_OPERATION);
1744 return;
1745 }
1746 }
1747 bound_framebuffer_ = info;
[email protected]6217d392010-03-25 22:08:351748
1749 // When rendering to an offscreen frame buffer, instead of unbinding from
1750 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:081751 if (info == NULL && offscreen_target_frame_buffer_.get())
1752 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:351753
[email protected]051b1372010-04-12 02:42:081754 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:561755}
1756
[email protected]051b1372010-04-12 02:42:081757void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
1758 RenderbufferManager::RenderbufferInfo* info = NULL;
1759 GLuint service_id = 0;
1760 if (client_id != 0 && !id_manager()->GetServiceId(client_id, &service_id)) {
1761 // It's a new id so make a renderbuffer info for it.
1762 glGenRenderbuffersEXT(1, &service_id);
1763 RegisterObjects(1, &client_id, &service_id);
1764 CreateRenderbufferInfo(service_id);
1765 }
1766 if (service_id) {
1767 info = GetRenderbufferInfo(service_id);
1768 // Check the renderbuffer exists
1769 if (!info) {
1770 SetGLError(GL_INVALID_OPERATION);
1771 return;
1772 }
1773 }
1774 bound_renderbuffer_ = info;
1775 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:561776}
1777
[email protected]051b1372010-04-12 02:42:081778void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:501779 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:081780 GLuint service_id = 0;
1781 if (client_id != 0 && !id_manager()->GetServiceId(client_id, &service_id)) {
1782 // It's a new id so make a texture info for it.
1783 glGenTextures(1, &service_id);
1784 RegisterObjects(1, &client_id, &service_id);
1785 CreateTextureInfo(service_id);
1786 }
1787 if (service_id) {
1788 info = GetTextureInfo(service_id);
[email protected]3916c97e2010-02-25 03:20:501789 // Check the texture exists
1790 // Check that we are not trying to bind it to a different target.
[email protected]a93bb842010-02-16 23:03:471791 if (!info || (info->target() != 0 && info->target() != target)) {
1792 SetGLError(GL_INVALID_OPERATION);
1793 return;
1794 }
1795 if (info->target() == 0) {
[email protected]3916c97e2010-02-25 03:20:501796 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:471797 }
1798 }
[email protected]051b1372010-04-12 02:42:081799 glBindTexture(target, service_id);
[email protected]3916c97e2010-02-25 03:20:501800 TextureUnit& unit = texture_units_[active_texture_unit_];
1801 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:471802 switch (target) {
1803 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501804 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:471805 break;
1806 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:501807 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:471808 break;
1809 default:
1810 NOTREACHED(); // Validation should prevent us getting here.
1811 break;
1812 }
1813}
1814
[email protected]07f54fcc2009-12-22 02:46:301815void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501816 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301817 vertex_attrib_infos_[index].set_enabled(false);
[email protected]8a837bb2010-01-05 00:21:241818 glDisableVertexAttribArray(index);
[email protected]07f54fcc2009-12-22 02:46:301819 } else {
1820 SetGLError(GL_INVALID_VALUE);
1821 }
1822}
1823
1824void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501825 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301826 vertex_attrib_infos_[index].set_enabled(true);
1827 glEnableVertexAttribArray(index);
1828 } else {
1829 SetGLError(GL_INVALID_VALUE);
1830 }
1831}
1832
[email protected]a93bb842010-02-16 23:03:471833void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:501834 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1835 if (!info || !info->MarkMipmapsGenerated()) {
[email protected]a93bb842010-02-16 23:03:471836 SetGLError(GL_INVALID_OPERATION);
1837 return;
1838 }
1839 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:471840}
1841
[email protected]b273e432010-04-12 17:23:581842bool GLES2DecoderImpl::GetHelper(
1843 GLenum pname, GLint* params, GLsizei* num_written) {
1844 DCHECK(params);
1845 DCHECK(num_written);
1846 switch (pname) {
1847 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1848 *num_written = 1;
1849 *params = GL_RGB; // TODO(gman): get correct format.
1850 return true;
1851 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1852 *num_written = 1;
1853 *params = GL_UNSIGNED_BYTE; // TODO(gman): get correct type.
1854 return true;
1855 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1856 *num_written = 1;
1857 *params = 16; // TODO(gman): get correct value.
1858 return true;
1859 case GL_MAX_VARYING_VECTORS:
1860 *num_written = 1;
1861 *params = 8; // TODO(gman): get correct value.
1862 return true;
1863 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1864 *num_written = 1;
1865 *params = 128; // TODO(gman): get correct value.
1866 return true;
1867 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1868 *num_written = 1;
1869 *params = 0; // We don't support compressed textures.
1870 return true;
1871 case GL_NUM_SHADER_BINARY_FORMATS:
1872 *num_written = 1;
1873 *params = 0; // We don't support binary shader formats.
1874 return true;
1875 case GL_SHADER_BINARY_FORMATS:
1876 *num_written = 0;
1877 return true; // We don't support binary shader format.s
1878 case GL_SHADER_COMPILER:
1879 *num_written = 1;
1880 *params = GL_TRUE;
1881 return true;
1882 default:
1883 return false;
1884 }
1885}
1886
1887void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
1888 DCHECK(params);
1889 GLint values[16];
1890 GLsizei num_written;
1891 if (GetHelper(pname, &values[0], &num_written)) {
1892 DCHECK_LE(static_cast<size_t>(num_written), arraysize(values));
1893 for (GLsizei ii = 0; ii < num_written; ++ii) {
1894 params[ii] = static_cast<GLboolean>(values[ii]);
1895 }
1896 } else {
1897 glGetBooleanv(pname, params);
1898 }
1899}
1900
1901void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
1902 DCHECK(params);
1903 GLint values[16];
1904 GLsizei num_written;
1905 if (GetHelper(pname, &values[0], &num_written)) {
1906 DCHECK_LE(static_cast<size_t>(num_written), arraysize(values));
1907 for (GLsizei ii = 0; ii < num_written; ++ii) {
1908 params[ii] = static_cast<GLfloat>(values[ii]);
1909 }
1910 } else {
1911 glGetFloatv(pname, params);
1912 }
1913}
1914
1915void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
1916 DCHECK(params);
1917 GLsizei num_written;
1918 if (!GetHelper(pname, params, &num_written)) {
1919 glGetIntegerv(pname, params);
1920 }
1921}
1922
[email protected]558847a2010-03-24 07:02:541923error::Error GLES2DecoderImpl::HandleBindAttribLocation(
1924 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
1925 GLuint program;
1926 if (!id_manager()->GetServiceId(c.program, &program)) {
1927 SetGLError(GL_INVALID_VALUE);
1928 return error::kNoError;
1929 }
1930 GLuint index = static_cast<GLuint>(c.index);
1931 uint32 name_size = c.data_size;
1932 const char* name = GetSharedMemoryAs<const char*>(
1933 c.name_shm_id, c.name_shm_offset, name_size);
1934 if (name == NULL) {
1935 return error::kOutOfBounds;
1936 }
1937 String name_str(name, name_size);
1938 glBindAttribLocation(program, index, name_str.c_str());
1939 return error::kNoError;
1940}
1941
1942error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
1943 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
1944 GLuint program;
1945 if (!id_manager()->GetServiceId(c.program, &program)) {
1946 SetGLError(GL_INVALID_VALUE);
1947 return error::kNoError;
1948 }
1949 GLuint index = static_cast<GLuint>(c.index);
1950 uint32 name_size = c.data_size;
1951 const char* name = GetImmediateDataAs<const char*>(
1952 c, name_size, immediate_data_size);
1953 if (name == NULL) {
1954 return error::kOutOfBounds;
1955 }
1956 String name_str(name, name_size);
1957 glBindAttribLocation(program, index, name_str.c_str());
1958 return error::kNoError;
1959}
1960
1961error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
1962 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
1963 GLuint program;
1964 if (!id_manager()->GetServiceId(c.program, &program)) {
1965 SetGLError(GL_INVALID_VALUE);
1966 return error::kNoError;
1967 }
1968 GLuint index = static_cast<GLuint>(c.index);
1969 Bucket* bucket = GetBucket(c.name_bucket_id);
1970 if (!bucket || bucket->size() == 0) {
1971 return error::kInvalidArguments;
1972 }
1973 std::string name_str;
1974 bucket->GetAsString(&name_str);
1975 glBindAttribLocation(program, index, name_str.c_str());
1976 return error::kNoError;
1977}
1978
[email protected]f7a64ee2010-02-01 22:24:141979error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:461980 uint32 immediate_data_size, const gles2::DeleteShader& c) {
1981 GLuint shader = c.shader;
[email protected]96449d2c2009-11-25 00:01:321982 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501983 if (!id_manager()->GetServiceId(shader, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:461984 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141985 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321986 }
[email protected]45bf5152010-02-12 00:11:311987 RemoveShaderInfo(service_id);
[email protected]07f54fcc2009-12-22 02:46:301988 glDeleteShader(service_id);
[email protected]3916c97e2010-02-25 03:20:501989 id_manager()->RemoveMapping(shader, service_id);
[email protected]f7a64ee2010-02-01 22:24:141990 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321991}
1992
[email protected]f7a64ee2010-02-01 22:24:141993error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:461994 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
1995 GLuint program = c.program;
[email protected]96449d2c2009-11-25 00:01:321996 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501997 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:461998 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141999 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322000 }
[email protected]1d32bc82010-01-13 22:06:462001 RemoveProgramInfo(service_id);
[email protected]ba3176a2009-12-16 18:19:462002 glDeleteProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:502003 id_manager()->RemoveMapping(program, service_id);
[email protected]f7a64ee2010-02-01 22:24:142004 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322005}
2006
[email protected]07f54fcc2009-12-22 02:46:302007void GLES2DecoderImpl::DoDrawArrays(
2008 GLenum mode, GLint first, GLsizei count) {
2009 if (IsDrawValid(first + count - 1)) {
[email protected]3916c97e2010-02-25 03:20:502010 bool has_non_renderable_textures;
2011 SetBlackTextureForNonRenderableTextures(&has_non_renderable_textures);
[email protected]07f54fcc2009-12-22 02:46:302012 glDrawArrays(mode, first, count);
[email protected]3916c97e2010-02-25 03:20:502013 if (has_non_renderable_textures) {
2014 RestoreStateForNonRenderableTextures();
2015 }
[email protected]07f54fcc2009-12-22 02:46:302016 }
2017}
2018
[email protected]36cef8ce2010-03-16 07:34:452019void GLES2DecoderImpl::DoFramebufferRenderbuffer(
2020 GLenum target, GLenum attachment, GLenum renderbuffertarget,
2021 GLuint renderbuffer) {
[email protected]051b1372010-04-12 02:42:082022 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452023 SetGLError(GL_INVALID_OPERATION);
2024 return;
2025 }
2026 glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget,
2027 renderbuffer);
2028}
2029
2030GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]051b1372010-04-12 02:42:082031 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452032 return GL_FRAMEBUFFER_COMPLETE;
2033 }
2034 return glCheckFramebufferStatusEXT(target);
2035}
2036
2037void GLES2DecoderImpl::DoFramebufferTexture2D(
2038 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
2039 GLint level) {
[email protected]051b1372010-04-12 02:42:082040 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452041 SetGLError(GL_INVALID_OPERATION);
2042 return;
2043 }
2044 glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
2045}
2046
2047void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
2048 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082049 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452050 SetGLError(GL_INVALID_OPERATION);
2051 return;
2052 }
2053 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
2054}
2055
2056void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
2057 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082058 if (!bound_renderbuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452059 SetGLError(GL_INVALID_OPERATION);
2060 return;
2061 }
2062 glGetRenderbufferParameterivEXT(target, pname, params);
2063}
2064
2065void GLES2DecoderImpl::DoRenderbufferStorage(
2066 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:082067 if (!bound_renderbuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452068 SetGLError(GL_INVALID_OPERATION);
2069 return;
2070 }
2071 glRenderbufferStorageEXT(target, internalformat, width, height);
2072}
2073
[email protected]07f54fcc2009-12-22 02:46:302074void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]a93bb842010-02-16 23:03:472075 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2076 if (!info) {
2077 SetGLError(GL_INVALID_OPERATION);
2078 return;
2079 }
[email protected]07f54fcc2009-12-22 02:46:302080 CopyRealGLErrorsToWrapper();
2081 glLinkProgram(program);
2082 GLenum error = glGetError();
2083 if (error != GL_NO_ERROR) {
2084 RemoveProgramInfo(program);
2085 SetGLError(error);
2086 } else {
[email protected]a93bb842010-02-16 23:03:472087 info->Update();
[email protected]07f54fcc2009-12-22 02:46:302088 }
2089};
2090
[email protected]3916c97e2010-02-25 03:20:502091void GLES2DecoderImpl::DoTexParameterf(
2092 GLenum target, GLenum pname, GLfloat param) {
2093 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:302094 if (!info) {
[email protected]3916c97e2010-02-25 03:20:502095 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:302096 } else {
[email protected]3916c97e2010-02-25 03:20:502097 info->SetParameter(pname, static_cast<GLint>(param));
2098 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:302099 }
2100}
2101
[email protected]3916c97e2010-02-25 03:20:502102void GLES2DecoderImpl::DoTexParameteri(
2103 GLenum target, GLenum pname, GLint param) {
2104 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2105 if (!info) {
2106 SetGLError(GL_INVALID_VALUE);
2107 } else {
2108 info->SetParameter(pname, param);
2109 glTexParameteri(target, pname, param);
2110 }
2111}
2112
2113void GLES2DecoderImpl::DoTexParameterfv(
2114 GLenum target, GLenum pname, const GLfloat* params) {
2115 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2116 if (!info) {
2117 SetGLError(GL_INVALID_VALUE);
2118 } else {
2119 info->SetParameter(pname, *reinterpret_cast<const GLint*>(params));
2120 glTexParameterfv(target, pname, params);
2121 }
2122}
2123
2124void GLES2DecoderImpl::DoTexParameteriv(
2125 GLenum target, GLenum pname, const GLint* params) {
2126 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2127 if (!info) {
2128 SetGLError(GL_INVALID_VALUE);
2129 } else {
2130 info->SetParameter(pname, *params);
2131 glTexParameteriv(target, pname, params);
2132 }
2133}
2134
2135void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
2136 if (!current_program_ || current_program_->IsDeleted()) {
2137 // The program does not exist.
2138 SetGLError(GL_INVALID_OPERATION);
2139 return;
2140 }
2141 current_program_->SetSamplers(location, 1, &v0);
2142 glUniform1i(location, v0);
2143}
2144
2145void GLES2DecoderImpl::DoUniform1iv(
2146 GLint location, GLsizei count, const GLint *value) {
2147 if (!current_program_ || current_program_->IsDeleted()) {
2148 // The program does not exist.
2149 SetGLError(GL_INVALID_OPERATION);
2150 return;
2151 }
2152 current_program_->SetSamplers(location, count, value);
2153 glUniform1iv(location, count, value);
2154}
2155
2156void GLES2DecoderImpl::DoUseProgram(GLuint program) {
2157 ProgramManager::ProgramInfo* info = NULL;
2158 if (program) {
2159 info = GetProgramInfo(program);
2160 if (!info) {
2161 // Program was not linked successfully. (ie, glLinkProgram)
2162 SetGLError(GL_INVALID_OPERATION);
2163 return;
2164 }
2165 }
2166 current_program_ = info;
2167 glUseProgram(program);
2168}
2169
[email protected]96449d2c2009-11-25 00:01:322170GLenum GLES2DecoderImpl::GetGLError() {
2171 // Check the GL error first, then our wrapped error.
2172 GLenum error = glGetError();
2173 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:372174 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:322175 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:292176 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:322177 break;
2178 }
2179 }
2180 }
2181
2182 if (error != GL_NO_ERROR) {
2183 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:292184 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322185 }
2186 return error;
2187}
2188
2189void GLES2DecoderImpl::SetGLError(GLenum error) {
[email protected]ddd968b82010-03-02 00:44:292190 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322191}
2192
[email protected]07f54fcc2009-12-22 02:46:302193void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
2194 GLenum error;
2195 while ((error = glGetError()) != GL_NO_ERROR) {
2196 SetGLError(error);
2197 }
2198}
2199
[email protected]6217d392010-03-25 22:08:352200void GLES2DecoderImpl::ClearRealGLErrors() {
2201 GLenum error;
2202 while ((error = glGetError()) != GL_NO_ERROR) {
2203 NOTREACHED() << "GL error " << error << " was unhandled.";
2204 }
2205}
2206
[email protected]07f54fcc2009-12-22 02:46:302207bool GLES2DecoderImpl::VertexAttribInfo::CanAccess(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:502208 if (!enabled_) {
2209 return true;
2210 }
2211
2212 if (!buffer_ || buffer_->IsDeleted()) {
2213 return false;
2214 }
2215
2216 // The number of elements that can be accessed.
2217 GLsizeiptr buffer_size = buffer_->size();
2218 if (offset_ > buffer_size || real_stride_ == 0) {
2219 return false;
2220 }
2221
2222 uint32 usable_size = buffer_size - offset_;
2223 GLuint num_elements = usable_size / real_stride_ +
2224 ((usable_size % real_stride_) >=
2225 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
2226 return index < num_elements;
2227}
2228
2229void GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures(
2230 bool* has_non_renderable_textures) {
2231 DCHECK(has_non_renderable_textures);
2232 DCHECK(current_program_);
2233 DCHECK(!current_program_->IsDeleted());
2234 *has_non_renderable_textures = false;
2235 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
2236 current_program_->sampler_indices();
2237 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
2238 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2239 current_program_->GetUniformInfo(sampler_indices[ii]);
2240 DCHECK(uniform_info);
2241 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
2242 GLuint texture_unit_index = uniform_info->texture_units[jj];
2243 if (texture_unit_index < group_->max_texture_units()) {
2244 TextureUnit& texture_unit = texture_units_[texture_unit_index];
2245 TextureManager::TextureInfo* texture_info =
2246 uniform_info->type == GL_SAMPLER_2D ?
2247 texture_unit.bound_texture_2d :
2248 texture_unit.bound_texture_cube_map;
2249 if (!texture_info || !texture_info->CanRender()) {
2250 *has_non_renderable_textures = true;
2251 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
2252 glBindTexture(
2253 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
2254 GL_TEXTURE_CUBE_MAP,
2255 uniform_info->type == GL_SAMPLER_2D ? black_2d_texture_id_ :
2256 black_cube_texture_id_);
2257 }
2258 }
2259 // else: should this be an error?
2260 }
2261 }
2262}
2263
2264void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
2265 DCHECK(current_program_);
2266 DCHECK(!current_program_->IsDeleted());
2267 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
2268 current_program_->sampler_indices();
2269 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
2270 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2271 current_program_->GetUniformInfo(sampler_indices[ii]);
2272 DCHECK(uniform_info);
2273 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
2274 GLuint texture_unit_index = uniform_info->texture_units[jj];
2275 if (texture_unit_index < group_->max_texture_units()) {
2276 TextureUnit& texture_unit = texture_units_[texture_unit_index];
2277 TextureManager::TextureInfo* texture_info =
2278 uniform_info->type == GL_SAMPLER_2D ?
2279 texture_unit.bound_texture_2d :
2280 texture_unit.bound_texture_cube_map;
2281 if (!texture_info || !texture_info->CanRender()) {
2282 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
2283 // Get the texture info that was previously bound here.
2284 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
2285 texture_unit.bound_texture_2d :
2286 texture_unit.bound_texture_cube_map;
2287 glBindTexture(texture_unit.bind_target,
2288 texture_info ? texture_info->texture_id() : 0);
2289 }
2290 }
2291 }
2292 }
2293 // Set the active texture back to whatever the user had it as.
2294 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:302295}
2296
2297bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]3916c97e2010-02-25 03:20:502298 if (!current_program_ || current_program_->IsDeleted()) {
2299 // The program does not exist.
2300 // But GL says no ERROR.
2301 return false;
2302 }
2303 // Validate that all attribs current program needs are setup correctly.
2304 const ProgramManager::ProgramInfo::AttribInfoVector& infos =
2305 current_program_->GetAttribInfos();
2306 for (size_t ii = 0; ii < infos.size(); ++ii) {
2307 GLint location = infos[ii].location;
2308 if (location < 0) {
2309 return false;
2310 }
2311 DCHECK_LT(static_cast<GLuint>(location), group_->max_vertex_attribs());
2312 if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:462313 SetGLError(GL_INVALID_OPERATION);
2314 return false;
2315 }
[email protected]07f54fcc2009-12-22 02:46:302316 }
[email protected]3916c97e2010-02-25 03:20:502317 return true;
[email protected]07f54fcc2009-12-22 02:46:302318};
2319
[email protected]f7a64ee2010-02-01 22:24:142320error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:192321 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:502322 if (!bound_element_array_buffer_ ||
2323 bound_element_array_buffer_->IsDeleted()) {
2324 SetGLError(GL_INVALID_OPERATION);
2325 } else {
[email protected]96449d2c2009-11-25 00:01:322326 GLenum mode = c.mode;
2327 GLsizei count = c.count;
2328 GLenum type = c.type;
[email protected]1d32bc82010-01-13 22:06:462329 int32 offset = c.index_offset;
[email protected]a76b0052010-03-05 00:33:182330 if (count < 0 || offset < 0) {
[email protected]d2cf0a2d2010-02-25 21:36:122331 SetGLError(GL_INVALID_VALUE);
2332 } else if (!ValidateGLenumDrawMode(mode) ||
2333 !ValidateGLenumIndexType(type)) {
[email protected]1d32bc82010-01-13 22:06:462334 SetGLError(GL_INVALID_ENUM);
[email protected]ba3176a2009-12-16 18:19:462335 } else {
[email protected]0c86dbf2010-03-05 08:14:112336 GLuint max_vertex_accessed;
2337 if (!bound_element_array_buffer_->GetMaxValueForRange(
2338 offset, count, type, &max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:462339 SetGLError(GL_INVALID_OPERATION);
2340 } else {
[email protected]0c86dbf2010-03-05 08:14:112341 if (IsDrawValid(max_vertex_accessed)) {
2342 bool has_non_renderable_textures;
2343 SetBlackTextureForNonRenderableTextures(
2344 &has_non_renderable_textures);
[email protected]3916c97e2010-02-25 03:20:502345 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]0c86dbf2010-03-05 08:14:112346 glDrawElements(mode, count, type, indices);
2347 if (has_non_renderable_textures) {
2348 RestoreStateForNonRenderableTextures();
[email protected]1d32bc82010-01-13 22:06:462349 }
2350 }
[email protected]07f54fcc2009-12-22 02:46:302351 }
[email protected]ba3176a2009-12-16 18:19:462352 }
[email protected]96449d2c2009-11-25 00:01:322353 }
[email protected]f7a64ee2010-02-01 22:24:142354 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322355}
2356
[email protected]96449d2c2009-11-25 00:01:322357// Calls glShaderSource for the various versions of the ShaderSource command.
2358// Assumes that data / data_size points to a piece of memory that is in range
2359// of whatever context it came from (shared memory, immediate memory, bucket
2360// memory.)
[email protected]45bf5152010-02-12 00:11:312361error::Error GLES2DecoderImpl::ShaderSourceHelper(
2362 GLuint shader, const char* data, uint32 data_size) {
2363 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2364 if (!info) {
2365 SetGLError(GL_INVALID_OPERATION);
2366 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322367 }
[email protected]45bf5152010-02-12 00:11:312368 // Note: We don't actually call glShaderSource here. We wait until
2369 // the call to glCompileShader.
2370 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:142371 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322372}
2373
[email protected]f7a64ee2010-02-01 22:24:142374error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:192375 uint32 immediate_data_size, const gles2::ShaderSource& c) {
2376 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:502377 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:192378 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142379 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192380 }
[email protected]96449d2c2009-11-25 00:01:322381 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:312382 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:322383 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:462384 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142385 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:322386 }
[email protected]45bf5152010-02-12 00:11:312387 return ShaderSourceHelper(shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:322388}
2389
[email protected]f7a64ee2010-02-01 22:24:142390error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:192391 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
2392 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:502393 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:192394 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142395 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192396 }
[email protected]96449d2c2009-11-25 00:01:322397 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:312398 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:302399 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462400 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142401 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:322402 }
[email protected]45bf5152010-02-12 00:11:312403 return ShaderSourceHelper(shader, data, data_size);
2404}
2405
[email protected]558847a2010-03-24 07:02:542406error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
2407 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
2408 GLuint shader;
2409 if (!id_manager()->GetServiceId(c.shader, &shader)) {
2410 SetGLError(GL_INVALID_VALUE);
2411 return error::kNoError;
2412 }
2413 Bucket* bucket = GetBucket(c.data_bucket_id);
2414 if (!bucket || bucket->size() == 0) {
2415 return error::kInvalidArguments;
2416 }
2417 return ShaderSourceHelper(
2418 shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
2419 bucket->size() - 1);
2420}
2421
[email protected]45bf5152010-02-12 00:11:312422void GLES2DecoderImpl::DoCompileShader(GLuint shader) {
2423 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2424 if (!info) {
2425 SetGLError(GL_INVALID_OPERATION);
2426 return;
2427 }
2428 // TODO(gman): Run shader through compiler that converts GL ES 2.0 shader
2429 // to DesktopGL shader and pass that to glShaderSource and then
2430 // glCompileShader.
2431 const char* ptr = info->source().c_str();
2432 glShaderSource(shader, 1, &ptr, NULL);
2433 glCompileShader(shader);
2434};
2435
[email protected]ddd968b82010-03-02 00:44:292436void GLES2DecoderImpl::DoGetShaderiv(
2437 GLuint shader, GLenum pname, GLint* params) {
2438 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2439 if (!info) {
2440 SetGLError(GL_INVALID_OPERATION);
2441 return;
2442 }
2443 if (pname == GL_SHADER_SOURCE_LENGTH) {
2444 *params = info->source().size();
2445 } else {
2446 glGetShaderiv(shader, pname, params);
2447 }
2448}
2449
[email protected]45bf5152010-02-12 00:11:312450void GLES2DecoderImpl::DoGetShaderSource(
2451 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst) {
2452 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2453 if (!info) {
2454 SetGLError(GL_INVALID_OPERATION);
2455 return;
2456 }
[email protected]a76b0052010-03-05 00:33:182457 // bufsize is set by the service side code and should always be positive.
2458 DCHECK_GT(bufsize, 0);
[email protected]45bf5152010-02-12 00:11:312459 const std::string& source = info->source();
2460 GLsizei size = std::min(bufsize - 1, static_cast<GLsizei>(source.size()));
2461 if (length) {
2462 *length = size;
2463 }
2464 memcpy(dst, source.c_str(), size);
2465 dst[size] = '\0';
[email protected]96449d2c2009-11-25 00:01:322466}
2467
[email protected]f7a64ee2010-02-01 22:24:142468error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:192469 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]3916c97e2010-02-25 03:20:502470 if (bound_array_buffer_ && !bound_array_buffer_->IsDeleted()) {
[email protected]96449d2c2009-11-25 00:01:322471 GLuint indx = c.indx;
2472 GLint size = c.size;
2473 GLenum type = c.type;
2474 GLboolean normalized = c.normalized;
2475 GLsizei stride = c.stride;
[email protected]07f54fcc2009-12-22 02:46:302476 GLsizei offset = c.offset;
2477 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]ba3176a2009-12-16 18:19:462478 if (!ValidateGLenumVertexAttribType(type) ||
[email protected]d2cf0a2d2010-02-25 21:36:122479 !ValidateGLintVertexAttribSize(size)) {
2480 SetGLError(GL_INVALID_ENUM);
2481 return error::kNoError;
2482 }
2483 if (indx >= group_->max_vertex_attribs() ||
2484 stride < 0 ||
2485 offset < 0) {
[email protected]ba3176a2009-12-16 18:19:462486 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142487 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322488 }
[email protected]3916c97e2010-02-25 03:20:502489 GLsizei component_size =
2490 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]07f54fcc2009-12-22 02:46:302491 GLsizei real_stride = stride != 0 ? stride : component_size * size;
2492 if (offset % component_size > 0) {
2493 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142494 return error::kNoError;
[email protected]07f54fcc2009-12-22 02:46:302495 }
2496 vertex_attrib_infos_[indx].SetInfo(
2497 bound_array_buffer_,
[email protected]07f54fcc2009-12-22 02:46:302498 size,
2499 type,
2500 real_stride,
2501 offset);
[email protected]96449d2c2009-11-25 00:01:322502 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
2503 } else {
2504 SetGLError(GL_INVALID_VALUE);
2505 }
[email protected]f7a64ee2010-02-01 22:24:142506 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322507}
2508
[email protected]f7a64ee2010-02-01 22:24:142509error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:192510 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:312511 GLint x = c.x;
2512 GLint y = c.y;
2513 GLsizei width = c.width;
2514 GLsizei height = c.height;
2515 GLenum format = c.format;
2516 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:562517 if (width < 0 || height < 0) {
2518 SetGLError(GL_INVALID_VALUE);
2519 return error::kNoError;
2520 }
[email protected]a51788e2010-02-24 21:54:252521 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:182522 uint32 pixels_size;
2523 if (!GLES2Util::ComputeImageDataSize(
2524 width, height, format, type, pack_alignment_, &pixels_size)) {
2525 return error::kOutOfBounds;
2526 }
[email protected]612d2f82009-12-08 20:49:312527 void* pixels = GetSharedMemoryAs<void*>(
2528 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:252529 Result* result = GetSharedMemoryAs<Result*>(
2530 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2531 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:142532 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462533 }
[email protected]a51788e2010-02-24 21:54:252534
[email protected]ba3176a2009-12-16 18:19:462535 if (!ValidateGLenumReadPixelFormat(format) ||
2536 !ValidateGLenumPixelType(type)) {
[email protected]d2cf0a2d2010-02-25 21:36:122537 SetGLError(GL_INVALID_ENUM);
2538 return error::kNoError;
2539 }
[email protected]57f223832010-03-19 01:57:562540 if (width == 0 || height == 0) {
2541 return error::kNoError;
2542 }
2543
2544 CopyRealGLErrorsToWrapper();
2545
2546 // Get the size of the current fbo or backbuffer.
[email protected]d37231fa2010-04-09 21:16:022547 gfx::Size max_size = GetBoundFrameBufferSize();
[email protected]57f223832010-03-19 01:57:562548
2549 GLint max_x;
2550 GLint max_y;
2551 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]ba3176a2009-12-16 18:19:462552 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142553 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:312554 }
[email protected]57f223832010-03-19 01:57:562555
[email protected]d37231fa2010-04-09 21:16:022556 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:562557 // The user requested an out of range area. Get the results 1 line
2558 // at a time.
2559 uint32 temp_size;
2560 if (!GLES2Util::ComputeImageDataSize(
2561 width, 1, format, type, pack_alignment_, &temp_size)) {
2562 SetGLError(GL_INVALID_VALUE);
2563 return error::kNoError;
2564 }
2565 GLsizei unpadded_row_size = temp_size;
2566 if (!GLES2Util::ComputeImageDataSize(
2567 width, 2, format, type, pack_alignment_, &temp_size)) {
2568 SetGLError(GL_INVALID_VALUE);
2569 return error::kNoError;
2570 }
2571 GLsizei padded_row_size = temp_size - unpadded_row_size;
2572 if (padded_row_size < 0 || unpadded_row_size < 0) {
2573 SetGLError(GL_INVALID_VALUE);
2574 return error::kNoError;
2575 }
2576
2577 GLint dest_x_offset = std::max(-x, 0);
2578 uint32 dest_row_offset;
2579 if (!GLES2Util::ComputeImageDataSize(
2580 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
2581 SetGLError(GL_INVALID_VALUE);
2582 return error::kNoError;
2583 }
2584
2585 // Copy each row into the larger dest rect.
2586 int8* dst = static_cast<int8*>(pixels);
2587 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:022588 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:562589 GLint read_width = read_end_x - read_x;
2590 for (GLint yy = 0; yy < height; ++yy) {
2591 GLint ry = y + yy;
2592
2593 // Clear the row.
2594 memset(dst, 0, unpadded_row_size);
2595
2596 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:022597 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:562598 glReadPixels(
2599 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
2600 }
2601 dst += padded_row_size;
2602 }
2603 } else {
2604 glReadPixels(x, y, width, height, format, type, pixels);
2605 }
[email protected]a51788e2010-02-24 21:54:252606 GLenum error = glGetError();
2607 if (error == GL_NO_ERROR) {
2608 *result = true;
2609 } else {
2610 SetGLError(error);
2611 }
[email protected]f7a64ee2010-02-01 22:24:142612 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322613}
2614
[email protected]f7a64ee2010-02-01 22:24:142615error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:192616 uint32 immediate_data_size, const gles2::PixelStorei& c) {
2617 GLenum pname = c.pname;
2618 GLenum param = c.param;
[email protected]d2cf0a2d2010-02-25 21:36:122619 if (!ValidateGLenumPixelStore(pname)) {
2620 SetGLError(GL_INVALID_ENUM);
2621 return error::kNoError;
2622 }
2623 if (!ValidateGLintPixelStoreAlignment(param)) {
[email protected]ba3176a2009-12-16 18:19:462624 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142625 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192626 }
2627 glPixelStorei(pname, param);
2628 switch (pname) {
2629 case GL_PACK_ALIGNMENT:
2630 pack_alignment_ = param;
2631 break;
2632 case GL_UNPACK_ALIGNMENT:
2633 unpack_alignment_ = param;
2634 break;
2635 default:
2636 // Validation should have prevented us from getting here.
2637 DCHECK(false);
2638 break;
2639 }
[email protected]f7a64ee2010-02-01 22:24:142640 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192641}
2642
[email protected]558847a2010-03-24 07:02:542643error::Error GLES2DecoderImpl::GetAttribLocationHelper(
2644 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
2645 const std::string& name_str) {
[email protected]b9849abf2009-11-25 19:13:192646 GLuint program;
[email protected]558847a2010-03-24 07:02:542647 if (!id_manager()->GetServiceId(client_id, &program)) {
[email protected]b9849abf2009-11-25 19:13:192648 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142649 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192650 }
[email protected]0bfd9882010-02-05 23:02:252651 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2652 if (!info) {
2653 // Program was not linked successfully. (ie, glLinkProgram)
2654 SetGLError(GL_INVALID_OPERATION);
2655 return error::kNoError;
2656 }
[email protected]b9849abf2009-11-25 19:13:192657 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:542658 location_shm_id, location_shm_offset, sizeof(GLint));
2659 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:142660 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192661 }
[email protected]558847a2010-03-24 07:02:542662 // Require the client to init this incase the context is lost and we are no
2663 // longer executing commands.
2664 if (*location != -1) {
2665 return error::kGenericError;
2666 }
[email protected]0bfd9882010-02-05 23:02:252667 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142668 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192669}
2670
[email protected]558847a2010-03-24 07:02:542671error::Error GLES2DecoderImpl::HandleGetAttribLocation(
2672 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
2673 uint32 name_size = c.data_size;
2674 const char* name = GetSharedMemoryAs<const char*>(
2675 c.name_shm_id, c.name_shm_offset, name_size);
2676 if (!name) {
2677 return error::kOutOfBounds;
2678 }
2679 String name_str(name, name_size);
2680 return GetAttribLocationHelper(
2681 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2682}
2683
[email protected]f7a64ee2010-02-01 22:24:142684error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192685 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:542686 uint32 name_size = c.data_size;
2687 const char* name = GetImmediateDataAs<const char*>(
2688 c, name_size, immediate_data_size);
2689 if (!name) {
2690 return error::kOutOfBounds;
2691 }
2692 String name_str(name, name_size);
2693 return GetAttribLocationHelper(
2694 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2695}
2696
2697error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
2698 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
2699 Bucket* bucket = GetBucket(c.name_bucket_id);
2700 if (!bucket) {
2701 return error::kInvalidArguments;
2702 }
2703 std::string name_str;
2704 bucket->GetAsString(&name_str);
2705 return GetAttribLocationHelper(
2706 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2707}
2708
2709error::Error GLES2DecoderImpl::GetUniformLocationHelper(
2710 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
2711 const std::string& name_str) {
[email protected]b9849abf2009-11-25 19:13:192712 GLuint program;
[email protected]558847a2010-03-24 07:02:542713 if (!id_manager()->GetServiceId(client_id, &program)) {
[email protected]b9849abf2009-11-25 19:13:192714 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142715 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192716 }
[email protected]0bfd9882010-02-05 23:02:252717 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2718 if (!info) {
2719 // Program was not linked successfully. (ie, glLinkProgram)
2720 SetGLError(GL_INVALID_OPERATION);
2721 return error::kNoError;
2722 }
[email protected]b9849abf2009-11-25 19:13:192723 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:542724 location_shm_id, location_shm_offset, sizeof(GLint));
2725 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:142726 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192727 }
[email protected]558847a2010-03-24 07:02:542728 // Require the client to init this incase the context is lost an we are no
2729 // longer executing commands.
2730 if (*location != -1) {
2731 return error::kGenericError;
2732 }
2733 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142734 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192735}
2736
[email protected]f7a64ee2010-02-01 22:24:142737error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:192738 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:192739 uint32 name_size = c.data_size;
2740 const char* name = GetSharedMemoryAs<const char*>(
2741 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:542742 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:142743 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192744 }
2745 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:542746 return GetUniformLocationHelper(
2747 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:192748}
2749
[email protected]f7a64ee2010-02-01 22:24:142750error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192751 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:192752 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:302753 const char* name = GetImmediateDataAs<const char*>(
2754 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:542755 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:142756 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192757 }
2758 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:542759 return GetUniformLocationHelper(
2760 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2761}
2762
2763error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
2764 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
2765 Bucket* bucket = GetBucket(c.name_bucket_id);
2766 if (!bucket) {
2767 return error::kInvalidArguments;
2768 }
2769 std::string name_str;
2770 bucket->GetAsString(&name_str);
2771 return GetUniformLocationHelper(
2772 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:192773}
2774
[email protected]ddd968b82010-03-02 00:44:292775error::Error GLES2DecoderImpl::HandleGetString(
2776 uint32 immediate_data_size, const gles2::GetString& c) {
2777 GLenum name = static_cast<GLenum>(c.name);
2778 if (!ValidateGLenumStringType(name)) {
2779 SetGLError(GL_INVALID_ENUM);
2780 return error::kNoError;
2781 }
2782 Bucket* bucket = CreateBucket(c.bucket_id);
2783 bucket->SetFromString(reinterpret_cast<const char*>(glGetString(name)));
2784 return error::kNoError;
2785}
2786
[email protected]0c86dbf2010-03-05 08:14:112787void GLES2DecoderImpl::DoBufferData(
2788 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]3b6ec202010-03-05 05:16:232789 if (!ValidateGLenumBufferTarget(target) ||
2790 !ValidateGLenumBufferUsage(usage)) {
2791 SetGLError(GL_INVALID_ENUM);
[email protected]0c86dbf2010-03-05 08:14:112792 return;
[email protected]3b6ec202010-03-05 05:16:232793 }
2794 if (size < 0) {
2795 SetGLError(GL_INVALID_VALUE);
[email protected]0c86dbf2010-03-05 08:14:112796 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232797 }
2798 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
2799 if (!info) {
2800 SetGLError(GL_INVALID_OPERATION);
[email protected]0c86dbf2010-03-05 08:14:112801 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232802 }
2803 // Clear the buffer to 0 if no initial data was passed in.
2804 scoped_array<int8> zero;
2805 if (!data) {
2806 zero.reset(new int8[size]);
2807 memset(zero.get(), 0, size);
2808 data = zero.get();
2809 }
2810 CopyRealGLErrorsToWrapper();
2811 glBufferData(target, size, data, usage);
2812 GLenum error = glGetError();
2813 if (error != GL_NO_ERROR) {
2814 SetGLError(error);
2815 } else {
[email protected]0c86dbf2010-03-05 08:14:112816 info->SetSize(size);
2817 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:232818 }
[email protected]0c86dbf2010-03-05 08:14:112819}
2820
2821error::Error GLES2DecoderImpl::HandleBufferData(
2822 uint32 immediate_data_size, const gles2::BufferData& c) {
2823 GLenum target = static_cast<GLenum>(c.target);
2824 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
2825 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
2826 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
2827 GLenum usage = static_cast<GLenum>(c.usage);
2828 const void* data = NULL;
2829 if (data_shm_id != 0 || data_shm_offset != 0) {
2830 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
2831 if (!data) {
2832 return error::kOutOfBounds;
2833 }
2834 }
2835 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:142836 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192837}
2838
[email protected]f7a64ee2010-02-01 22:24:142839error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:192840 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
2841 GLenum target = static_cast<GLenum>(c.target);
2842 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:302843 const void* data = GetImmediateDataAs<const void*>(
2844 c, size, immediate_data_size);
2845 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142846 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:302847 }
[email protected]b9849abf2009-11-25 19:13:192848 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:112849 DoBufferData(target, size, data, usage);
2850 return error::kNoError;
2851}
2852
2853void GLES2DecoderImpl::DoBufferSubData(
2854 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:502855 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472856 if (!info) {
2857 SetGLError(GL_INVALID_OPERATION);
[email protected]a93bb842010-02-16 23:03:472858 }
[email protected]0c86dbf2010-03-05 08:14:112859 if (!info->SetRange(offset, size, data)) {
2860 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:302861 } else {
[email protected]0c86dbf2010-03-05 08:14:112862 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:302863 }
[email protected]b9849abf2009-11-25 19:13:192864}
2865
[email protected]a93bb842010-02-16 23:03:472866error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
2867 GLenum target,
2868 GLint level,
2869 GLenum internal_format,
2870 GLsizei width,
2871 GLsizei height,
2872 GLint border,
2873 GLsizei image_size,
2874 const void* data) {
[email protected]a93bb842010-02-16 23:03:472875 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]86093972010-03-11 00:13:562876 if (!ValidateGLenumTextureTarget(target) ||
2877 !ValidateGLenumCompressedTextureInternalFormat(internal_format)) {
[email protected]a93bb842010-02-16 23:03:472878 SetGLError(GL_INVALID_ENUM);
2879 return error::kNoError;
2880 }
[email protected]3916c97e2010-02-25 03:20:502881 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:472882 border != 0) {
2883 SetGLError(GL_INVALID_VALUE);
2884 return error::kNoError;
2885 }
[email protected]3916c97e2010-02-25 03:20:502886 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472887 if (!info) {
2888 SetGLError(GL_INVALID_OPERATION);
2889 return error::kNoError;
2890 }
2891 scoped_array<int8> zero;
2892 if (!data) {
2893 zero.reset(new int8[image_size]);
2894 memset(zero.get(), 0, image_size);
2895 data = zero.get();
2896 }
2897 info->SetLevelInfo(
2898 target, level, internal_format, width, height, 1, border, 0, 0);
2899 glCompressedTexImage2D(
2900 target, level, internal_format, width, height, border, image_size, data);
2901 return error::kNoError;
2902}
2903
[email protected]f7a64ee2010-02-01 22:24:142904error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192905 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
2906 GLenum target = static_cast<GLenum>(c.target);
2907 GLint level = static_cast<GLint>(c.level);
2908 GLenum internal_format = static_cast<GLenum>(c.internalformat);
2909 GLsizei width = static_cast<GLsizei>(c.width);
2910 GLsizei height = static_cast<GLsizei>(c.height);
2911 GLint border = static_cast<GLint>(c.border);
2912 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
2913 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
2914 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
2915 const void* data = NULL;
2916 if (data_shm_id != 0 || data_shm_offset != 0) {
2917 data = GetSharedMemoryAs<const void*>(
2918 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:462919 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142920 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192921 }
2922 }
[email protected]a93bb842010-02-16 23:03:472923 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192924 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:192925}
2926
[email protected]f7a64ee2010-02-01 22:24:142927error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:192928 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
2929 GLenum target = static_cast<GLenum>(c.target);
2930 GLint level = static_cast<GLint>(c.level);
2931 GLenum internal_format = static_cast<GLenum>(c.internalformat);
2932 GLsizei width = static_cast<GLsizei>(c.width);
2933 GLsizei height = static_cast<GLsizei>(c.height);
2934 GLint border = static_cast<GLint>(c.border);
2935 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:302936 const void* data = GetImmediateDataAs<const void*>(
2937 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462938 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142939 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462940 }
[email protected]a93bb842010-02-16 23:03:472941 return DoCompressedTexImage2D(
2942 target, level, internal_format, width, height, border, image_size, data);
2943}
2944
[email protected]a93bb842010-02-16 23:03:472945error::Error GLES2DecoderImpl::DoTexImage2D(
2946 GLenum target,
2947 GLint level,
2948 GLenum internal_format,
2949 GLsizei width,
2950 GLsizei height,
2951 GLint border,
2952 GLenum format,
2953 GLenum type,
2954 const void* pixels,
2955 uint32 pixels_size) {
2956 if (!ValidateGLenumTextureTarget(target) ||
2957 !ValidateGLenumTextureFormat(internal_format) ||
2958 !ValidateGLenumTextureFormat(format) ||
2959 !ValidateGLenumPixelType(type)) {
[email protected]8bf5a3e2010-01-29 04:21:362960 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:142961 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192962 }
[email protected]3916c97e2010-02-25 03:20:502963 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:472964 border != 0) {
2965 SetGLError(GL_INVALID_VALUE);
2966 return error::kNoError;
2967 }
[email protected]3916c97e2010-02-25 03:20:502968 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472969 if (!info) {
2970 SetGLError(GL_INVALID_OPERATION);
2971 return error::kNoError;
2972 }
2973 scoped_array<int8> zero;
2974 if (!pixels) {
2975 zero.reset(new int8[pixels_size]);
2976 memset(zero.get(), 0, pixels_size);
2977 pixels = zero.get();
2978 }
2979 info->SetLevelInfo(
2980 target, level, internal_format, width, height, 1, border, format, type);
2981 glTexImage2D(
2982 target, level, internal_format, width, height, border, format, type,
2983 pixels);
[email protected]f7a64ee2010-02-01 22:24:142984 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192985}
2986
[email protected]f7a64ee2010-02-01 22:24:142987error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192988 uint32 immediate_data_size, const gles2::TexImage2D& c) {
2989 GLenum target = static_cast<GLenum>(c.target);
2990 GLint level = static_cast<GLint>(c.level);
2991 GLint internal_format = static_cast<GLint>(c.internalformat);
2992 GLsizei width = static_cast<GLsizei>(c.width);
2993 GLsizei height = static_cast<GLsizei>(c.height);
2994 GLint border = static_cast<GLint>(c.border);
2995 GLenum format = static_cast<GLenum>(c.format);
2996 GLenum type = static_cast<GLenum>(c.type);
2997 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
2998 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:182999 uint32 pixels_size;
3000 if (!GLES2Util::ComputeImageDataSize(
3001 width, height, format, type, unpack_alignment_, &pixels_size)) {
3002 return error::kOutOfBounds;
3003 }
[email protected]b9849abf2009-11-25 19:13:193004 const void* pixels = NULL;
3005 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
3006 pixels = GetSharedMemoryAs<const void*>(
3007 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:463008 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:143009 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193010 }
3011 }
[email protected]a93bb842010-02-16 23:03:473012 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:193013 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:473014 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:193015}
3016
[email protected]f7a64ee2010-02-01 22:24:143017error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:193018 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
3019 GLenum target = static_cast<GLenum>(c.target);
3020 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:463021 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:193022 GLsizei width = static_cast<GLsizei>(c.width);
3023 GLsizei height = static_cast<GLsizei>(c.height);
3024 GLint border = static_cast<GLint>(c.border);
3025 GLenum format = static_cast<GLenum>(c.format);
3026 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:183027 uint32 size;
3028 if (!GLES2Util::ComputeImageDataSize(
3029 width, height, format, type, unpack_alignment_, &size)) {
3030 return error::kOutOfBounds;
3031 }
[email protected]07f54fcc2009-12-22 02:46:303032 const void* pixels = GetImmediateDataAs<const void*>(
3033 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:463034 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:143035 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:463036 }
[email protected]a93bb842010-02-16 23:03:473037 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:463038 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:473039 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:143040 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323041}
3042
[email protected]f7a64ee2010-02-01 22:24:143043error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:193044 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:363045 GLuint index = static_cast<GLuint>(c.index);
3046 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:253047 typedef gles2::GetVertexAttribPointerv::Result Result;
3048 Result* result = GetSharedMemoryAs<Result*>(
3049 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:363050 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:143051 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:363052 }
[email protected]07d0cc82010-02-17 04:51:403053 // Check that the client initialized the result.
3054 if (result->size != 0) {
3055 return error::kInvalidArguments;
3056 }
[email protected]8bf5a3e2010-01-29 04:21:363057 if (!ValidateGLenumVertexPointer(pname)) {
3058 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:143059 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:363060 }
[email protected]3916c97e2010-02-25 03:20:503061 if (index >= group_->max_vertex_attribs()) {
[email protected]8bf5a3e2010-01-29 04:21:363062 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:143063 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:363064 }
[email protected]0bfd9882010-02-05 23:02:253065 result->SetNumResults(1);
3066 *result->GetData() = vertex_attrib_infos_[index].offset();
[email protected]f7a64ee2010-02-01 22:24:143067 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323068}
3069
[email protected]f7b85372010-02-03 01:11:373070bool GLES2DecoderImpl::GetUniformSetup(
3071 GLuint program, GLint location,
3072 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:253073 error::Error* error, GLuint* service_id, void** result_pointer) {
[email protected]f7b85372010-02-03 01:11:373074 *error = error::kNoError;
3075 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:253076 SizedResult<GLint>* result;
3077 result = GetSharedMemoryAs<SizedResult<GLint>*>(
3078 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
3079 if (!result) {
[email protected]f7b85372010-02-03 01:11:373080 *error = error::kOutOfBounds;
3081 return false;
3082 }
[email protected]0bfd9882010-02-05 23:02:253083 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:373084 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:253085 result->SetNumResults(0);
[email protected]3916c97e2010-02-25 03:20:503086 if (!id_manager()->GetServiceId(program, service_id)) {
[email protected]f7b85372010-02-03 01:11:373087 SetGLError(GL_INVALID_VALUE);
3088 return error::kNoError;
3089 }
3090 ProgramManager::ProgramInfo* info = GetProgramInfo(*service_id);
3091 if (!info) {
3092 // Program was not linked successfully. (ie, glLinkProgram)
3093 SetGLError(GL_INVALID_OPERATION);
3094 return false;
3095 }
[email protected]0bfd9882010-02-05 23:02:253096 GLenum type;
3097 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:373098 // No such location.
3099 SetGLError(GL_INVALID_OPERATION);
3100 return false;
3101 }
[email protected]3916c97e2010-02-25 03:20:503102 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:373103 if (size == 0) {
3104 SetGLError(GL_INVALID_OPERATION);
3105 return false;
3106 }
[email protected]0bfd9882010-02-05 23:02:253107 result = GetSharedMemoryAs<SizedResult<GLint>*>(
3108 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
3109 if (!result) {
[email protected]f7b85372010-02-03 01:11:373110 *error = error::kOutOfBounds;
3111 return false;
3112 }
[email protected]0bfd9882010-02-05 23:02:253113 result->size = size;
[email protected]f7b85372010-02-03 01:11:373114 return true;
3115}
3116
[email protected]f7a64ee2010-02-01 22:24:143117error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:193118 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:373119 GLuint program = c.program;
3120 GLint location = c.location;
3121 GLuint service_id;
3122 Error error;
[email protected]0bfd9882010-02-05 23:02:253123 void* result;
[email protected]f7b85372010-02-03 01:11:373124 if (GetUniformSetup(
3125 program, location, c.params_shm_id, c.params_shm_offset,
3126 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:253127 glGetUniformiv(
3128 service_id, location,
3129 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:373130 }
3131 return error;
[email protected]96449d2c2009-11-25 00:01:323132}
3133
[email protected]f7a64ee2010-02-01 22:24:143134error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:193135 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:373136 GLuint program = c.program;
3137 GLint location = c.location;
3138 GLuint service_id;
3139 Error error;
[email protected]0bfd9882010-02-05 23:02:253140 void* result;
3141 typedef gles2::GetUniformfv::Result Result;
[email protected]f7b85372010-02-03 01:11:373142 if (GetUniformSetup(
3143 program, location, c.params_shm_id, c.params_shm_offset,
3144 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:253145 glGetUniformfv(
3146 service_id,
3147 location,
3148 static_cast<gles2::GetUniformfv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:373149 }
3150 return error;
[email protected]96449d2c2009-11-25 00:01:323151}
3152
[email protected]f7a64ee2010-02-01 22:24:143153error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:193154 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:253155 GLenum shader_type = static_cast<GLenum>(c.shadertype);
3156 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
3157 typedef gles2::GetShaderPrecisionFormat::Result Result;
3158 Result* result = GetSharedMemoryAs<Result*>(
3159 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3160 if (!result) {
3161 return error::kOutOfBounds;
3162 }
[email protected]07d0cc82010-02-17 04:51:403163 // Check that the client initialized the result.
3164 if (result->success != 0) {
3165 return error::kInvalidArguments;
3166 }
[email protected]0bfd9882010-02-05 23:02:253167 if (!ValidateGLenumShaderType(shader_type) ||
3168 !ValidateGLenumShaderPrecision(precision_type)) {
[email protected]0bfd9882010-02-05 23:02:253169 SetGLError(GL_INVALID_ENUM);
3170 } else {
3171 result->success = 1; // true
3172 switch (precision_type) {
3173 case GL_LOW_INT:
3174 case GL_MEDIUM_INT:
3175 case GL_HIGH_INT:
3176 result->min_range = -31;
3177 result->max_range = 31;
3178 result->precision = 0;
3179 case GL_LOW_FLOAT:
3180 case GL_MEDIUM_FLOAT:
3181 case GL_HIGH_FLOAT:
3182 result->min_range = -62;
3183 result->max_range = 62;
3184 result->precision = -16;
3185 break;
3186 default:
3187 NOTREACHED();
3188 break;
3189 }
3190 }
[email protected]f7a64ee2010-02-01 22:24:143191 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323192}
3193
[email protected]f7a64ee2010-02-01 22:24:143194error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:193195 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:253196 GLuint service_id;
3197 uint32 result_size = c.result_size;
[email protected]3916c97e2010-02-25 03:20:503198 if (!id_manager()->GetServiceId(c.program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:253199 SetGLError(GL_INVALID_VALUE);
3200 return error::kNoError;
3201 }
3202 typedef gles2::GetAttachedShaders::Result Result;
3203 uint32 max_count = Result::ComputeMaxResults(result_size);
3204 Result* result = GetSharedMemoryAs<Result*>(
3205 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
3206 if (!result) {
3207 return error::kOutOfBounds;
3208 }
[email protected]07d0cc82010-02-17 04:51:403209 // Check that the client initialized the result.
3210 if (result->size != 0) {
3211 return error::kInvalidArguments;
3212 }
[email protected]0bfd9882010-02-05 23:02:253213 GLsizei count = 0;
3214 glGetAttachedShaders(service_id, max_count, &count, result->GetData());
3215 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]3916c97e2010-02-25 03:20:503216 if (!id_manager()->GetClientId(result->GetData()[ii],
[email protected]0bfd9882010-02-05 23:02:253217 &result->GetData()[ii])) {
3218 NOTREACHED();
3219 return error::kGenericError;
3220 }
3221 }
3222 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:143223 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323224}
3225
[email protected]f7a64ee2010-02-01 22:24:143226error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:193227 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:253228 GLuint program = c.program;
3229 GLuint index = c.index;
3230 uint32 name_bucket_id = c.name_bucket_id;
3231 GLuint service_id;
3232 typedef gles2::GetActiveUniform::Result Result;
3233 Result* result = GetSharedMemoryAs<Result*>(
3234 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3235 if (!result) {
3236 return error::kOutOfBounds;
3237 }
[email protected]07d0cc82010-02-17 04:51:403238 // Check that the client initialized the result.
3239 if (result->success != 0) {
3240 return error::kInvalidArguments;
3241 }
[email protected]3916c97e2010-02-25 03:20:503242 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:253243 SetGLError(GL_INVALID_VALUE);
3244 return error::kNoError;
3245 }
3246 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
3247 if (!info) {
3248 // Program was not linked successfully. (ie, glLinkProgram)
3249 SetGLError(GL_INVALID_OPERATION);
3250 return error::kNoError;
3251 }
3252 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
3253 info->GetUniformInfo(index);
3254 if (!uniform_info) {
3255 SetGLError(GL_INVALID_VALUE);
3256 return error::kNoError;
3257 }
3258 result->success = 1; // true.
3259 result->size = uniform_info->size;
3260 result->type = uniform_info->type;
3261 Bucket* bucket = CreateBucket(name_bucket_id);
3262 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:143263 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323264}
3265
[email protected]f7a64ee2010-02-01 22:24:143266error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:193267 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:253268 GLuint program = c.program;
3269 GLuint index = c.index;
3270 uint32 name_bucket_id = c.name_bucket_id;
3271 GLuint service_id;
3272 typedef gles2::GetActiveAttrib::Result Result;
3273 Result* result = GetSharedMemoryAs<Result*>(
3274 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3275 if (!result) {
3276 return error::kOutOfBounds;
3277 }
[email protected]07d0cc82010-02-17 04:51:403278 // Check that the client initialized the result.
3279 if (result->success != 0) {
3280 return error::kInvalidArguments;
3281 }
[email protected]3916c97e2010-02-25 03:20:503282 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:253283 SetGLError(GL_INVALID_VALUE);
3284 return error::kNoError;
3285 }
3286 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
3287 if (!info) {
3288 // Program was not linked successfully. (ie, glLinkProgram)
3289 SetGLError(GL_INVALID_OPERATION);
3290 return error::kNoError;
3291 }
3292 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
3293 info->GetAttribInfo(index);
3294 if (!attrib_info) {
3295 SetGLError(GL_INVALID_VALUE);
3296 return error::kNoError;
3297 }
3298 result->success = 1; // true.
3299 result->size = attrib_info->size;
3300 result->type = attrib_info->type;
3301 Bucket* bucket = CreateBucket(name_bucket_id);
3302 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:143303 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323304}
3305
[email protected]b273e432010-04-12 17:23:583306error::Error GLES2DecoderImpl::HandleShaderBinary(
3307 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
3308#if 1 // No binary shader support.
3309 SetGLError(GL_INVALID_OPERATION);
3310 return error::kNoError;
3311#else
3312 GLsizei n = static_cast<GLsizei>(c.n);
3313 if (n < 0) {
3314 SetGLError(GL_INVALID_VALUE);
3315 return error::kNoError;
3316 }
3317 GLsizei length = static_cast<GLsizei>(c.length);
3318 if (length < 0) {
3319 SetGLError(GL_INVALID_VALUE);
3320 return error::kNoError;
3321 }
3322 uint32 data_size;
3323 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3324 return error::kOutOfBounds;
3325 }
3326 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
3327 c.shaders_shm_id, c.shaders_shm_offset, data_size);
3328 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
3329 const void* binary = GetSharedMemoryAs<const void*>(
3330 c.binary_shm_id, c.binary_shm_offset, length);
3331 if (shaders == NULL || binary == NULL) {
3332 return error::kOutOfBounds;
3333 }
3334 scoped_array<GLuint> service_ids(new GLuint[n]);
3335 for (GLsizei ii = 0; ii < n; ++ii) {
3336 if (!id_manager()->GetServiceId(shaders[ii], &service_ids[ii])) {
3337 SetGLError(GL_INVALID_VALUE);
3338 return error::kNoError;
3339 }
3340 // TODO(gman): Check that each shader exists.
3341 }
3342 // TODO(gman): call glShaderBinary
3343 return error::kNoError;
3344#endif
3345}
3346
[email protected]6217d392010-03-25 22:08:353347error::Error GLES2DecoderImpl::HandleSwapBuffers(
3348 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
3349 // Check a client created frame buffer is not bound. TODO(apatrick):
3350 // this error is overkill. It will require that the client recreate the
3351 // context to continue.
[email protected]051b1372010-04-12 02:42:083352 if (bound_framebuffer_)
[email protected]6217d392010-03-25 22:08:353353 return error::kLostContext;
3354
3355 // If offscreen then don't actually SwapBuffers to the display. Just copy
3356 // the rendered frame to another frame buffer.
3357 if (offscreen_target_frame_buffer_.get()) {
3358 ScopedGLErrorSuppressor suppressor(this);
3359
3360 // First check to see if a deferred offscreen render buffer resize is
3361 // pending.
3362 if (!UpdateOffscreenFrameBufferSize())
3363 return error::kLostContext;
3364
3365 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]d37231fa2010-04-09 21:16:023366 offscreen_saved_color_texture_->Copy(
3367 offscreen_saved_color_texture_->size());
[email protected]6217d392010-03-25 22:08:353368 } else {
[email protected]d37231fa2010-04-09 21:16:023369#if !defined(UNIT_TEST)
3370 context_->SwapBuffers();
[email protected]6217d392010-03-25 22:08:353371#endif
3372 }
3373
3374 if (swap_buffers_callback_.get()) {
3375 swap_buffers_callback_->Run();
3376 }
3377
3378 return error::kNoError;
3379}
3380
[email protected]96449d2c2009-11-25 00:01:323381// Include the auto-generated part of this file. We split this because it means
3382// we can easily edit the non-auto generated parts right here in this file
3383// instead of having to edit some template or the code generator.
3384#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
3385
3386} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:253387} // namespace gpu