blob: 3cc59e69f6de583f5571b0dc0d98543b1b029faf [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]58ae32f2010-04-14 01:26:0438#if defined(UNIT_TEST)
39
40// OpenGL constants not defined in OpenGL ES 2.0 needed when compiling
41// unit tests. For native OpenGL ES 2.0 backend these are not used. For OpenGL
42// backend these must be defined by the local system.
43#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
44#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
45#define GL_MAX_VARYING_FLOATS 0x8B4B
46
47#endif
48
[email protected]a7a27ace2009-12-12 00:11:2549namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3250namespace gles2 {
51
[email protected]6217d392010-03-25 22:08:3552class GLES2DecoderImpl;
53
[email protected]07f54fcc2009-12-22 02:46:3054// Check that certain assumptions the code makes are true. There are places in
55// the code where shared memory is passed direclty to GL. Example, glUniformiv,
56// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
57// a few others) are 32bits. If they are not 32bits the code will have to change
58// to call those GL functions with service side memory and then copy the results
59// to shared memory, converting the sizes.
60COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
61 GLint_not_same_size_as_uint32);
62COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
63 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3764COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
65 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3066
[email protected]43f28f832010-02-03 02:28:4867// TODO(kbr): the use of this anonymous namespace core dumps the
68// linker on Mac OS X 10.6 when the symbol ordering file is used
69// namespace {
[email protected]96449d2c2009-11-25 00:01:3270
71// Returns the address of the first byte after a struct.
72template <typename T>
73const void* AddressAfterStruct(const T& pod) {
74 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
75}
76
[email protected]07f54fcc2009-12-22 02:46:3077// Returns the address of the frst byte after the struct or NULL if size >
78// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3279template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3080RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
81 uint32 size,
82 uint32 immediate_data_size) {
83 return (size <= immediate_data_size) ?
84 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
85 NULL;
[email protected]96449d2c2009-11-25 00:01:3286}
87
[email protected]07f54fcc2009-12-22 02:46:3088// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1889bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3290 GLuint count,
91 size_t size,
[email protected]a76b0052010-03-05 00:33:1892 unsigned int elements_per_unit,
93 uint32* dst) {
94 uint32 value;
95 if (!SafeMultiplyUint32(count, size, &value)) {
96 return false;
97 }
98 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
99 return false;
100 }
101 *dst = value;
102 return true;
[email protected]96449d2c2009-11-25 00:01:32103}
104
105// A struct to hold info about each command.
106struct CommandInfo {
107 int arg_flags; // How to handle the arguments for this command
108 int arg_count; // How many arguments are expected for this command.
109};
110
111// A table of CommandInfo for all the commands.
112const CommandInfo g_command_info[] = {
113 #define GLES2_CMD_OP(name) { \
114 name::kArgFlags, \
115 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
116
117 GLES2_COMMAND_LIST(GLES2_CMD_OP)
118
119 #undef GLES2_CMD_OP
120};
121
[email protected]6217d392010-03-25 22:08:35122// This class prevents any GL errors that occur when it is in scope from
123// being reported to the client.
124class ScopedGLErrorSuppressor {
125 public:
126 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
127 ~ScopedGLErrorSuppressor();
128 private:
129 GLES2DecoderImpl* decoder_;
130 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
131};
132
133// Temporarily changes a decoder's bound 2D texture and restore it when this
134// object goes out of scope. Also temporarily switches to using active texture
135// unit zero in case the client has changed that to something invalid.
136class ScopedTexture2DBinder {
137 public:
138 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
139 ~ScopedTexture2DBinder();
140
141 private:
142 GLES2DecoderImpl* decoder_;
143 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
144};
145
146// Temporarily changes a decoder's bound render buffer and restore it when this
147// object goes out of scope.
148class ScopedRenderBufferBinder {
149 public:
150 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
151 ~ScopedRenderBufferBinder();
152
153 private:
154 GLES2DecoderImpl* decoder_;
155 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
156};
157
158// Temporarily changes a decoder's bound frame buffer and restore it when this
159// object goes out of scope.
160class ScopedFrameBufferBinder {
161 public:
162 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
163 ~ScopedFrameBufferBinder();
164
165 private:
166 GLES2DecoderImpl* decoder_;
167 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
168};
169
[email protected]2f2d7042010-04-14 21:45:58170// Temporarily switch to a decoder's default GL context, having known default
171// state.
172class ScopedDefaultGLContext {
173 public:
174 explicit ScopedDefaultGLContext(GLES2DecoderImpl* decoder);
175 ~ScopedDefaultGLContext();
176
177 private:
178 GLES2DecoderImpl* decoder_;
179 DISALLOW_COPY_AND_ASSIGN(ScopedDefaultGLContext);
180};
181
[email protected]6217d392010-03-25 22:08:35182// Encapsulates an OpenGL texture.
183class Texture {
184 public:
185 explicit Texture(GLES2DecoderImpl* decoder);
186 ~Texture();
187
188 // Create a new render texture.
189 void Create();
190
191 // Set the initial size and format of a render texture or resize it.
192 bool AllocateStorage(const gfx::Size& size);
193
194 // Copy the contents of the currently bound frame buffer.
195 void Copy(const gfx::Size& size);
196
197 // Destroy the render texture. This must be explicitly called before
198 // destroying this object.
199 void Destroy();
200
201 GLuint id() const {
202 return id_;
203 }
204
[email protected]d37231fa2010-04-09 21:16:02205 gfx::Size size() const {
206 return size_;
207 }
208
[email protected]6217d392010-03-25 22:08:35209 private:
210 GLES2DecoderImpl* decoder_;
211 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02212 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35213 DISALLOW_COPY_AND_ASSIGN(Texture);
214};
215
216// Encapsulates an OpenGL render buffer of any format.
217class RenderBuffer {
218 public:
219 explicit RenderBuffer(GLES2DecoderImpl* decoder);
220 ~RenderBuffer();
221
222 // Create a new render buffer.
223 void Create();
224
225 // Set the initial size and format of a render buffer or resize it.
226 bool AllocateStorage(const gfx::Size& size, GLenum format);
227
228 // Destroy the render buffer. This must be explicitly called before destroying
229 // this object.
230 void Destroy();
231
232 GLuint id() const {
233 return id_;
234 }
235
236 private:
237 GLES2DecoderImpl* decoder_;
238 GLuint id_;
239 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
240};
241
242// Encapsulates an OpenGL frame buffer.
243class FrameBuffer {
244 public:
245 explicit FrameBuffer(GLES2DecoderImpl* decoder);
246 ~FrameBuffer();
247
248 // Create a new frame buffer.
249 void Create();
250
251 // Attach a color render buffer to a frame buffer.
252 void AttachRenderTexture(Texture* texture);
253
254 // Attach a depth stencil render buffer to a frame buffer. Note that
255 // this unbinds any currently bound frame buffer.
256 void AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer);
257
258 // Clear the given attached buffers.
259 void Clear(GLbitfield buffers);
260
261 // Destroy the frame buffer. This must be explicitly called before destroying
262 // this object.
263 void Destroy();
264
265 // See glCheckFramebufferStatusEXT.
266 GLenum CheckStatus();
267
268 GLuint id() const {
269 return id_;
270 }
271
272 private:
273 GLES2DecoderImpl* decoder_;
274 GLuint id_;
275 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
276};
[email protected]43f28f832010-02-03 02:28:48277// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32278
[email protected]3916c97e2010-02-25 03:20:50279GLES2Decoder::GLES2Decoder(ContextGroup* group)
280 : group_(group),
[email protected]3916c97e2010-02-25 03:20:50281 debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32282}
283
[email protected]3916c97e2010-02-25 03:20:50284GLES2Decoder::~GLES2Decoder() {
285}
286
[email protected]96449d2c2009-11-25 00:01:32287// This class implements GLES2Decoder so we don't have to expose all the GLES2
288// cmd stuff to outside this class.
[email protected]6217d392010-03-25 22:08:35289class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
290 public GLES2Decoder {
[email protected]96449d2c2009-11-25 00:01:32291 public:
[email protected]3916c97e2010-02-25 03:20:50292 explicit GLES2DecoderImpl(ContextGroup* group);
293
[email protected]07f54fcc2009-12-22 02:46:30294 // Info about Vertex Attributes. This is used to track what the user currently
295 // has bound on each Vertex Attribute so that checking can be done at
296 // glDrawXXX time.
297 class VertexAttribInfo {
298 public:
299 VertexAttribInfo()
300 : enabled_(false),
301 size_(0),
302 type_(0),
303 offset_(0),
[email protected]3916c97e2010-02-25 03:20:50304 real_stride_(0) {
[email protected]07f54fcc2009-12-22 02:46:30305 }
[email protected]3916c97e2010-02-25 03:20:50306
[email protected]07f54fcc2009-12-22 02:46:30307 // Returns true if this VertexAttrib can access index.
308 bool CanAccess(GLuint index);
309
310 void set_enabled(bool enabled) {
311 enabled_ = enabled;
312 }
313
[email protected]3916c97e2010-02-25 03:20:50314 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30315 return buffer_;
316 }
317
[email protected]8bf5a3e2010-01-29 04:21:36318 GLsizei offset() const {
319 return offset_;
320 }
321
[email protected]07f54fcc2009-12-22 02:46:30322 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50323 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30324 GLint size,
325 GLenum type,
326 GLsizei real_stride,
327 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24328 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30329 buffer_ = buffer;
330 size_ = size;
331 type_ = type;
332 real_stride_ = real_stride;
333 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50334 }
335
336 void ClearBuffer() {
337 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30338 }
339
340 private:
341 // Whether or not this attribute is enabled.
342 bool enabled_;
343
344 // number of components (1, 2, 3, 4)
345 GLint size_;
346
347 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
348 GLenum type_;
349
350 // The offset into the buffer.
351 GLsizei offset_;
352
353 // The stride that will be used to access the buffer. This is the actual
354 // stide, NOT the GL bogus stride. In other words there is never a stride
355 // of 0.
356 GLsizei real_stride_;
357
[email protected]3916c97e2010-02-25 03:20:50358 // The buffer bound to this attribute.
359 BufferManager::BufferInfo::Ref buffer_;
[email protected]07f54fcc2009-12-22 02:46:30360 };
361
[email protected]96449d2c2009-11-25 00:01:32362 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14363 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50364 unsigned int arg_count,
365 const void* args);
[email protected]96449d2c2009-11-25 00:01:32366
367 // Overridden from AsyncAPIInterface.
368 virtual const char* GetCommandName(unsigned int command_id) const;
369
370 // Overridden from GLES2Decoder.
[email protected]d37231fa2010-04-09 21:16:02371 virtual bool Initialize(GLContext* context,
[email protected]6217d392010-03-25 22:08:35372 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:02373 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35374 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32375 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35376 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]eb54a562010-01-20 21:55:18377 virtual bool MakeCurrent();
[email protected]8a837bb2010-01-05 00:21:24378 virtual uint32 GetServiceIdForTesting(uint32 client_id);
[email protected]56ac89b2010-03-17 21:16:55379 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]d37231fa2010-04-09 21:16:02380 virtual GLContext* GetGLContext() { return context_; }
[email protected]43f28f832010-02-03 02:28:48381
382 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
383
[email protected]96449d2c2009-11-25 00:01:32384 private:
[email protected]6217d392010-03-25 22:08:35385 friend class ScopedGLErrorSuppressor;
386 friend class ScopedTexture2DBinder;
387 friend class ScopedFrameBufferBinder;
388 friend class ScopedRenderBufferBinder;
[email protected]2f2d7042010-04-14 21:45:58389 friend class ScopedDefaultGLContext;
[email protected]6217d392010-03-25 22:08:35390 friend class RenderBuffer;
391 friend class FrameBuffer;
392
[email protected]3916c97e2010-02-25 03:20:50393 // State associated with each texture unit.
394 struct TextureUnit {
395 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
396
397 // The last target that was bound to this texture unit.
398 GLenum bind_target;
399
400 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
401 TextureManager::TextureInfo::Ref bound_texture_2d;
402
403 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
404 // glBindTexture
405 TextureManager::TextureInfo::Ref bound_texture_cube_map;
406 };
407
[email protected]a93bb842010-02-16 23:03:47408 friend void GLGenTexturesHelper(
409 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
410 friend void GLDeleteTexturesHelper(
411 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
412 friend void GLGenBuffersHelper(
413 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
414 friend void GLDeleteBuffersHelper(
415 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
[email protected]a25fa872010-03-25 02:57:58416 friend void GLGenFramebuffersHelper(
417 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
418 friend void GLDeleteFramebuffersHelper(
419 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
420 friend void GLGenRenderbuffersHelper(
421 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
422 friend void GLDeleteRenderbuffersHelper(
423 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
[email protected]a93bb842010-02-16 23:03:47424
[email protected]3916c97e2010-02-25 03:20:50425 // TODO(gman): Cache these pointers?
426 IdManager* id_manager() {
427 return group_->id_manager();
428 }
429
430 BufferManager* buffer_manager() {
431 return group_->buffer_manager();
432 }
433
[email protected]a25fa872010-03-25 02:57:58434 RenderbufferManager* renderbuffer_manager() {
435 return group_->renderbuffer_manager();
436 }
437
438 FramebufferManager* framebuffer_manager() {
439 return group_->framebuffer_manager();
440 }
441
[email protected]3916c97e2010-02-25 03:20:50442 ProgramManager* program_manager() {
443 return group_->program_manager();
444 }
445
446 ShaderManager* shader_manager() {
447 return group_->shader_manager();
448 }
449
450 TextureManager* texture_manager() {
451 return group_->texture_manager();
452 }
453
[email protected]6217d392010-03-25 22:08:35454 bool UpdateOffscreenFrameBufferSize();
455
[email protected]96449d2c2009-11-25 00:01:32456 // Template to help call glGenXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30457 template <void gl_gen_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32458 bool GenGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12459 DCHECK_GE(n, 0);
[email protected]8a837bb2010-01-05 00:21:24460 if (!ValidateIdsAreUnused(n, client_ids)) {
461 return false;
462 }
[email protected]96449d2c2009-11-25 00:01:32463 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30464 gl_gen_function(this, n, temp.get());
[email protected]07f54fcc2009-12-22 02:46:30465 return RegisterObjects(n, client_ids, temp.get());
[email protected]96449d2c2009-11-25 00:01:32466 }
467
468 // Template to help call glDeleteXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30469 template <void gl_delete_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32470 bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12471 DCHECK_GE(n, 0);
[email protected]96449d2c2009-11-25 00:01:32472 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30473 UnregisterObjects(n, client_ids, temp.get());
474 gl_delete_function(this, n, temp.get());
[email protected]96449d2c2009-11-25 00:01:32475 return true;
476 }
477
[email protected]8a837bb2010-01-05 00:21:24478 // Check that the given ids are not used.
479 bool ValidateIdsAreUnused(GLsizei n, const GLuint* client_ids);
480
[email protected]07f54fcc2009-12-22 02:46:30481 // Register client ids with generated service ids.
482 bool RegisterObjects(
483 GLsizei n, const GLuint* client_ids, const GLuint* service_ids);
484
485 // Unregisters client ids with service ids.
486 void UnregisterObjects(
487 GLsizei n, const GLuint* client_ids, GLuint* service_ids);
488
[email protected]a93bb842010-02-16 23:03:47489 // Creates a TextureInfo for the given texture.
[email protected]6217d392010-03-25 22:08:35490 TextureManager::TextureInfo* CreateTextureInfo(GLuint texture) {
491 return texture_manager()->CreateTextureInfo(texture);
[email protected]a93bb842010-02-16 23:03:47492 }
493
494 // Gets the texture info for the given texture. Returns NULL if none exists.
495 TextureManager::TextureInfo* GetTextureInfo(GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:50496 TextureManager::TextureInfo* info =
497 texture_manager()->GetTextureInfo(texture);
498 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47499 }
500
501 // Deletes the texture info for the given texture.
[email protected]3916c97e2010-02-25 03:20:50502 void RemoveTextureInfo(GLuint texture) {
503 texture_manager()->RemoveTextureInfo(texture);
504 }
[email protected]a93bb842010-02-16 23:03:47505
[email protected]d37231fa2010-04-09 21:16:02506 // Get the size (in pixels) of the currently bound frame buffer (either FBO
507 // or regular back buffer).
508 gfx::Size GetBoundFrameBufferSize();
509
[email protected]a93bb842010-02-16 23:03:47510 // Wrapper for CompressedTexImage2D commands.
511 error::Error DoCompressedTexImage2D(
512 GLenum target,
513 GLint level,
514 GLenum internal_format,
515 GLsizei width,
516 GLsizei height,
517 GLint border,
518 GLsizei image_size,
519 const void* data);
520
521 // Wrapper for TexImage2D commands.
522 error::Error DoTexImage2D(
523 GLenum target,
524 GLint level,
525 GLenum internal_format,
526 GLsizei width,
527 GLsizei height,
528 GLint border,
529 GLenum format,
530 GLenum type,
531 const void* pixels,
532 uint32 pixels_size);
533
534 // Creates a ProgramInfo for the given program.
535 void CreateProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50536 program_manager()->CreateProgramInfo(program);
[email protected]a93bb842010-02-16 23:03:47537 }
538
[email protected]07f54fcc2009-12-22 02:46:30539 // Gets the program info for the given program. Returns NULL if none exists.
540 // Programs that have no had glLinkProgram succesfully called on them will
541 // not exist.
[email protected]1d32bc82010-01-13 22:06:46542 ProgramManager::ProgramInfo* GetProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50543 ProgramManager::ProgramInfo* info =
544 program_manager()->GetProgramInfo(program);
545 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46546 }
[email protected]07f54fcc2009-12-22 02:46:30547
[email protected]07f54fcc2009-12-22 02:46:30548 // Deletes the program info for the given program.
[email protected]1d32bc82010-01-13 22:06:46549 void RemoveProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50550 program_manager()->RemoveProgramInfo(program);
[email protected]1d32bc82010-01-13 22:06:46551 }
[email protected]07f54fcc2009-12-22 02:46:30552
[email protected]45bf5152010-02-12 00:11:31553 // Creates a ShaderInfo for the given shader.
554 void CreateShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50555 shader_manager()->CreateShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31556 }
557
558 // Gets the shader info for the given shader. Returns NULL if none exists.
559 ShaderManager::ShaderInfo* GetShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50560 ShaderManager::ShaderInfo* info = shader_manager()->GetShaderInfo(shader);
561 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]45bf5152010-02-12 00:11:31562 }
563
564 // Deletes the shader info for the given shader.
565 void RemoveShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50566 shader_manager()->RemoveShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31567 }
568
[email protected]a93bb842010-02-16 23:03:47569 // Creates a buffer info for the given buffer.
570 void CreateBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50571 return buffer_manager()->CreateBufferInfo(buffer);
[email protected]a93bb842010-02-16 23:03:47572 }
573
[email protected]07f54fcc2009-12-22 02:46:30574 // Gets the buffer info for the given buffer.
[email protected]1d32bc82010-01-13 22:06:46575 BufferManager::BufferInfo* GetBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50576 BufferManager::BufferInfo* info = buffer_manager()->GetBufferInfo(buffer);
577 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46578 }
[email protected]07f54fcc2009-12-22 02:46:30579
[email protected]a93bb842010-02-16 23:03:47580 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
581 // on glDeleteBuffers so we can make sure the user does not try to render
582 // with deleted buffers.
583 void RemoveBufferInfo(GLuint buffer_id);
584
[email protected]a25fa872010-03-25 02:57:58585 // Creates a framebuffer info for the given framebuffer.
586 void CreateFramebufferInfo(GLuint framebuffer) {
587 return framebuffer_manager()->CreateFramebufferInfo(framebuffer);
588 }
589
590 // Gets the framebuffer info for the given framebuffer.
591 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
592 GLuint framebuffer) {
593 FramebufferManager::FramebufferInfo* info =
594 framebuffer_manager()->GetFramebufferInfo(framebuffer);
595 return (info && !info->IsDeleted()) ? info : NULL;
596 }
597
598 // Removes the framebuffer info for the given framebuffer.
599 void RemoveFramebufferInfo(GLuint framebuffer_id) {
600 framebuffer_manager()->RemoveFramebufferInfo(framebuffer_id);
601 }
602
603 // Creates a renderbuffer info for the given renderbuffer.
604 void CreateRenderbufferInfo(GLuint renderbuffer) {
605 return renderbuffer_manager()->CreateRenderbufferInfo(renderbuffer);
606 }
607
608 // Gets the renderbuffer info for the given renderbuffer.
609 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
610 GLuint renderbuffer) {
611 RenderbufferManager::RenderbufferInfo* info =
612 renderbuffer_manager()->GetRenderbufferInfo(renderbuffer);
613 return (info && !info->IsDeleted()) ? info : NULL;
614 }
615
616 // Removes the renderbuffer info for the given renderbuffer.
617 void RemoveRenderbufferInfo(GLuint renderbuffer_id) {
618 renderbuffer_manager()->RemoveRenderbufferInfo(renderbuffer_id);
619 }
620
[email protected]558847a2010-03-24 07:02:54621 error::Error GetAttribLocationHelper(
622 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
623 const std::string& name_str);
624
625 error::Error GetUniformLocationHelper(
626 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
627 const std::string& name_str);
628
[email protected]3916c97e2010-02-25 03:20:50629 // Helper for glShaderSource.
630 error::Error ShaderSourceHelper(
631 GLuint shader, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30632
[email protected]b273e432010-04-12 17:23:58633 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
634 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
635
[email protected]96449d2c2009-11-25 00:01:32636 // Wrapper for glCreateProgram
637 void CreateProgramHelper(GLuint client_id);
638
639 // Wrapper for glCreateShader
640 void CreateShaderHelper(GLenum type, GLuint client_id);
641
[email protected]3916c97e2010-02-25 03:20:50642 // Wrapper for glActiveTexture
643 void DoActiveTexture(GLenum texture_unit);
644
[email protected]96449d2c2009-11-25 00:01:32645 // Wrapper for glBindBuffer since we need to track the current targets.
646 void DoBindBuffer(GLenum target, GLuint buffer);
647
[email protected]86093972010-03-11 00:13:56648 // Wrapper for glBindFramebuffer since we need to track the current targets.
649 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
650
651 // Wrapper for glBindRenderbuffer since we need to track the current targets.
652 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
653
[email protected]a93bb842010-02-16 23:03:47654 // Wrapper for glBindTexture since we need to track the current targets.
655 void DoBindTexture(GLenum target, GLuint texture);
656
[email protected]36cef8ce2010-03-16 07:34:45657 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11658 void DoBufferData(
659 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
660
[email protected]36cef8ce2010-03-16 07:34:45661 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11662 void DoBufferSubData(
663 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
664
[email protected]36cef8ce2010-03-16 07:34:45665 // Wrapper for glCheckFramebufferStatus
666 GLenum DoCheckFramebufferStatus(GLenum target);
667
[email protected]45bf5152010-02-12 00:11:31668 // Wrapper for glCompileShader.
669 void DoCompileShader(GLuint shader);
670
[email protected]07f54fcc2009-12-22 02:46:30671 // Wrapper for glDrawArrays.
672 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
673
674 // Wrapper for glDisableVertexAttribArray.
675 void DoDisableVertexAttribArray(GLuint index);
676
677 // Wrapper for glEnableVertexAttribArray.
678 void DoEnableVertexAttribArray(GLuint index);
679
[email protected]36cef8ce2010-03-16 07:34:45680 // Wrapper for glFramebufferRenderbufffer.
681 void DoFramebufferRenderbuffer(
682 GLenum target, GLenum attachment, GLenum renderbuffertarget,
683 GLuint renderbuffer);
684
685 // Wrapper for glFramebufferTexture2D.
686 void DoFramebufferTexture2D(
687 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
688 GLint level);
689
[email protected]a93bb842010-02-16 23:03:47690 // Wrapper for glGenerateMipmap
691 void DoGenerateMipmap(GLenum target);
692
[email protected]b273e432010-04-12 17:23:58693 // Wrapper for DoGetBooleanv.
694 void DoGetBooleanv(GLenum pname, GLboolean* params);
695
696 // Wrapper for DoGetFloatv.
697 void DoGetFloatv(GLenum pname, GLfloat* params);
698
[email protected]36cef8ce2010-03-16 07:34:45699 // Wrapper for glGetFramebufferAttachmentParameteriv.
700 void DoGetFramebufferAttachmentParameteriv(
701 GLenum target, GLenum attachment, GLenum pname, GLint* params);
702
[email protected]a0c3e972010-04-21 00:49:13703 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:58704 void DoGetIntegerv(GLenum pname, GLint* params);
705
[email protected]29a9eb52010-04-13 09:04:23706 // Gets the max value in a range in a buffer.
707 GLuint DoGetMaxValueInBuffer(
708 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
709
[email protected]a0c3e972010-04-21 00:49:13710 // Wrapper for glGetProgramiv.
711 void DoGetProgramiv(
712 GLuint program_id, GLenum pname, GLint* params);
713
[email protected]36cef8ce2010-03-16 07:34:45714 // Wrapper for glRenderbufferParameteriv.
715 void DoGetRenderbufferParameteriv(
716 GLenum target, GLenum pname, GLint* params);
717
[email protected]ddd968b82010-03-02 00:44:29718 // Wrapper for glGetShaderiv
719 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
720
[email protected]45bf5152010-02-12 00:11:31721 // Wrapper for glGetShaderSource.
722 void DoGetShaderSource(
723 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst);
724
[email protected]07f54fcc2009-12-22 02:46:30725 // Wrapper for glLinkProgram
726 void DoLinkProgram(GLuint program);
727
[email protected]36cef8ce2010-03-16 07:34:45728 // Wrapper for glRenderbufferStorage.
729 void DoRenderbufferStorage(
730 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
731
[email protected]b273e432010-04-12 17:23:58732 // Wrapper for glReleaseShaderCompiler.
733 void DoReleaseShaderCompiler() { }
734
[email protected]3916c97e2010-02-25 03:20:50735 // Wrappers for glTexParameter functions.
736 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
737 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
738 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
739 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
740
741 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
742 // spec only these 2 functions can be used to set sampler uniforms.
743 void DoUniform1i(GLint location, GLint v0);
744 void DoUniform1iv(GLint location, GLsizei count, const GLint *value);
745
[email protected]07f54fcc2009-12-22 02:46:30746 // Wrapper for glUseProgram
747 void DoUseProgram(GLuint program);
748
[email protected]96449d2c2009-11-25 00:01:32749 // Gets the GLError through our wrapper.
750 GLenum GetGLError();
751
752 // Sets our wrapper for the GLError.
753 void SetGLError(GLenum error);
754
[email protected]07f54fcc2009-12-22 02:46:30755 // Copies the real GL errors to the wrapper. This is so we can
756 // make sure there are no native GL errors before calling some GL function
757 // so that on return we know any error generated was for that specific
758 // command.
759 void CopyRealGLErrorsToWrapper();
760
[email protected]6217d392010-03-25 22:08:35761 // Clear all real GL errors. This is to prevent the client from seeing any
762 // errors caused by GL calls that it was not responsible for issuing.
763 void ClearRealGLErrors();
764
[email protected]07f54fcc2009-12-22 02:46:30765 // Checks if the current program and vertex attributes are valid for drawing.
766 bool IsDrawValid(GLuint max_vertex_accessed);
767
[email protected]3916c97e2010-02-25 03:20:50768 void SetBlackTextureForNonRenderableTextures(
769 bool* has_non_renderable_textures);
770 void RestoreStateForNonRenderableTextures();
771
[email protected]07f54fcc2009-12-22 02:46:30772 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:50773 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:30774 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:50775 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
776 bound_array_buffer_ : bound_element_array_buffer_;
777 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:30778 }
779
[email protected]a93bb842010-02-16 23:03:47780 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:50781 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
782 TextureUnit& unit = texture_units_[active_texture_unit_];
783 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:47784 switch (target) {
785 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:50786 info = unit.bound_texture_2d;
787 break;
[email protected]a93bb842010-02-16 23:03:47788 case GL_TEXTURE_CUBE_MAP:
789 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
790 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
791 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
792 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
793 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
794 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:50795 info = unit.bound_texture_cube_map;
796 break;
[email protected]1aef98132010-02-23 18:00:07797 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
798 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
799 // because |texture_| is used by the FBO rendering mechanism for readback
800 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:47801 default:
802 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:50803 return NULL;
[email protected]a93bb842010-02-16 23:03:47804 }
[email protected]3916c97e2010-02-25 03:20:50805 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47806 }
807
[email protected]f7b85372010-02-03 01:11:37808 // Validates the program and location for a glGetUniform call and returns
809 // a SizeResult setup to receive the result. Returns true if glGetUniform
810 // should be called.
811 bool GetUniformSetup(
812 GLuint program, GLint location,
813 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:25814 error::Error* error, GLuint* service_id, void** result);
[email protected]f7b85372010-02-03 01:11:37815
[email protected]86093972010-03-11 00:13:56816 bool ValidateGLenumCompressedTextureInternalFormat(GLenum format);
817
[email protected]96449d2c2009-11-25 00:01:32818 // Generate a member function prototype for each command in an automated and
819 // typesafe way.
820 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:14821 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:19822 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:32823 const gles2::name& args); \
824
825 GLES2_COMMAND_LIST(GLES2_CMD_OP)
826
827 #undef GLES2_CMD_OP
828
[email protected]2f2d7042010-04-14 21:45:58829 // The GL context this decoder renders to on behalf of the client.
[email protected]d37231fa2010-04-09 21:16:02830 GLContext* context_;
831
[email protected]2f2d7042010-04-14 21:45:58832 // A GLContext that is kept in its default state. It is used to perform
833 // operations that should not be dependent on client set GLContext state, like
834 // clearing a render buffer when it is created.
835 // TODO(apatrick): Decoders in the same ContextGroup could potentially share
836 // the same default GL context.
[email protected]4bedba72010-04-20 22:08:54837 scoped_ptr<GLContext> default_context_;
[email protected]2f2d7042010-04-14 21:45:58838
[email protected]6217d392010-03-25 22:08:35839 // A parent decoder can access this decoders saved offscreen frame buffer.
840 // The parent pointer is reset if the parent is destroyed.
841 base::WeakPtr<GLES2DecoderImpl> parent_;
842
843 // Width and height to which an offscreen frame buffer should be resized on
844 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:02845 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:35846
[email protected]96449d2c2009-11-25 00:01:32847 // Current GL error bits.
848 uint32 error_bits_;
849
[email protected]96449d2c2009-11-25 00:01:32850 // Util to help with GL.
851 GLES2Util util_;
852
853 // pack alignment as last set by glPixelStorei
854 GLint pack_alignment_;
855
856 // unpack alignment as last set by glPixelStorei
857 GLint unpack_alignment_;
858
859 // The currently bound array buffer. If this is 0 it is illegal to call
860 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:50861 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:32862
863 // The currently bound element array buffer. If this is 0 it is illegal
864 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:50865 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:30866
867 // Info for each vertex attribute saved so we can check at glDrawXXX time
868 // if it is safe to draw.
869 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
870
[email protected]3916c97e2010-02-25 03:20:50871 // Current active texture by 0 - n index.
872 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
873 // be 2.
874 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:30875
[email protected]3916c97e2010-02-25 03:20:50876 // Which textures are bound to texture units through glActiveTexture.
877 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:47878
[email protected]3916c97e2010-02-25 03:20:50879 // Black (0,0,0,0) textures for when non-renderable textures are used.
880 // NOTE: There is no corresponding TextureInfo for these textures.
881 // TextureInfos are only for textures the client side can access.
882 GLuint black_2d_texture_id_;
883 GLuint black_cube_texture_id_;
[email protected]45bf5152010-02-12 00:11:31884
[email protected]1d32bc82010-01-13 22:06:46885 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:50886 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:30887
[email protected]86093972010-03-11 00:13:56888 // The currently bound framebuffer
[email protected]051b1372010-04-12 02:42:08889 FramebufferManager::FramebufferInfo::Ref bound_framebuffer_;
[email protected]86093972010-03-11 00:13:56890
891 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:08892 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:56893
[email protected]96449d2c2009-11-25 00:01:32894 bool anti_aliased_;
895
[email protected]6217d392010-03-25 22:08:35896 // The offscreen frame buffer that the client renders to.
897 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
898 scoped_ptr<Texture> offscreen_target_color_texture_;
899 scoped_ptr<RenderBuffer> offscreen_target_depth_stencil_render_buffer_;
900
901 // The copy that is saved when SwapBuffers is called.
902 scoped_ptr<Texture> offscreen_saved_color_texture_;
903
[email protected]43f28f832010-02-03 02:28:48904 scoped_ptr<Callback0::Type> swap_buffers_callback_;
905
[email protected]96449d2c2009-11-25 00:01:32906 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
907};
908
[email protected]6217d392010-03-25 22:08:35909ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
910 : decoder_(decoder) {
911 decoder_->CopyRealGLErrorsToWrapper();
912}
913
914ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
915 decoder_->ClearRealGLErrors();
916}
917
918ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
919 GLuint id)
920 : decoder_(decoder) {
921 ScopedGLErrorSuppressor suppressor(decoder_);
922
923 // TODO(apatrick): Check if there are any other states that need to be reset
924 // before binding a new texture.
925 glActiveTexture(GL_TEXTURE0);
926 glBindTexture(GL_TEXTURE_2D, id);
927}
928
929ScopedTexture2DBinder::~ScopedTexture2DBinder() {
930 ScopedGLErrorSuppressor suppressor(decoder_);
931 GLES2DecoderImpl::TextureUnit& info = decoder_->texture_units_[0];
932 GLuint last_id;
933 if (info.bound_texture_2d)
934 last_id = info.bound_texture_2d->texture_id();
935 else
936 last_id = 0;
937
938 glBindTexture(GL_TEXTURE_2D, last_id);
939 glActiveTexture(GL_TEXTURE0 + decoder_->active_texture_unit_);
940}
941
942ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
943 GLuint id)
944 : decoder_(decoder) {
945 ScopedGLErrorSuppressor suppressor(decoder_);
946 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
947}
948
949ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
950 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:08951 glBindRenderbufferEXT(
952 GL_RENDERBUFFER,
953 decoder_->bound_renderbuffer_ ?
954 decoder_->bound_renderbuffer_->renderbuffer_id() : 0);
[email protected]6217d392010-03-25 22:08:35955}
956
957ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
958 GLuint id)
959 : decoder_(decoder) {
960 ScopedGLErrorSuppressor suppressor(decoder_);
961 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
962}
963
964ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
965 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:08966 FramebufferManager::FramebufferInfo* info =
967 decoder_->bound_framebuffer_.get();
968 GLuint framebuffer_id = info ? info->framebuffer_id() : 0;
969 if (framebuffer_id == 0 &&
[email protected]6217d392010-03-25 22:08:35970 decoder_->offscreen_target_frame_buffer_.get()) {
971 glBindFramebufferEXT(GL_FRAMEBUFFER,
972 decoder_->offscreen_target_frame_buffer_->id());
973 } else {
[email protected]051b1372010-04-12 02:42:08974 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_id);
[email protected]6217d392010-03-25 22:08:35975 }
976}
977
[email protected]2f2d7042010-04-14 21:45:58978ScopedDefaultGLContext::ScopedDefaultGLContext(GLES2DecoderImpl* decoder)
979 : decoder_(decoder) {
980 decoder_->default_context_->MakeCurrent();
981}
982
983ScopedDefaultGLContext::~ScopedDefaultGLContext() {
984 decoder_->context_->MakeCurrent();
985}
986
[email protected]6217d392010-03-25 22:08:35987Texture::Texture(GLES2DecoderImpl* decoder)
988 : decoder_(decoder),
989 id_(0) {
990}
991
992Texture::~Texture() {
993 // This does not destroy the render texture because that would require that
994 // the associated GL context was current. Just check that it was explicitly
995 // destroyed.
996 DCHECK_EQ(id_, 0u);
997}
998
999void Texture::Create() {
1000 ScopedGLErrorSuppressor suppressor(decoder_);
1001 Destroy();
1002 glGenTextures(1, &id_);
1003}
1004
1005bool Texture::AllocateStorage(const gfx::Size& size) {
1006 DCHECK_NE(id_, 0u);
1007 ScopedGLErrorSuppressor suppressor(decoder_);
1008 ScopedTexture2DBinder binder(decoder_, id_);
1009 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1010 glTexParameteri(
1011 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1012 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1013 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1014 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
1015
1016 glTexImage2D(GL_TEXTURE_2D,
1017 0, // mip level
1018 GL_RGBA,
1019 size.width(),
1020 size.height(),
1021 0, // border
1022 GL_RGBA,
1023 GL_UNSIGNED_BYTE,
1024 NULL);
1025
[email protected]d37231fa2010-04-09 21:16:021026 size_ = size;
1027
[email protected]6217d392010-03-25 22:08:351028 return glGetError() == GL_NO_ERROR;
1029}
1030
1031void Texture::Copy(const gfx::Size& size) {
1032 DCHECK_NE(id_, 0u);
1033 ScopedGLErrorSuppressor suppressor(decoder_);
1034 ScopedTexture2DBinder binder(decoder_, id_);
1035 glCopyTexImage2D(GL_TEXTURE_2D,
1036 0, // level
1037 GL_RGBA,
1038 0, 0,
1039 size.width(),
1040 size.height(),
1041 0); // border
1042}
1043
1044void Texture::Destroy() {
1045 if (id_ != 0) {
1046 ScopedGLErrorSuppressor suppressor(decoder_);
1047 glDeleteTextures(1, &id_);
1048 id_ = 0;
1049 }
1050}
1051
1052RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1053 : decoder_(decoder),
1054 id_(0) {
1055}
1056
1057RenderBuffer::~RenderBuffer() {
1058 // This does not destroy the render buffer because that would require that
1059 // the associated GL context was current. Just check that it was explicitly
1060 // destroyed.
1061 DCHECK_EQ(id_, 0u);
1062}
1063
1064void RenderBuffer::Create() {
1065 ScopedGLErrorSuppressor suppressor(decoder_);
1066 Destroy();
1067 glGenRenderbuffersEXT(1, &id_);
1068}
1069
1070bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format) {
1071 ScopedGLErrorSuppressor suppressor(decoder_);
1072 ScopedRenderBufferBinder binder(decoder_, id_);
1073 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1074 format,
1075 size.width(),
1076 size.height());
1077 return glGetError() == GL_NO_ERROR;
1078}
1079
1080void RenderBuffer::Destroy() {
1081 if (id_ != 0) {
1082 ScopedGLErrorSuppressor suppressor(decoder_);
1083 glDeleteRenderbuffersEXT(1, &id_);
1084 id_ = 0;
1085 }
1086}
1087
1088FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1089 : decoder_(decoder),
1090 id_(0) {
1091}
1092
1093FrameBuffer::~FrameBuffer() {
1094 // This does not destroy the frame buffer because that would require that
1095 // the associated GL context was current. Just check that it was explicitly
1096 // destroyed.
1097 DCHECK_EQ(id_, 0u);
1098}
1099
1100void FrameBuffer::Create() {
1101 ScopedGLErrorSuppressor suppressor(decoder_);
1102 Destroy();
1103 glGenFramebuffersEXT(1, &id_);
1104}
1105
1106void FrameBuffer::AttachRenderTexture(Texture* texture) {
1107 DCHECK_NE(id_, 0u);
1108 ScopedGLErrorSuppressor suppressor(decoder_);
1109 ScopedFrameBufferBinder binder(decoder_, id_);
1110 GLuint attach_id = texture ? texture->id() : 0;
1111 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1112 GL_COLOR_ATTACHMENT0,
1113 GL_TEXTURE_2D,
1114 attach_id,
1115 0);
1116}
1117
1118void FrameBuffer::AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer) {
1119 DCHECK_NE(id_, 0u);
1120 ScopedGLErrorSuppressor suppressor(decoder_);
1121 ScopedFrameBufferBinder binder(decoder_, id_);
1122 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1123 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
1124 GL_DEPTH_ATTACHMENT,
1125 GL_RENDERBUFFER,
1126 attach_id);
1127 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
1128 GL_STENCIL_ATTACHMENT,
1129 GL_RENDERBUFFER,
1130 attach_id);
1131}
1132
1133void FrameBuffer::Clear(GLbitfield buffers) {
1134 ScopedGLErrorSuppressor suppressor(decoder_);
1135 ScopedFrameBufferBinder binder(decoder_, id_);
1136 glClear(buffers);
1137}
1138
1139void FrameBuffer::Destroy() {
1140 if (id_ != 0) {
1141 ScopedGLErrorSuppressor suppressor(decoder_);
1142 glDeleteFramebuffersEXT(1, &id_);
1143 id_ = 0;
1144 }
1145}
1146
1147GLenum FrameBuffer::CheckStatus() {
1148 DCHECK_NE(id_, 0u);
1149 ScopedGLErrorSuppressor suppressor(decoder_);
1150 ScopedFrameBufferBinder binder(decoder_, id_);
1151 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1152}
1153
[email protected]3916c97e2010-02-25 03:20:501154GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1155 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321156}
1157
[email protected]3916c97e2010-02-25 03:20:501158GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
1159 : GLES2Decoder(group),
[email protected]d37231fa2010-04-09 21:16:021160 context_(NULL),
[email protected]96449d2c2009-11-25 00:01:321161 error_bits_(0),
1162 util_(0), // TODO(gman): Set to actual num compress texture formats.
1163 pack_alignment_(4),
1164 unpack_alignment_(4),
[email protected]3916c97e2010-02-25 03:20:501165 active_texture_unit_(0),
1166 black_2d_texture_id_(0),
1167 black_cube_texture_id_(0),
[email protected]96449d2c2009-11-25 00:01:321168 anti_aliased_(false) {
1169}
1170
[email protected]d37231fa2010-04-09 21:16:021171bool GLES2DecoderImpl::Initialize(GLContext* context,
[email protected]6217d392010-03-25 22:08:351172 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:021173 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:351174 uint32 parent_client_texture_id) {
[email protected]4bedba72010-04-20 22:08:541175 DCHECK(context);
[email protected]d37231fa2010-04-09 21:16:021176 DCHECK(!context_);
1177 context_ = context;
1178
[email protected]2f2d7042010-04-14 21:45:581179 // Create a GL context that is kept in a default state and shares a namespace
1180 // with the main GL context.
[email protected]4bedba72010-04-20 22:08:541181 default_context_.reset(GLContext::CreateOffscreenGLContext(
1182 context_->GetHandle()));
1183 if (!default_context_.get()) {
[email protected]2f2d7042010-04-14 21:45:581184 Destroy();
1185 return false;
1186 }
1187
[email protected]6217d392010-03-25 22:08:351188 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021189 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351190 if (parent)
1191 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1192
[email protected]246a70452010-03-05 21:53:501193 if (!MakeCurrent()) {
1194 Destroy();
1195 return false;
[email protected]eb54a562010-01-20 21:55:181196 }
1197
[email protected]246a70452010-03-05 21:53:501198 CHECK_GL_ERROR();
1199
1200 if (!group_->Initialize()) {
1201 Destroy();
1202 return false;
1203 }
1204
1205 vertex_attrib_infos_.reset(
1206 new VertexAttribInfo[group_->max_vertex_attribs()]);
1207 texture_units_.reset(
1208 new TextureUnit[group_->max_texture_units()]);
1209 GLuint ids[2];
1210 glGenTextures(2, ids);
1211 // Make black textures for replacing non-renderable textures.
1212 black_2d_texture_id_ = ids[0];
1213 black_cube_texture_id_ = ids[1];
1214 static int8 black[] = {0, 0, 0, 0};
1215 glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
1216 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
1217 GL_UNSIGNED_BYTE, black);
1218 glBindTexture(GL_TEXTURE_2D, 0);
1219 glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
1220 static GLenum faces[] = {
1221 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
1222 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
1223 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
1224 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
1225 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
1226 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
1227 };
1228 for (size_t ii = 0; ii < arraysize(faces); ++ii) {
1229 glTexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA,
1230 GL_UNSIGNED_BYTE, black);
1231 }
1232 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
1233 CHECK_GL_ERROR();
1234
[email protected]d37231fa2010-04-09 21:16:021235#if !defined(UNIT_TEST)
1236 if (context_->IsOffscreen()) {
[email protected]6217d392010-03-25 22:08:351237 // Create the target frame buffer. This is the one that the client renders
1238 // directly to.
1239 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1240 offscreen_target_frame_buffer_->Create();
1241 offscreen_target_color_texture_.reset(new Texture(this));
1242 offscreen_target_color_texture_->Create();
1243 offscreen_target_depth_stencil_render_buffer_.reset(
1244 new RenderBuffer(this));
1245 offscreen_target_depth_stencil_render_buffer_->Create();
1246
1247 // Create the saved offscreen texture. The target frame buffer is copied
1248 // here when SwapBuffers is called.
1249 offscreen_saved_color_texture_.reset(new Texture(this));
1250 offscreen_saved_color_texture_->Create();
1251
[email protected]6217d392010-03-25 22:08:351252 // Map the ID of the saved offscreen texture into the parent so that
1253 // it can reference it.
1254 if (parent_) {
1255 GLuint service_id = offscreen_saved_color_texture_->id();
1256 parent_->id_manager()->AddMapping(parent_client_texture_id,
1257 service_id);
1258 TextureManager::TextureInfo* info =
1259 parent_->CreateTextureInfo(service_id);
1260 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
1261 }
1262
1263 // Allocate the render buffers at their initial size and check the status
1264 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021265 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351266 if (!UpdateOffscreenFrameBufferSize()) {
1267 DLOG(ERROR) << "Could not allocate offscreen buffer storage.";
1268 Destroy();
1269 return false;
1270 }
1271
1272 // Bind to the new default frame buffer (the offscreen target frame buffer).
1273 // This should now be associated with ID zero.
1274 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
1275 }
[email protected]d37231fa2010-04-09 21:16:021276#endif // UNIT_TEST
[email protected]6217d392010-03-25 22:08:351277
[email protected]76a0ee102010-04-07 21:03:041278#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1279 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1280 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1281 // isn't well documented; it was discovered in the Khronos OpenGL ES
1282 // mailing list archives.
1283 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
1284#endif
1285
[email protected]246a70452010-03-05 21:53:501286 return true;
[email protected]96449d2c2009-11-25 00:01:321287}
1288
[email protected]07f54fcc2009-12-22 02:46:301289// These commands convert from c calls to local os calls.
1290void GLGenBuffersHelper(
[email protected]a93bb842010-02-16 23:03:471291 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301292 glGenBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:471293 // TODO(gman): handle error
1294 for (GLsizei ii = 0; ii < n; ++ii) {
1295 decoder->CreateBufferInfo(ids[ii]);
1296 }
[email protected]07f54fcc2009-12-22 02:46:301297}
1298
1299void GLGenFramebuffersHelper(
[email protected]a25fa872010-03-25 02:57:581300 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301301 glGenFramebuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:581302 // TODO(gman): handle error
1303 for (GLsizei ii = 0; ii < n; ++ii) {
1304 decoder->CreateFramebufferInfo(ids[ii]);
1305 }
[email protected]07f54fcc2009-12-22 02:46:301306}
1307
1308void GLGenRenderbuffersHelper(
[email protected]a25fa872010-03-25 02:57:581309 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301310 glGenRenderbuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:581311 // TODO(gman): handle error
1312 for (GLsizei ii = 0; ii < n; ++ii) {
1313 decoder->CreateRenderbufferInfo(ids[ii]);
1314 }
[email protected]07f54fcc2009-12-22 02:46:301315}
1316
1317void GLGenTexturesHelper(
[email protected]a93bb842010-02-16 23:03:471318 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301319 glGenTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:471320 // TODO(gman): handle error
1321 for (GLsizei ii = 0; ii < n; ++ii) {
1322 decoder->CreateTextureInfo(ids[ii]);
1323 }
[email protected]07f54fcc2009-12-22 02:46:301324}
1325
1326void GLDeleteBuffersHelper(
1327 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
1328 glDeleteBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:471329 // TODO(gman): handle error
[email protected]07f54fcc2009-12-22 02:46:301330 for (GLsizei ii = 0; ii < n; ++ii) {
1331 decoder->RemoveBufferInfo(ids[ii]);
1332 }
1333}
1334
1335void GLDeleteFramebuffersHelper(
[email protected]a25fa872010-03-25 02:57:581336 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301337 glDeleteFramebuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:581338 // TODO(gman): handle error
1339 for (GLsizei ii = 0; ii < n; ++ii) {
1340 decoder->RemoveFramebufferInfo(ids[ii]);
1341 }
[email protected]07f54fcc2009-12-22 02:46:301342}
1343
1344void GLDeleteRenderbuffersHelper(
[email protected]a25fa872010-03-25 02:57:581345 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301346 glDeleteRenderbuffersEXT(n, ids);
[email protected]a25fa872010-03-25 02:57:581347 // TODO(gman): handle error
1348 for (GLsizei ii = 0; ii < n; ++ii) {
1349 decoder->RemoveRenderbufferInfo(ids[ii]);
1350 }
[email protected]07f54fcc2009-12-22 02:46:301351}
1352
1353void GLDeleteTexturesHelper(
[email protected]a93bb842010-02-16 23:03:471354 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:301355 glDeleteTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:471356 // TODO(gman): handle error
1357 for (GLsizei ii = 0; ii < n; ++ii) {
1358 decoder->RemoveTextureInfo(ids[ii]);
1359 }
[email protected]07f54fcc2009-12-22 02:46:301360}
1361
[email protected]43f28f832010-02-03 02:28:481362// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:321363
[email protected]eb54a562010-01-20 21:55:181364bool GLES2DecoderImpl::MakeCurrent() {
1365#if defined(UNIT_TEST)
1366 return true;
[email protected]eb54a562010-01-20 21:55:181367#else
[email protected]d37231fa2010-04-09 21:16:021368 return context_->MakeCurrent();
[email protected]eb54a562010-01-20 21:55:181369#endif
1370}
1371
[email protected]8a837bb2010-01-05 00:21:241372uint32 GLES2DecoderImpl::GetServiceIdForTesting(uint32 client_id) {
1373#if defined(UNIT_TEST)
1374 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501375 bool result = id_manager()->GetServiceId(client_id, &service_id);
[email protected]8a837bb2010-01-05 00:21:241376 return result ? service_id : 0u;
1377#else
1378 DCHECK(false);
1379 return 0u;
1380#endif
1381}
1382
1383bool GLES2DecoderImpl::ValidateIdsAreUnused(
1384 GLsizei n, const GLuint* client_ids) {
1385 for (GLsizei ii = 0; ii < n; ++ii) {
1386 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501387 if (id_manager()->GetServiceId(client_ids[ii], &service_id)) {
[email protected]8a837bb2010-01-05 00:21:241388 return false;
1389 }
1390 }
1391 return true;
1392}
1393
[email protected]07f54fcc2009-12-22 02:46:301394bool GLES2DecoderImpl::RegisterObjects(
1395 GLsizei n, const GLuint* client_ids, const GLuint* service_ids) {
1396 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501397 if (!id_manager()->AddMapping(client_ids[ii], service_ids[ii])) {
[email protected]8a837bb2010-01-05 00:21:241398 NOTREACHED();
1399 return false;
[email protected]07f54fcc2009-12-22 02:46:301400 }
1401 }
1402 return true;
1403}
1404
1405void GLES2DecoderImpl::UnregisterObjects(
1406 GLsizei n, const GLuint* client_ids, GLuint* service_ids) {
[email protected]07f54fcc2009-12-22 02:46:301407 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501408 if (id_manager()->GetServiceId(client_ids[ii], &service_ids[ii])) {
1409 id_manager()->RemoveMapping(client_ids[ii], service_ids[ii]);
[email protected]07f54fcc2009-12-22 02:46:301410 } else {
1411 service_ids[ii] = 0;
1412 }
1413 }
1414}
1415
[email protected]d37231fa2010-04-09 21:16:021416gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() {
1417 if (bound_framebuffer_ != 0) {
1418 int width = 0;
1419 int height = 0;
[email protected]246a70452010-03-05 21:53:501420
[email protected]d37231fa2010-04-09 21:16:021421 // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
1422 // stencil.
1423 GLint fb_type = 0;
1424 glGetFramebufferAttachmentParameterivEXT(
1425 GL_FRAMEBUFFER,
1426 GL_COLOR_ATTACHMENT0,
1427 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
1428 &fb_type);
1429 switch (fb_type) {
1430 case GL_RENDERBUFFER:
1431 {
1432 GLint renderbuffer_id = 0;
1433 glGetFramebufferAttachmentParameterivEXT(
1434 GL_FRAMEBUFFER,
1435 GL_COLOR_ATTACHMENT0,
1436 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1437 &renderbuffer_id);
1438 if (renderbuffer_id != 0) {
1439 glGetRenderbufferParameterivEXT(
1440 GL_RENDERBUFFER,
1441 GL_RENDERBUFFER_WIDTH,
1442 &width);
1443 glGetRenderbufferParameterivEXT(
1444 GL_RENDERBUFFER,
1445 GL_RENDERBUFFER_HEIGHT,
1446 &height);
1447 }
1448 break;
1449 }
1450 case GL_TEXTURE:
1451 {
1452 GLint texture_id = 0;
1453 glGetFramebufferAttachmentParameterivEXT(
1454 GL_FRAMEBUFFER,
1455 GL_COLOR_ATTACHMENT0,
1456 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1457 &texture_id);
1458 if (texture_id != 0) {
1459 TextureManager::TextureInfo* texture_info =
1460 GetTextureInfo(texture_id);
1461 if (texture_info) {
1462 GLint level = 0;
1463 GLint face = 0;
1464 glGetFramebufferAttachmentParameterivEXT(
1465 GL_FRAMEBUFFER,
1466 GL_COLOR_ATTACHMENT0,
1467 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
1468 &level);
1469 glGetFramebufferAttachmentParameterivEXT(
1470 GL_FRAMEBUFFER,
1471 GL_COLOR_ATTACHMENT0,
1472 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
1473 &face);
1474 texture_info->GetLevelSize(
1475 face ? face : GL_TEXTURE_2D, level, &width, &height);
1476 }
1477 }
1478 break;
1479 }
1480 default:
1481 // unknown so assume width and height are zero.
1482 break;
[email protected]246a70452010-03-05 21:53:501483 }
1484
[email protected]d37231fa2010-04-09 21:16:021485 return gfx::Size(width, height);
1486 } else if (offscreen_target_color_texture_.get()) {
1487 return offscreen_target_color_texture_->size();
[email protected]6217d392010-03-25 22:08:351488 } else {
[email protected]246a70452010-03-05 21:53:501489#if defined(UNIT_TEST)
[email protected]d37231fa2010-04-09 21:16:021490 return gfx::Size(INT_MAX, INT_MAX);
1491#else
1492 return context_->GetSize();
[email protected]246a70452010-03-05 21:53:501493#endif
[email protected]d37231fa2010-04-09 21:16:021494 }
[email protected]246a70452010-03-05 21:53:501495}
1496
[email protected]6217d392010-03-25 22:08:351497bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]d37231fa2010-04-09 21:16:021498 if (offscreen_target_color_texture_->size() == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:351499 return true;
1500
[email protected]2f2d7042010-04-14 21:45:581501 if (parent_) {
1502 // Create the saved offscreen color texture (only accessible to parent).
1503 offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
1504
1505 // Attach the saved offscreen color texture to a frame buffer so we can
1506 // clear it with glClear.
1507 offscreen_target_frame_buffer_->AttachRenderTexture(
1508 offscreen_saved_color_texture_.get());
1509 if (offscreen_target_frame_buffer_->CheckStatus() !=
1510 GL_FRAMEBUFFER_COMPLETE) {
1511 return false;
1512 }
1513
1514#if !defined(UNIT_TEST)
1515 // Clear the saved offscreen color texture. Use default GL context
1516 // to ensure clear is not affected by client set state.
1517 {
1518 ScopedDefaultGLContext scoped_context(this);
1519 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
1520 offscreen_target_frame_buffer_->id());
1521 glClear(GL_COLOR_BUFFER_BIT);
1522 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1523
1524 if (glGetError() != GL_NO_ERROR)
1525 return false;
1526 }
1527#endif
1528 }
1529
[email protected]6217d392010-03-25 22:08:351530 // Reallocate the offscreen target buffers.
[email protected]d37231fa2010-04-09 21:16:021531 if (!offscreen_target_color_texture_->AllocateStorage(
1532 pending_offscreen_size_)) {
[email protected]6217d392010-03-25 22:08:351533 return false;
1534 }
1535
1536 if (!offscreen_target_depth_stencil_render_buffer_->AllocateStorage(
[email protected]d37231fa2010-04-09 21:16:021537 pending_offscreen_size_, GL_DEPTH24_STENCIL8)) {
[email protected]6217d392010-03-25 22:08:351538 return false;
1539 }
1540
[email protected]2f2d7042010-04-14 21:45:581541 // Attach the offscreen target buffers to the target frame buffer.
[email protected]6217d392010-03-25 22:08:351542 offscreen_target_frame_buffer_->AttachRenderTexture(
1543 offscreen_target_color_texture_.get());
1544 offscreen_target_frame_buffer_->AttachDepthStencilRenderBuffer(
1545 offscreen_target_depth_stencil_render_buffer_.get());
1546 if (offscreen_target_frame_buffer_->CheckStatus() !=
1547 GL_FRAMEBUFFER_COMPLETE) {
1548 return false;
1549 }
1550
[email protected]2f2d7042010-04-14 21:45:581551#if !defined(UNIT_TEST)
1552 // Clear offscreen frame buffer to its initial state. Use default GL context
1553 // to ensure clear is not affected by client set state.
1554 {
1555 ScopedDefaultGLContext scoped_context(this);
1556 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
1557 offscreen_target_frame_buffer_->id());
1558 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1559 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1560
1561 if (glGetError() != GL_NO_ERROR)
1562 return false;
1563 }
1564#endif
1565
[email protected]6217d392010-03-25 22:08:351566 if (parent_) {
[email protected]d37231fa2010-04-09 21:16:021567 // Create the saved offscreen color texture (only accessible to parent).
1568 offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
1569
[email protected]2f2d7042010-04-14 21:45:581570 // Update the info about the offscreen saved color texture in the parent.
1571 // The reference to the parent is a weak pointer and will become null if the
1572 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:351573 GLuint service_id = offscreen_saved_color_texture_->id();
1574
1575 TextureManager::TextureInfo* info =
1576 parent_->texture_manager()->GetTextureInfo(service_id);
1577 DCHECK(info);
1578
1579 info->SetLevelInfo(GL_TEXTURE_2D,
1580 0, // level
1581 GL_RGBA,
[email protected]d37231fa2010-04-09 21:16:021582 pending_offscreen_size_.width(),
1583 pending_offscreen_size_.height(),
[email protected]6217d392010-03-25 22:08:351584 1, // depth
1585 0, // border
1586 GL_RGBA,
1587 GL_UNSIGNED_BYTE);
1588 }
1589
[email protected]6217d392010-03-25 22:08:351590 return true;
1591}
1592
[email protected]43f28f832010-02-03 02:28:481593void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
1594 swap_buffers_callback_.reset(callback);
1595}
1596
[email protected]96449d2c2009-11-25 00:01:321597void GLES2DecoderImpl::Destroy() {
[email protected]4bedba72010-04-20 22:08:541598 if (context_) {
1599 MakeCurrent();
[email protected]6217d392010-03-25 22:08:351600
[email protected]4bedba72010-04-20 22:08:541601 // Remove the saved frame buffer mapping from the parent decoder. The
1602 // parent pointer is a weak pointer so it will be null if the parent has
1603 // already been destroyed.
1604 if (parent_) {
1605 // First check the texture has been mapped into the parent. This might not
1606 // be the case if initialization failed midway through.
1607 GLuint service_id = offscreen_saved_color_texture_->id();
1608 GLuint client_id;
1609 if (parent_->id_manager()->GetClientId(service_id, &client_id)) {
1610 parent_->texture_manager()->RemoveTextureInfo(service_id);
1611 parent_->id_manager()->RemoveMapping(client_id, service_id);
1612 }
[email protected]6217d392010-03-25 22:08:351613 }
[email protected]6217d392010-03-25 22:08:351614
[email protected]4bedba72010-04-20 22:08:541615 if (offscreen_target_frame_buffer_.get()) {
1616 offscreen_target_frame_buffer_->Destroy();
1617 offscreen_target_frame_buffer_.reset();
1618 }
[email protected]6217d392010-03-25 22:08:351619
[email protected]4bedba72010-04-20 22:08:541620 if (offscreen_target_color_texture_.get()) {
1621 offscreen_target_color_texture_->Destroy();
1622 offscreen_target_color_texture_.reset();
1623 }
[email protected]6217d392010-03-25 22:08:351624
[email protected]4bedba72010-04-20 22:08:541625 if (offscreen_target_depth_stencil_render_buffer_.get()) {
1626 offscreen_target_depth_stencil_render_buffer_->Destroy();
1627 offscreen_target_depth_stencil_render_buffer_.reset();
1628 }
[email protected]6217d392010-03-25 22:08:351629
[email protected]4bedba72010-04-20 22:08:541630 if (offscreen_saved_color_texture_.get()) {
1631 offscreen_saved_color_texture_->Destroy();
1632 offscreen_saved_color_texture_.reset();
1633 }
[email protected]d37231fa2010-04-09 21:16:021634 }
[email protected]2f2d7042010-04-14 21:45:581635
1636 if (default_context_.get()) {
1637 default_context_->Destroy();
1638 default_context_.reset();
1639 }
[email protected]96449d2c2009-11-25 00:01:321640}
1641
[email protected]6217d392010-03-25 22:08:351642void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
1643 // We can't resize the render buffers immediately because there might be a
1644 // partial frame rendered into them and we don't want the tail end of that
1645 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021646 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351647}
1648
[email protected]96449d2c2009-11-25 00:01:321649const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
1650 if (command_id > kStartPoint && command_id < kNumCommands) {
1651 return gles2::GetCommandName(static_cast<CommandId>(command_id));
1652 }
1653 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
1654}
1655
1656// Decode command with its arguments, and call the corresponding GL function.
1657// Note: args is a pointer to the command buffer. As such, it could be changed
1658// by a (malicious) client at any time, so if validation has to happen, it
1659// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:141660error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:321661 unsigned int command,
1662 unsigned int arg_count,
1663 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:141664 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191665 if (debug()) {
1666 // TODO(gman): Change output to something useful for NaCl.
[email protected]b9849abf2009-11-25 19:13:191667 printf("cmd: %s\n", GetCommandName(command));
1668 }
[email protected]96449d2c2009-11-25 00:01:321669 unsigned int command_index = command - kStartPoint - 1;
1670 if (command_index < arraysize(g_command_info)) {
1671 const CommandInfo& info = g_command_info[command_index];
1672 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
1673 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
1674 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:191675 uint32 immediate_data_size =
1676 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:321677 switch (command) {
1678 #define GLES2_CMD_OP(name) \
1679 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:191680 result = Handle ## name( \
1681 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321682 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:191683 break; \
[email protected]96449d2c2009-11-25 00:01:321684
1685 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:321686 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:381687 }
1688 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:301689 GLenum error;
1690 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:381691 // TODO(gman): Change output to something useful for NaCl.
[email protected]07f54fcc2009-12-22 02:46:301692 SetGLError(error);
[email protected]bf0985e2009-12-17 03:04:381693 printf("GL ERROR b4: %s\n", GetCommandName(command));
[email protected]b9849abf2009-11-25 19:13:191694 }
[email protected]96449d2c2009-11-25 00:01:321695 }
1696 } else {
[email protected]f7a64ee2010-02-01 22:24:141697 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:321698 }
[email protected]b9849abf2009-11-25 19:13:191699 } else {
1700 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:321701 }
[email protected]b9849abf2009-11-25 19:13:191702 return result;
[email protected]96449d2c2009-11-25 00:01:321703}
1704
[email protected]3916c97e2010-02-25 03:20:501705void GLES2DecoderImpl::RemoveBufferInfo(GLuint buffer_id) {
1706 buffer_manager()->RemoveBufferInfo(buffer_id);
1707 // TODO(gman): See if we can remove the rest of this function as
1708 // buffers are now reference counted and have a "IsDeleted" function.
1709 if (bound_array_buffer_ && bound_array_buffer_->buffer_id() == buffer_id) {
1710 bound_array_buffer_ = NULL;
1711 }
1712 if (bound_element_array_buffer_ &&
1713 bound_element_array_buffer_->buffer_id() == buffer_id) {
1714 bound_element_array_buffer_ = NULL;
1715 }
1716
1717 // go through VertexAttribInfo and update any info that references the buffer.
1718 for (GLuint ii = 0; ii < group_->max_vertex_attribs(); ++ii) {
1719 VertexAttribInfo& info = vertex_attrib_infos_[ii];
1720 if (info.buffer() && info.buffer()->buffer_id() == buffer_id) {
1721 info.ClearBuffer();
1722 }
1723 }
1724}
1725
[email protected]96449d2c2009-11-25 00:01:321726void GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
1727 // TODO(gman): verify client_id is unused.
1728 GLuint service_id = glCreateProgram();
1729 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501730 id_manager()->AddMapping(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:471731 CreateProgramInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321732 }
1733}
1734
1735void GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
1736 // TODO(gman): verify client_id is unused.
1737 GLuint service_id = glCreateShader(type);
1738 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501739 id_manager()->AddMapping(client_id, service_id);
[email protected]45bf5152010-02-12 00:11:311740 CreateShaderInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321741 }
1742}
1743
[email protected]86093972010-03-11 00:13:561744bool GLES2DecoderImpl::ValidateGLenumCompressedTextureInternalFormat(GLenum) {
1745 // TODO(gman): Add support for compressed texture formats.
1746 return false;
1747}
1748
[email protected]3916c97e2010-02-25 03:20:501749void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:451750 GLuint texture_index = texture_unit - GL_TEXTURE0;
1751 if (texture_index > group_->max_texture_units()) {
[email protected]3916c97e2010-02-25 03:20:501752 SetGLError(GL_INVALID_ENUM);
1753 return;
1754 }
[email protected]36cef8ce2010-03-16 07:34:451755 active_texture_unit_ = texture_index;
1756 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:501757}
1758
[email protected]051b1372010-04-12 02:42:081759void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:501760 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:081761 GLuint service_id = 0;
1762 if (client_id != 0 && !id_manager()->GetServiceId(client_id, &service_id)) {
1763 // It's a new id so make a buffer info for it.
1764 glGenBuffersARB(1, &service_id);
1765 RegisterObjects(1, &client_id, &service_id);
1766 CreateBufferInfo(service_id);
1767 }
1768 if (service_id) {
1769 info = GetBufferInfo(service_id);
[email protected]0c86dbf2010-03-05 08:14:111770 // Check the buffer exists
1771 // Check that we are not trying to bind it to a different target.
1772 if (!info || (info->target() != 0 && info->target() != target)) {
[email protected]a93bb842010-02-16 23:03:471773 SetGLError(GL_INVALID_OPERATION);
1774 return;
1775 }
[email protected]0c86dbf2010-03-05 08:14:111776 if (info->target() == 0) {
1777 info->set_target(target);
1778 }
[email protected]a93bb842010-02-16 23:03:471779 }
[email protected]96449d2c2009-11-25 00:01:321780 switch (target) {
1781 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501782 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321783 break;
1784 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501785 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321786 break;
1787 default:
[email protected]a93bb842010-02-16 23:03:471788 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:321789 break;
1790 }
[email protected]051b1372010-04-12 02:42:081791 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:321792}
1793
[email protected]051b1372010-04-12 02:42:081794void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
1795 FramebufferManager::FramebufferInfo* info = NULL;
1796 GLuint service_id = 0;
1797 if (client_id != 0 && !id_manager()->GetServiceId(client_id, &service_id)) {
1798 // It's a new id so make a framebuffer info for it.
1799 glGenFramebuffersEXT(1, &service_id);
1800 RegisterObjects(1, &client_id, &service_id);
1801 CreateFramebufferInfo(service_id);
1802 }
1803 if (service_id) {
1804 info = GetFramebufferInfo(service_id);
1805 // Check the framebuffer exists
1806 if (!info) {
1807 SetGLError(GL_INVALID_OPERATION);
1808 return;
1809 }
1810 }
1811 bound_framebuffer_ = info;
[email protected]6217d392010-03-25 22:08:351812
1813 // When rendering to an offscreen frame buffer, instead of unbinding from
1814 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:081815 if (info == NULL && offscreen_target_frame_buffer_.get())
1816 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:351817
[email protected]051b1372010-04-12 02:42:081818 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:561819}
1820
[email protected]051b1372010-04-12 02:42:081821void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
1822 RenderbufferManager::RenderbufferInfo* info = NULL;
1823 GLuint service_id = 0;
1824 if (client_id != 0 && !id_manager()->GetServiceId(client_id, &service_id)) {
1825 // It's a new id so make a renderbuffer info for it.
1826 glGenRenderbuffersEXT(1, &service_id);
1827 RegisterObjects(1, &client_id, &service_id);
1828 CreateRenderbufferInfo(service_id);
1829 }
1830 if (service_id) {
1831 info = GetRenderbufferInfo(service_id);
1832 // Check the renderbuffer exists
1833 if (!info) {
1834 SetGLError(GL_INVALID_OPERATION);
1835 return;
1836 }
1837 }
1838 bound_renderbuffer_ = info;
1839 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:561840}
1841
[email protected]051b1372010-04-12 02:42:081842void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:501843 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:081844 GLuint service_id = 0;
1845 if (client_id != 0 && !id_manager()->GetServiceId(client_id, &service_id)) {
1846 // It's a new id so make a texture info for it.
1847 glGenTextures(1, &service_id);
1848 RegisterObjects(1, &client_id, &service_id);
1849 CreateTextureInfo(service_id);
1850 }
1851 if (service_id) {
1852 info = GetTextureInfo(service_id);
[email protected]3916c97e2010-02-25 03:20:501853 // Check the texture exists
1854 // Check that we are not trying to bind it to a different target.
[email protected]a93bb842010-02-16 23:03:471855 if (!info || (info->target() != 0 && info->target() != target)) {
1856 SetGLError(GL_INVALID_OPERATION);
1857 return;
1858 }
1859 if (info->target() == 0) {
[email protected]3916c97e2010-02-25 03:20:501860 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:471861 }
1862 }
[email protected]051b1372010-04-12 02:42:081863 glBindTexture(target, service_id);
[email protected]3916c97e2010-02-25 03:20:501864 TextureUnit& unit = texture_units_[active_texture_unit_];
1865 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:471866 switch (target) {
1867 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501868 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:471869 break;
1870 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:501871 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:471872 break;
1873 default:
1874 NOTREACHED(); // Validation should prevent us getting here.
1875 break;
1876 }
1877}
1878
[email protected]07f54fcc2009-12-22 02:46:301879void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501880 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301881 vertex_attrib_infos_[index].set_enabled(false);
[email protected]8a837bb2010-01-05 00:21:241882 glDisableVertexAttribArray(index);
[email protected]07f54fcc2009-12-22 02:46:301883 } else {
1884 SetGLError(GL_INVALID_VALUE);
1885 }
1886}
1887
1888void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501889 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301890 vertex_attrib_infos_[index].set_enabled(true);
1891 glEnableVertexAttribArray(index);
1892 } else {
1893 SetGLError(GL_INVALID_VALUE);
1894 }
1895}
1896
[email protected]a93bb842010-02-16 23:03:471897void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:501898 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1899 if (!info || !info->MarkMipmapsGenerated()) {
[email protected]a93bb842010-02-16 23:03:471900 SetGLError(GL_INVALID_OPERATION);
1901 return;
1902 }
1903 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:471904}
1905
[email protected]b273e432010-04-12 17:23:581906bool GLES2DecoderImpl::GetHelper(
1907 GLenum pname, GLint* params, GLsizei* num_written) {
1908 DCHECK(params);
1909 DCHECK(num_written);
1910 switch (pname) {
[email protected]58ae32f2010-04-14 01:26:041911#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]b273e432010-04-12 17:23:581912 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1913 *num_written = 1;
[email protected]58ae32f2010-04-14 01:26:041914 *params = GL_RGBA; // TODO(gman): get correct format.
[email protected]b273e432010-04-12 17:23:581915 return true;
1916 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1917 *num_written = 1;
1918 *params = GL_UNSIGNED_BYTE; // TODO(gman): get correct type.
1919 return true;
1920 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
[email protected]58ae32f2010-04-14 01:26:041921 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, params);
[email protected]b273e432010-04-12 17:23:581922 *num_written = 1;
[email protected]58ae32f2010-04-14 01:26:041923 *params /= 4;
[email protected]b273e432010-04-12 17:23:581924 return true;
1925 case GL_MAX_VARYING_VECTORS:
[email protected]58ae32f2010-04-14 01:26:041926 glGetIntegerv(GL_MAX_VARYING_FLOATS, params);
[email protected]b273e432010-04-12 17:23:581927 *num_written = 1;
[email protected]58ae32f2010-04-14 01:26:041928 *params /= 4;
[email protected]b273e432010-04-12 17:23:581929 return true;
1930 case GL_MAX_VERTEX_UNIFORM_VECTORS:
[email protected]58ae32f2010-04-14 01:26:041931 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, params);
[email protected]b273e432010-04-12 17:23:581932 *num_written = 1;
[email protected]58ae32f2010-04-14 01:26:041933 *params /= 4;
[email protected]b273e432010-04-12 17:23:581934 return true;
[email protected]58ae32f2010-04-14 01:26:041935#endif
[email protected]b273e432010-04-12 17:23:581936 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1937 *num_written = 1;
1938 *params = 0; // We don't support compressed textures.
1939 return true;
1940 case GL_NUM_SHADER_BINARY_FORMATS:
1941 *num_written = 1;
1942 *params = 0; // We don't support binary shader formats.
1943 return true;
1944 case GL_SHADER_BINARY_FORMATS:
1945 *num_written = 0;
1946 return true; // We don't support binary shader format.s
1947 case GL_SHADER_COMPILER:
1948 *num_written = 1;
1949 *params = GL_TRUE;
1950 return true;
1951 default:
1952 return false;
1953 }
1954}
1955
1956void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
1957 DCHECK(params);
1958 GLint values[16];
1959 GLsizei num_written;
1960 if (GetHelper(pname, &values[0], &num_written)) {
1961 DCHECK_LE(static_cast<size_t>(num_written), arraysize(values));
1962 for (GLsizei ii = 0; ii < num_written; ++ii) {
1963 params[ii] = static_cast<GLboolean>(values[ii]);
1964 }
1965 } else {
1966 glGetBooleanv(pname, params);
1967 }
1968}
1969
1970void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
1971 DCHECK(params);
1972 GLint values[16];
1973 GLsizei num_written;
1974 if (GetHelper(pname, &values[0], &num_written)) {
1975 DCHECK_LE(static_cast<size_t>(num_written), arraysize(values));
1976 for (GLsizei ii = 0; ii < num_written; ++ii) {
1977 params[ii] = static_cast<GLfloat>(values[ii]);
1978 }
1979 } else {
1980 glGetFloatv(pname, params);
1981 }
1982}
1983
1984void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
1985 DCHECK(params);
1986 GLsizei num_written;
1987 if (!GetHelper(pname, params, &num_written)) {
1988 glGetIntegerv(pname, params);
1989 }
1990}
1991
[email protected]a0c3e972010-04-21 00:49:131992void GLES2DecoderImpl::DoGetProgramiv(
1993 GLuint program_id, GLenum pname, GLint* params) {
1994 ProgramManager::ProgramInfo* info = GetProgramInfo(program_id);
1995 if (!info) {
1996 SetGLError(GL_INVALID_OPERATION);
1997 return;
1998 }
1999 info->GetProgramiv(pname, params);
2000}
2001
[email protected]558847a2010-03-24 07:02:542002error::Error GLES2DecoderImpl::HandleBindAttribLocation(
2003 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
2004 GLuint program;
2005 if (!id_manager()->GetServiceId(c.program, &program)) {
2006 SetGLError(GL_INVALID_VALUE);
2007 return error::kNoError;
2008 }
2009 GLuint index = static_cast<GLuint>(c.index);
2010 uint32 name_size = c.data_size;
2011 const char* name = GetSharedMemoryAs<const char*>(
2012 c.name_shm_id, c.name_shm_offset, name_size);
2013 if (name == NULL) {
2014 return error::kOutOfBounds;
2015 }
2016 String name_str(name, name_size);
2017 glBindAttribLocation(program, index, name_str.c_str());
2018 return error::kNoError;
2019}
2020
2021error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
2022 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
2023 GLuint program;
2024 if (!id_manager()->GetServiceId(c.program, &program)) {
2025 SetGLError(GL_INVALID_VALUE);
2026 return error::kNoError;
2027 }
2028 GLuint index = static_cast<GLuint>(c.index);
2029 uint32 name_size = c.data_size;
2030 const char* name = GetImmediateDataAs<const char*>(
2031 c, name_size, immediate_data_size);
2032 if (name == NULL) {
2033 return error::kOutOfBounds;
2034 }
2035 String name_str(name, name_size);
2036 glBindAttribLocation(program, index, name_str.c_str());
2037 return error::kNoError;
2038}
2039
2040error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
2041 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
2042 GLuint program;
2043 if (!id_manager()->GetServiceId(c.program, &program)) {
2044 SetGLError(GL_INVALID_VALUE);
2045 return error::kNoError;
2046 }
2047 GLuint index = static_cast<GLuint>(c.index);
2048 Bucket* bucket = GetBucket(c.name_bucket_id);
2049 if (!bucket || bucket->size() == 0) {
2050 return error::kInvalidArguments;
2051 }
2052 std::string name_str;
2053 bucket->GetAsString(&name_str);
2054 glBindAttribLocation(program, index, name_str.c_str());
2055 return error::kNoError;
2056}
2057
[email protected]f7a64ee2010-02-01 22:24:142058error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:462059 uint32 immediate_data_size, const gles2::DeleteShader& c) {
2060 GLuint shader = c.shader;
[email protected]96449d2c2009-11-25 00:01:322061 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:502062 if (!id_manager()->GetServiceId(shader, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:462063 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142064 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322065 }
[email protected]45bf5152010-02-12 00:11:312066 RemoveShaderInfo(service_id);
[email protected]07f54fcc2009-12-22 02:46:302067 glDeleteShader(service_id);
[email protected]3916c97e2010-02-25 03:20:502068 id_manager()->RemoveMapping(shader, service_id);
[email protected]f7a64ee2010-02-01 22:24:142069 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322070}
2071
[email protected]f7a64ee2010-02-01 22:24:142072error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:462073 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
2074 GLuint program = c.program;
[email protected]96449d2c2009-11-25 00:01:322075 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:502076 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:462077 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142078 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322079 }
[email protected]1d32bc82010-01-13 22:06:462080 RemoveProgramInfo(service_id);
[email protected]ba3176a2009-12-16 18:19:462081 glDeleteProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:502082 id_manager()->RemoveMapping(program, service_id);
[email protected]f7a64ee2010-02-01 22:24:142083 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322084}
2085
[email protected]07f54fcc2009-12-22 02:46:302086void GLES2DecoderImpl::DoDrawArrays(
2087 GLenum mode, GLint first, GLsizei count) {
2088 if (IsDrawValid(first + count - 1)) {
[email protected]3916c97e2010-02-25 03:20:502089 bool has_non_renderable_textures;
2090 SetBlackTextureForNonRenderableTextures(&has_non_renderable_textures);
[email protected]07f54fcc2009-12-22 02:46:302091 glDrawArrays(mode, first, count);
[email protected]3916c97e2010-02-25 03:20:502092 if (has_non_renderable_textures) {
2093 RestoreStateForNonRenderableTextures();
2094 }
[email protected]07f54fcc2009-12-22 02:46:302095 }
2096}
2097
[email protected]36cef8ce2010-03-16 07:34:452098void GLES2DecoderImpl::DoFramebufferRenderbuffer(
2099 GLenum target, GLenum attachment, GLenum renderbuffertarget,
2100 GLuint renderbuffer) {
[email protected]051b1372010-04-12 02:42:082101 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452102 SetGLError(GL_INVALID_OPERATION);
2103 return;
2104 }
2105 glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget,
2106 renderbuffer);
2107}
2108
2109GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]051b1372010-04-12 02:42:082110 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452111 return GL_FRAMEBUFFER_COMPLETE;
2112 }
2113 return glCheckFramebufferStatusEXT(target);
2114}
2115
2116void GLES2DecoderImpl::DoFramebufferTexture2D(
2117 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
2118 GLint level) {
[email protected]051b1372010-04-12 02:42:082119 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452120 SetGLError(GL_INVALID_OPERATION);
2121 return;
2122 }
2123 glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
2124}
2125
2126void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
2127 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082128 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452129 SetGLError(GL_INVALID_OPERATION);
2130 return;
2131 }
2132 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
2133}
2134
2135void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
2136 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082137 if (!bound_renderbuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452138 SetGLError(GL_INVALID_OPERATION);
2139 return;
2140 }
2141 glGetRenderbufferParameterivEXT(target, pname, params);
2142}
2143
2144void GLES2DecoderImpl::DoRenderbufferStorage(
2145 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:082146 if (!bound_renderbuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452147 SetGLError(GL_INVALID_OPERATION);
2148 return;
2149 }
2150 glRenderbufferStorageEXT(target, internalformat, width, height);
2151}
2152
[email protected]07f54fcc2009-12-22 02:46:302153void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]a93bb842010-02-16 23:03:472154 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2155 if (!info) {
2156 SetGLError(GL_INVALID_OPERATION);
2157 return;
2158 }
[email protected]07f54fcc2009-12-22 02:46:302159 CopyRealGLErrorsToWrapper();
2160 glLinkProgram(program);
2161 GLenum error = glGetError();
2162 if (error != GL_NO_ERROR) {
2163 RemoveProgramInfo(program);
2164 SetGLError(error);
2165 } else {
[email protected]a93bb842010-02-16 23:03:472166 info->Update();
[email protected]07f54fcc2009-12-22 02:46:302167 }
2168};
2169
[email protected]3916c97e2010-02-25 03:20:502170void GLES2DecoderImpl::DoTexParameterf(
2171 GLenum target, GLenum pname, GLfloat param) {
2172 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:302173 if (!info) {
[email protected]3916c97e2010-02-25 03:20:502174 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:302175 } else {
[email protected]3916c97e2010-02-25 03:20:502176 info->SetParameter(pname, static_cast<GLint>(param));
2177 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:302178 }
2179}
2180
[email protected]3916c97e2010-02-25 03:20:502181void GLES2DecoderImpl::DoTexParameteri(
2182 GLenum target, GLenum pname, GLint param) {
2183 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2184 if (!info) {
2185 SetGLError(GL_INVALID_VALUE);
2186 } else {
2187 info->SetParameter(pname, param);
2188 glTexParameteri(target, pname, param);
2189 }
2190}
2191
2192void GLES2DecoderImpl::DoTexParameterfv(
2193 GLenum target, GLenum pname, const GLfloat* params) {
2194 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2195 if (!info) {
2196 SetGLError(GL_INVALID_VALUE);
2197 } else {
2198 info->SetParameter(pname, *reinterpret_cast<const GLint*>(params));
2199 glTexParameterfv(target, pname, params);
2200 }
2201}
2202
2203void GLES2DecoderImpl::DoTexParameteriv(
2204 GLenum target, GLenum pname, const GLint* params) {
2205 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2206 if (!info) {
2207 SetGLError(GL_INVALID_VALUE);
2208 } else {
2209 info->SetParameter(pname, *params);
2210 glTexParameteriv(target, pname, params);
2211 }
2212}
2213
2214void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
2215 if (!current_program_ || current_program_->IsDeleted()) {
2216 // The program does not exist.
2217 SetGLError(GL_INVALID_OPERATION);
2218 return;
2219 }
2220 current_program_->SetSamplers(location, 1, &v0);
2221 glUniform1i(location, v0);
2222}
2223
2224void GLES2DecoderImpl::DoUniform1iv(
2225 GLint location, GLsizei count, const GLint *value) {
2226 if (!current_program_ || current_program_->IsDeleted()) {
2227 // The program does not exist.
2228 SetGLError(GL_INVALID_OPERATION);
2229 return;
2230 }
2231 current_program_->SetSamplers(location, count, value);
2232 glUniform1iv(location, count, value);
2233}
2234
2235void GLES2DecoderImpl::DoUseProgram(GLuint program) {
2236 ProgramManager::ProgramInfo* info = NULL;
2237 if (program) {
2238 info = GetProgramInfo(program);
2239 if (!info) {
2240 // Program was not linked successfully. (ie, glLinkProgram)
2241 SetGLError(GL_INVALID_OPERATION);
2242 return;
2243 }
2244 }
2245 current_program_ = info;
2246 glUseProgram(program);
2247}
2248
[email protected]96449d2c2009-11-25 00:01:322249GLenum GLES2DecoderImpl::GetGLError() {
2250 // Check the GL error first, then our wrapped error.
2251 GLenum error = glGetError();
2252 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:372253 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:322254 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:292255 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:322256 break;
2257 }
2258 }
2259 }
2260
2261 if (error != GL_NO_ERROR) {
2262 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:292263 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322264 }
2265 return error;
2266}
2267
2268void GLES2DecoderImpl::SetGLError(GLenum error) {
[email protected]ddd968b82010-03-02 00:44:292269 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322270}
2271
[email protected]07f54fcc2009-12-22 02:46:302272void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
2273 GLenum error;
2274 while ((error = glGetError()) != GL_NO_ERROR) {
2275 SetGLError(error);
2276 }
2277}
2278
[email protected]6217d392010-03-25 22:08:352279void GLES2DecoderImpl::ClearRealGLErrors() {
2280 GLenum error;
2281 while ((error = glGetError()) != GL_NO_ERROR) {
2282 NOTREACHED() << "GL error " << error << " was unhandled.";
2283 }
2284}
2285
[email protected]07f54fcc2009-12-22 02:46:302286bool GLES2DecoderImpl::VertexAttribInfo::CanAccess(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:502287 if (!enabled_) {
2288 return true;
2289 }
2290
2291 if (!buffer_ || buffer_->IsDeleted()) {
2292 return false;
2293 }
2294
2295 // The number of elements that can be accessed.
2296 GLsizeiptr buffer_size = buffer_->size();
2297 if (offset_ > buffer_size || real_stride_ == 0) {
2298 return false;
2299 }
2300
2301 uint32 usable_size = buffer_size - offset_;
2302 GLuint num_elements = usable_size / real_stride_ +
2303 ((usable_size % real_stride_) >=
2304 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
2305 return index < num_elements;
2306}
2307
2308void GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures(
2309 bool* has_non_renderable_textures) {
2310 DCHECK(has_non_renderable_textures);
2311 DCHECK(current_program_);
2312 DCHECK(!current_program_->IsDeleted());
2313 *has_non_renderable_textures = false;
2314 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
2315 current_program_->sampler_indices();
2316 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
2317 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2318 current_program_->GetUniformInfo(sampler_indices[ii]);
2319 DCHECK(uniform_info);
2320 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
2321 GLuint texture_unit_index = uniform_info->texture_units[jj];
2322 if (texture_unit_index < group_->max_texture_units()) {
2323 TextureUnit& texture_unit = texture_units_[texture_unit_index];
2324 TextureManager::TextureInfo* texture_info =
2325 uniform_info->type == GL_SAMPLER_2D ?
2326 texture_unit.bound_texture_2d :
2327 texture_unit.bound_texture_cube_map;
2328 if (!texture_info || !texture_info->CanRender()) {
2329 *has_non_renderable_textures = true;
2330 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
2331 glBindTexture(
2332 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
2333 GL_TEXTURE_CUBE_MAP,
2334 uniform_info->type == GL_SAMPLER_2D ? black_2d_texture_id_ :
2335 black_cube_texture_id_);
2336 }
2337 }
2338 // else: should this be an error?
2339 }
2340 }
2341}
2342
2343void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
2344 DCHECK(current_program_);
2345 DCHECK(!current_program_->IsDeleted());
2346 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
2347 current_program_->sampler_indices();
2348 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
2349 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2350 current_program_->GetUniformInfo(sampler_indices[ii]);
2351 DCHECK(uniform_info);
2352 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
2353 GLuint texture_unit_index = uniform_info->texture_units[jj];
2354 if (texture_unit_index < group_->max_texture_units()) {
2355 TextureUnit& texture_unit = texture_units_[texture_unit_index];
2356 TextureManager::TextureInfo* texture_info =
2357 uniform_info->type == GL_SAMPLER_2D ?
2358 texture_unit.bound_texture_2d :
2359 texture_unit.bound_texture_cube_map;
2360 if (!texture_info || !texture_info->CanRender()) {
2361 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
2362 // Get the texture info that was previously bound here.
2363 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
2364 texture_unit.bound_texture_2d :
2365 texture_unit.bound_texture_cube_map;
2366 glBindTexture(texture_unit.bind_target,
2367 texture_info ? texture_info->texture_id() : 0);
2368 }
2369 }
2370 }
2371 }
2372 // Set the active texture back to whatever the user had it as.
2373 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:302374}
2375
2376bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]3916c97e2010-02-25 03:20:502377 if (!current_program_ || current_program_->IsDeleted()) {
2378 // The program does not exist.
2379 // But GL says no ERROR.
2380 return false;
2381 }
2382 // Validate that all attribs current program needs are setup correctly.
2383 const ProgramManager::ProgramInfo::AttribInfoVector& infos =
2384 current_program_->GetAttribInfos();
2385 for (size_t ii = 0; ii < infos.size(); ++ii) {
2386 GLint location = infos[ii].location;
2387 if (location < 0) {
2388 return false;
2389 }
2390 DCHECK_LT(static_cast<GLuint>(location), group_->max_vertex_attribs());
2391 if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:462392 SetGLError(GL_INVALID_OPERATION);
2393 return false;
2394 }
[email protected]07f54fcc2009-12-22 02:46:302395 }
[email protected]3916c97e2010-02-25 03:20:502396 return true;
[email protected]07f54fcc2009-12-22 02:46:302397};
2398
[email protected]f7a64ee2010-02-01 22:24:142399error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:192400 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:502401 if (!bound_element_array_buffer_ ||
2402 bound_element_array_buffer_->IsDeleted()) {
2403 SetGLError(GL_INVALID_OPERATION);
2404 } else {
[email protected]96449d2c2009-11-25 00:01:322405 GLenum mode = c.mode;
2406 GLsizei count = c.count;
2407 GLenum type = c.type;
[email protected]1d32bc82010-01-13 22:06:462408 int32 offset = c.index_offset;
[email protected]a76b0052010-03-05 00:33:182409 if (count < 0 || offset < 0) {
[email protected]d2cf0a2d2010-02-25 21:36:122410 SetGLError(GL_INVALID_VALUE);
2411 } else if (!ValidateGLenumDrawMode(mode) ||
2412 !ValidateGLenumIndexType(type)) {
[email protected]1d32bc82010-01-13 22:06:462413 SetGLError(GL_INVALID_ENUM);
[email protected]ba3176a2009-12-16 18:19:462414 } else {
[email protected]0c86dbf2010-03-05 08:14:112415 GLuint max_vertex_accessed;
2416 if (!bound_element_array_buffer_->GetMaxValueForRange(
2417 offset, count, type, &max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:462418 SetGLError(GL_INVALID_OPERATION);
2419 } else {
[email protected]0c86dbf2010-03-05 08:14:112420 if (IsDrawValid(max_vertex_accessed)) {
2421 bool has_non_renderable_textures;
2422 SetBlackTextureForNonRenderableTextures(
2423 &has_non_renderable_textures);
[email protected]3916c97e2010-02-25 03:20:502424 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]0c86dbf2010-03-05 08:14:112425 glDrawElements(mode, count, type, indices);
2426 if (has_non_renderable_textures) {
2427 RestoreStateForNonRenderableTextures();
[email protected]1d32bc82010-01-13 22:06:462428 }
2429 }
[email protected]07f54fcc2009-12-22 02:46:302430 }
[email protected]ba3176a2009-12-16 18:19:462431 }
[email protected]96449d2c2009-11-25 00:01:322432 }
[email protected]f7a64ee2010-02-01 22:24:142433 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322434}
2435
[email protected]29a9eb52010-04-13 09:04:232436GLuint GLES2DecoderImpl::DoGetMaxValueInBuffer(
2437 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
2438 GLuint max_vertex_accessed = 0;
2439 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
2440 if (info->target() != GL_ELEMENT_ARRAY_BUFFER) {
2441 SetGLError(GL_INVALID_OPERATION);
2442 } else {
2443 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
2444 SetGLError(GL_INVALID_OPERATION);
2445 }
2446 }
2447 return max_vertex_accessed;
2448}
2449
[email protected]96449d2c2009-11-25 00:01:322450// Calls glShaderSource for the various versions of the ShaderSource command.
2451// Assumes that data / data_size points to a piece of memory that is in range
2452// of whatever context it came from (shared memory, immediate memory, bucket
2453// memory.)
[email protected]45bf5152010-02-12 00:11:312454error::Error GLES2DecoderImpl::ShaderSourceHelper(
2455 GLuint shader, const char* data, uint32 data_size) {
2456 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2457 if (!info) {
2458 SetGLError(GL_INVALID_OPERATION);
2459 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322460 }
[email protected]45bf5152010-02-12 00:11:312461 // Note: We don't actually call glShaderSource here. We wait until
2462 // the call to glCompileShader.
2463 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:142464 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322465}
2466
[email protected]f7a64ee2010-02-01 22:24:142467error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:192468 uint32 immediate_data_size, const gles2::ShaderSource& c) {
2469 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:502470 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:192471 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142472 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192473 }
[email protected]96449d2c2009-11-25 00:01:322474 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:312475 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:322476 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:462477 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142478 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:322479 }
[email protected]45bf5152010-02-12 00:11:312480 return ShaderSourceHelper(shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:322481}
2482
[email protected]f7a64ee2010-02-01 22:24:142483error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:192484 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
2485 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:502486 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:192487 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142488 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192489 }
[email protected]96449d2c2009-11-25 00:01:322490 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:312491 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:302492 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462493 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142494 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:322495 }
[email protected]45bf5152010-02-12 00:11:312496 return ShaderSourceHelper(shader, data, data_size);
2497}
2498
[email protected]558847a2010-03-24 07:02:542499error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
2500 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
2501 GLuint shader;
2502 if (!id_manager()->GetServiceId(c.shader, &shader)) {
2503 SetGLError(GL_INVALID_VALUE);
2504 return error::kNoError;
2505 }
2506 Bucket* bucket = GetBucket(c.data_bucket_id);
2507 if (!bucket || bucket->size() == 0) {
2508 return error::kInvalidArguments;
2509 }
2510 return ShaderSourceHelper(
2511 shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
2512 bucket->size() - 1);
2513}
2514
[email protected]45bf5152010-02-12 00:11:312515void GLES2DecoderImpl::DoCompileShader(GLuint shader) {
2516 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2517 if (!info) {
2518 SetGLError(GL_INVALID_OPERATION);
2519 return;
2520 }
2521 // TODO(gman): Run shader through compiler that converts GL ES 2.0 shader
2522 // to DesktopGL shader and pass that to glShaderSource and then
2523 // glCompileShader.
2524 const char* ptr = info->source().c_str();
2525 glShaderSource(shader, 1, &ptr, NULL);
2526 glCompileShader(shader);
2527};
2528
[email protected]ddd968b82010-03-02 00:44:292529void GLES2DecoderImpl::DoGetShaderiv(
2530 GLuint shader, GLenum pname, GLint* params) {
2531 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2532 if (!info) {
2533 SetGLError(GL_INVALID_OPERATION);
2534 return;
2535 }
2536 if (pname == GL_SHADER_SOURCE_LENGTH) {
2537 *params = info->source().size();
2538 } else {
2539 glGetShaderiv(shader, pname, params);
2540 }
2541}
2542
[email protected]45bf5152010-02-12 00:11:312543void GLES2DecoderImpl::DoGetShaderSource(
2544 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst) {
2545 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
2546 if (!info) {
2547 SetGLError(GL_INVALID_OPERATION);
2548 return;
2549 }
[email protected]a76b0052010-03-05 00:33:182550 // bufsize is set by the service side code and should always be positive.
2551 DCHECK_GT(bufsize, 0);
[email protected]45bf5152010-02-12 00:11:312552 const std::string& source = info->source();
2553 GLsizei size = std::min(bufsize - 1, static_cast<GLsizei>(source.size()));
2554 if (length) {
2555 *length = size;
2556 }
2557 memcpy(dst, source.c_str(), size);
2558 dst[size] = '\0';
[email protected]96449d2c2009-11-25 00:01:322559}
2560
[email protected]f7a64ee2010-02-01 22:24:142561error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:192562 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]3916c97e2010-02-25 03:20:502563 if (bound_array_buffer_ && !bound_array_buffer_->IsDeleted()) {
[email protected]96449d2c2009-11-25 00:01:322564 GLuint indx = c.indx;
2565 GLint size = c.size;
2566 GLenum type = c.type;
2567 GLboolean normalized = c.normalized;
2568 GLsizei stride = c.stride;
[email protected]07f54fcc2009-12-22 02:46:302569 GLsizei offset = c.offset;
2570 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]ba3176a2009-12-16 18:19:462571 if (!ValidateGLenumVertexAttribType(type) ||
[email protected]d2cf0a2d2010-02-25 21:36:122572 !ValidateGLintVertexAttribSize(size)) {
2573 SetGLError(GL_INVALID_ENUM);
2574 return error::kNoError;
2575 }
2576 if (indx >= group_->max_vertex_attribs() ||
2577 stride < 0 ||
2578 offset < 0) {
[email protected]ba3176a2009-12-16 18:19:462579 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142580 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322581 }
[email protected]3916c97e2010-02-25 03:20:502582 GLsizei component_size =
2583 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]07f54fcc2009-12-22 02:46:302584 GLsizei real_stride = stride != 0 ? stride : component_size * size;
2585 if (offset % component_size > 0) {
2586 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142587 return error::kNoError;
[email protected]07f54fcc2009-12-22 02:46:302588 }
2589 vertex_attrib_infos_[indx].SetInfo(
2590 bound_array_buffer_,
[email protected]07f54fcc2009-12-22 02:46:302591 size,
2592 type,
2593 real_stride,
2594 offset);
[email protected]96449d2c2009-11-25 00:01:322595 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
2596 } else {
2597 SetGLError(GL_INVALID_VALUE);
2598 }
[email protected]f7a64ee2010-02-01 22:24:142599 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322600}
2601
[email protected]f7a64ee2010-02-01 22:24:142602error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:192603 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:312604 GLint x = c.x;
2605 GLint y = c.y;
2606 GLsizei width = c.width;
2607 GLsizei height = c.height;
2608 GLenum format = c.format;
2609 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:562610 if (width < 0 || height < 0) {
2611 SetGLError(GL_INVALID_VALUE);
2612 return error::kNoError;
2613 }
[email protected]a51788e2010-02-24 21:54:252614 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:182615 uint32 pixels_size;
2616 if (!GLES2Util::ComputeImageDataSize(
2617 width, height, format, type, pack_alignment_, &pixels_size)) {
2618 return error::kOutOfBounds;
2619 }
[email protected]612d2f82009-12-08 20:49:312620 void* pixels = GetSharedMemoryAs<void*>(
2621 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:252622 Result* result = GetSharedMemoryAs<Result*>(
2623 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2624 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:142625 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462626 }
[email protected]a51788e2010-02-24 21:54:252627
[email protected]ba3176a2009-12-16 18:19:462628 if (!ValidateGLenumReadPixelFormat(format) ||
2629 !ValidateGLenumPixelType(type)) {
[email protected]d2cf0a2d2010-02-25 21:36:122630 SetGLError(GL_INVALID_ENUM);
2631 return error::kNoError;
2632 }
[email protected]57f223832010-03-19 01:57:562633 if (width == 0 || height == 0) {
2634 return error::kNoError;
2635 }
2636
2637 CopyRealGLErrorsToWrapper();
2638
2639 // Get the size of the current fbo or backbuffer.
[email protected]d37231fa2010-04-09 21:16:022640 gfx::Size max_size = GetBoundFrameBufferSize();
[email protected]57f223832010-03-19 01:57:562641
2642 GLint max_x;
2643 GLint max_y;
2644 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]ba3176a2009-12-16 18:19:462645 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142646 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:312647 }
[email protected]57f223832010-03-19 01:57:562648
[email protected]d37231fa2010-04-09 21:16:022649 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:562650 // The user requested an out of range area. Get the results 1 line
2651 // at a time.
2652 uint32 temp_size;
2653 if (!GLES2Util::ComputeImageDataSize(
2654 width, 1, format, type, pack_alignment_, &temp_size)) {
2655 SetGLError(GL_INVALID_VALUE);
2656 return error::kNoError;
2657 }
2658 GLsizei unpadded_row_size = temp_size;
2659 if (!GLES2Util::ComputeImageDataSize(
2660 width, 2, format, type, pack_alignment_, &temp_size)) {
2661 SetGLError(GL_INVALID_VALUE);
2662 return error::kNoError;
2663 }
2664 GLsizei padded_row_size = temp_size - unpadded_row_size;
2665 if (padded_row_size < 0 || unpadded_row_size < 0) {
2666 SetGLError(GL_INVALID_VALUE);
2667 return error::kNoError;
2668 }
2669
2670 GLint dest_x_offset = std::max(-x, 0);
2671 uint32 dest_row_offset;
2672 if (!GLES2Util::ComputeImageDataSize(
2673 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
2674 SetGLError(GL_INVALID_VALUE);
2675 return error::kNoError;
2676 }
2677
2678 // Copy each row into the larger dest rect.
2679 int8* dst = static_cast<int8*>(pixels);
2680 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:022681 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:562682 GLint read_width = read_end_x - read_x;
2683 for (GLint yy = 0; yy < height; ++yy) {
2684 GLint ry = y + yy;
2685
2686 // Clear the row.
2687 memset(dst, 0, unpadded_row_size);
2688
2689 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:022690 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:562691 glReadPixels(
2692 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
2693 }
2694 dst += padded_row_size;
2695 }
2696 } else {
2697 glReadPixels(x, y, width, height, format, type, pixels);
2698 }
[email protected]a51788e2010-02-24 21:54:252699 GLenum error = glGetError();
2700 if (error == GL_NO_ERROR) {
2701 *result = true;
2702 } else {
2703 SetGLError(error);
2704 }
[email protected]f7a64ee2010-02-01 22:24:142705 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322706}
2707
[email protected]f7a64ee2010-02-01 22:24:142708error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:192709 uint32 immediate_data_size, const gles2::PixelStorei& c) {
2710 GLenum pname = c.pname;
2711 GLenum param = c.param;
[email protected]d2cf0a2d2010-02-25 21:36:122712 if (!ValidateGLenumPixelStore(pname)) {
2713 SetGLError(GL_INVALID_ENUM);
2714 return error::kNoError;
2715 }
2716 if (!ValidateGLintPixelStoreAlignment(param)) {
[email protected]ba3176a2009-12-16 18:19:462717 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142718 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192719 }
2720 glPixelStorei(pname, param);
2721 switch (pname) {
2722 case GL_PACK_ALIGNMENT:
2723 pack_alignment_ = param;
2724 break;
2725 case GL_UNPACK_ALIGNMENT:
2726 unpack_alignment_ = param;
2727 break;
2728 default:
2729 // Validation should have prevented us from getting here.
2730 DCHECK(false);
2731 break;
2732 }
[email protected]f7a64ee2010-02-01 22:24:142733 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192734}
2735
[email protected]558847a2010-03-24 07:02:542736error::Error GLES2DecoderImpl::GetAttribLocationHelper(
2737 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
2738 const std::string& name_str) {
[email protected]b9849abf2009-11-25 19:13:192739 GLuint program;
[email protected]558847a2010-03-24 07:02:542740 if (!id_manager()->GetServiceId(client_id, &program)) {
[email protected]b9849abf2009-11-25 19:13:192741 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142742 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192743 }
[email protected]0bfd9882010-02-05 23:02:252744 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2745 if (!info) {
2746 // Program was not linked successfully. (ie, glLinkProgram)
2747 SetGLError(GL_INVALID_OPERATION);
2748 return error::kNoError;
2749 }
[email protected]b9849abf2009-11-25 19:13:192750 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:542751 location_shm_id, location_shm_offset, sizeof(GLint));
2752 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:142753 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192754 }
[email protected]558847a2010-03-24 07:02:542755 // Require the client to init this incase the context is lost and we are no
2756 // longer executing commands.
2757 if (*location != -1) {
2758 return error::kGenericError;
2759 }
[email protected]0bfd9882010-02-05 23:02:252760 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142761 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192762}
2763
[email protected]558847a2010-03-24 07:02:542764error::Error GLES2DecoderImpl::HandleGetAttribLocation(
2765 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
2766 uint32 name_size = c.data_size;
2767 const char* name = GetSharedMemoryAs<const char*>(
2768 c.name_shm_id, c.name_shm_offset, name_size);
2769 if (!name) {
2770 return error::kOutOfBounds;
2771 }
2772 String name_str(name, name_size);
2773 return GetAttribLocationHelper(
2774 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2775}
2776
[email protected]f7a64ee2010-02-01 22:24:142777error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192778 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:542779 uint32 name_size = c.data_size;
2780 const char* name = GetImmediateDataAs<const char*>(
2781 c, name_size, immediate_data_size);
2782 if (!name) {
2783 return error::kOutOfBounds;
2784 }
2785 String name_str(name, name_size);
2786 return GetAttribLocationHelper(
2787 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2788}
2789
2790error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
2791 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
2792 Bucket* bucket = GetBucket(c.name_bucket_id);
2793 if (!bucket) {
2794 return error::kInvalidArguments;
2795 }
2796 std::string name_str;
2797 bucket->GetAsString(&name_str);
2798 return GetAttribLocationHelper(
2799 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2800}
2801
2802error::Error GLES2DecoderImpl::GetUniformLocationHelper(
2803 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
2804 const std::string& name_str) {
[email protected]b9849abf2009-11-25 19:13:192805 GLuint program;
[email protected]558847a2010-03-24 07:02:542806 if (!id_manager()->GetServiceId(client_id, &program)) {
[email protected]b9849abf2009-11-25 19:13:192807 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142808 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192809 }
[email protected]0bfd9882010-02-05 23:02:252810 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2811 if (!info) {
2812 // Program was not linked successfully. (ie, glLinkProgram)
2813 SetGLError(GL_INVALID_OPERATION);
2814 return error::kNoError;
2815 }
[email protected]b9849abf2009-11-25 19:13:192816 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:542817 location_shm_id, location_shm_offset, sizeof(GLint));
2818 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:142819 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192820 }
[email protected]558847a2010-03-24 07:02:542821 // Require the client to init this incase the context is lost an we are no
2822 // longer executing commands.
2823 if (*location != -1) {
2824 return error::kGenericError;
2825 }
2826 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142827 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192828}
2829
[email protected]f7a64ee2010-02-01 22:24:142830error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:192831 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:192832 uint32 name_size = c.data_size;
2833 const char* name = GetSharedMemoryAs<const char*>(
2834 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:542835 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:142836 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192837 }
2838 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:542839 return GetUniformLocationHelper(
2840 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:192841}
2842
[email protected]f7a64ee2010-02-01 22:24:142843error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192844 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:192845 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:302846 const char* name = GetImmediateDataAs<const char*>(
2847 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:542848 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:142849 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192850 }
2851 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:542852 return GetUniformLocationHelper(
2853 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2854}
2855
2856error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
2857 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
2858 Bucket* bucket = GetBucket(c.name_bucket_id);
2859 if (!bucket) {
2860 return error::kInvalidArguments;
2861 }
2862 std::string name_str;
2863 bucket->GetAsString(&name_str);
2864 return GetUniformLocationHelper(
2865 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:192866}
2867
[email protected]ddd968b82010-03-02 00:44:292868error::Error GLES2DecoderImpl::HandleGetString(
2869 uint32 immediate_data_size, const gles2::GetString& c) {
2870 GLenum name = static_cast<GLenum>(c.name);
2871 if (!ValidateGLenumStringType(name)) {
2872 SetGLError(GL_INVALID_ENUM);
2873 return error::kNoError;
2874 }
2875 Bucket* bucket = CreateBucket(c.bucket_id);
2876 bucket->SetFromString(reinterpret_cast<const char*>(glGetString(name)));
2877 return error::kNoError;
2878}
2879
[email protected]0c86dbf2010-03-05 08:14:112880void GLES2DecoderImpl::DoBufferData(
2881 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]3b6ec202010-03-05 05:16:232882 if (!ValidateGLenumBufferTarget(target) ||
2883 !ValidateGLenumBufferUsage(usage)) {
2884 SetGLError(GL_INVALID_ENUM);
[email protected]0c86dbf2010-03-05 08:14:112885 return;
[email protected]3b6ec202010-03-05 05:16:232886 }
2887 if (size < 0) {
2888 SetGLError(GL_INVALID_VALUE);
[email protected]0c86dbf2010-03-05 08:14:112889 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232890 }
2891 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
2892 if (!info) {
2893 SetGLError(GL_INVALID_OPERATION);
[email protected]0c86dbf2010-03-05 08:14:112894 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232895 }
2896 // Clear the buffer to 0 if no initial data was passed in.
2897 scoped_array<int8> zero;
2898 if (!data) {
2899 zero.reset(new int8[size]);
2900 memset(zero.get(), 0, size);
2901 data = zero.get();
2902 }
2903 CopyRealGLErrorsToWrapper();
2904 glBufferData(target, size, data, usage);
2905 GLenum error = glGetError();
2906 if (error != GL_NO_ERROR) {
2907 SetGLError(error);
2908 } else {
[email protected]0c86dbf2010-03-05 08:14:112909 info->SetSize(size);
2910 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:232911 }
[email protected]0c86dbf2010-03-05 08:14:112912}
2913
2914error::Error GLES2DecoderImpl::HandleBufferData(
2915 uint32 immediate_data_size, const gles2::BufferData& c) {
2916 GLenum target = static_cast<GLenum>(c.target);
2917 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
2918 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
2919 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
2920 GLenum usage = static_cast<GLenum>(c.usage);
2921 const void* data = NULL;
2922 if (data_shm_id != 0 || data_shm_offset != 0) {
2923 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
2924 if (!data) {
2925 return error::kOutOfBounds;
2926 }
2927 }
2928 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:142929 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192930}
2931
[email protected]f7a64ee2010-02-01 22:24:142932error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:192933 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
2934 GLenum target = static_cast<GLenum>(c.target);
2935 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:302936 const void* data = GetImmediateDataAs<const void*>(
2937 c, size, immediate_data_size);
2938 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142939 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:302940 }
[email protected]b9849abf2009-11-25 19:13:192941 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:112942 DoBufferData(target, size, data, usage);
2943 return error::kNoError;
2944}
2945
2946void GLES2DecoderImpl::DoBufferSubData(
2947 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:502948 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472949 if (!info) {
2950 SetGLError(GL_INVALID_OPERATION);
[email protected]a93bb842010-02-16 23:03:472951 }
[email protected]0c86dbf2010-03-05 08:14:112952 if (!info->SetRange(offset, size, data)) {
2953 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:302954 } else {
[email protected]0c86dbf2010-03-05 08:14:112955 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:302956 }
[email protected]b9849abf2009-11-25 19:13:192957}
2958
[email protected]a93bb842010-02-16 23:03:472959error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
2960 GLenum target,
2961 GLint level,
2962 GLenum internal_format,
2963 GLsizei width,
2964 GLsizei height,
2965 GLint border,
2966 GLsizei image_size,
2967 const void* data) {
[email protected]a93bb842010-02-16 23:03:472968 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]86093972010-03-11 00:13:562969 if (!ValidateGLenumTextureTarget(target) ||
2970 !ValidateGLenumCompressedTextureInternalFormat(internal_format)) {
[email protected]a93bb842010-02-16 23:03:472971 SetGLError(GL_INVALID_ENUM);
2972 return error::kNoError;
2973 }
[email protected]3916c97e2010-02-25 03:20:502974 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:472975 border != 0) {
2976 SetGLError(GL_INVALID_VALUE);
2977 return error::kNoError;
2978 }
[email protected]3916c97e2010-02-25 03:20:502979 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472980 if (!info) {
2981 SetGLError(GL_INVALID_OPERATION);
2982 return error::kNoError;
2983 }
2984 scoped_array<int8> zero;
2985 if (!data) {
2986 zero.reset(new int8[image_size]);
2987 memset(zero.get(), 0, image_size);
2988 data = zero.get();
2989 }
2990 info->SetLevelInfo(
2991 target, level, internal_format, width, height, 1, border, 0, 0);
2992 glCompressedTexImage2D(
2993 target, level, internal_format, width, height, border, image_size, data);
2994 return error::kNoError;
2995}
2996
[email protected]f7a64ee2010-02-01 22:24:142997error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192998 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
2999 GLenum target = static_cast<GLenum>(c.target);
3000 GLint level = static_cast<GLint>(c.level);
3001 GLenum internal_format = static_cast<GLenum>(c.internalformat);
3002 GLsizei width = static_cast<GLsizei>(c.width);
3003 GLsizei height = static_cast<GLsizei>(c.height);
3004 GLint border = static_cast<GLint>(c.border);
3005 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
3006 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
3007 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
3008 const void* data = NULL;
3009 if (data_shm_id != 0 || data_shm_offset != 0) {
3010 data = GetSharedMemoryAs<const void*>(
3011 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:463012 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143013 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193014 }
3015 }
[email protected]a93bb842010-02-16 23:03:473016 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:193017 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:193018}
3019
[email protected]f7a64ee2010-02-01 22:24:143020error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:193021 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
3022 GLenum target = static_cast<GLenum>(c.target);
3023 GLint level = static_cast<GLint>(c.level);
3024 GLenum internal_format = static_cast<GLenum>(c.internalformat);
3025 GLsizei width = static_cast<GLsizei>(c.width);
3026 GLsizei height = static_cast<GLsizei>(c.height);
3027 GLint border = static_cast<GLint>(c.border);
3028 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:303029 const void* data = GetImmediateDataAs<const void*>(
3030 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:463031 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143032 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:463033 }
[email protected]a93bb842010-02-16 23:03:473034 return DoCompressedTexImage2D(
3035 target, level, internal_format, width, height, border, image_size, data);
3036}
3037
[email protected]a93bb842010-02-16 23:03:473038error::Error GLES2DecoderImpl::DoTexImage2D(
3039 GLenum target,
3040 GLint level,
3041 GLenum internal_format,
3042 GLsizei width,
3043 GLsizei height,
3044 GLint border,
3045 GLenum format,
3046 GLenum type,
3047 const void* pixels,
3048 uint32 pixels_size) {
3049 if (!ValidateGLenumTextureTarget(target) ||
3050 !ValidateGLenumTextureFormat(internal_format) ||
3051 !ValidateGLenumTextureFormat(format) ||
3052 !ValidateGLenumPixelType(type)) {
[email protected]8bf5a3e2010-01-29 04:21:363053 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:143054 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193055 }
[email protected]3916c97e2010-02-25 03:20:503056 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:473057 border != 0) {
3058 SetGLError(GL_INVALID_VALUE);
3059 return error::kNoError;
3060 }
[email protected]3916c97e2010-02-25 03:20:503061 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:473062 if (!info) {
3063 SetGLError(GL_INVALID_OPERATION);
3064 return error::kNoError;
3065 }
3066 scoped_array<int8> zero;
3067 if (!pixels) {
3068 zero.reset(new int8[pixels_size]);
3069 memset(zero.get(), 0, pixels_size);
3070 pixels = zero.get();
3071 }
3072 info->SetLevelInfo(
3073 target, level, internal_format, width, height, 1, border, format, type);
3074 glTexImage2D(
3075 target, level, internal_format, width, height, border, format, type,
3076 pixels);
[email protected]f7a64ee2010-02-01 22:24:143077 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193078}
3079
[email protected]f7a64ee2010-02-01 22:24:143080error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:193081 uint32 immediate_data_size, const gles2::TexImage2D& c) {
3082 GLenum target = static_cast<GLenum>(c.target);
3083 GLint level = static_cast<GLint>(c.level);
3084 GLint internal_format = static_cast<GLint>(c.internalformat);
3085 GLsizei width = static_cast<GLsizei>(c.width);
3086 GLsizei height = static_cast<GLsizei>(c.height);
3087 GLint border = static_cast<GLint>(c.border);
3088 GLenum format = static_cast<GLenum>(c.format);
3089 GLenum type = static_cast<GLenum>(c.type);
3090 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
3091 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:183092 uint32 pixels_size;
3093 if (!GLES2Util::ComputeImageDataSize(
3094 width, height, format, type, unpack_alignment_, &pixels_size)) {
3095 return error::kOutOfBounds;
3096 }
[email protected]b9849abf2009-11-25 19:13:193097 const void* pixels = NULL;
3098 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
3099 pixels = GetSharedMemoryAs<const void*>(
3100 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:463101 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:143102 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193103 }
3104 }
[email protected]a93bb842010-02-16 23:03:473105 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:193106 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:473107 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:193108}
3109
[email protected]f7a64ee2010-02-01 22:24:143110error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:193111 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
3112 GLenum target = static_cast<GLenum>(c.target);
3113 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:463114 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:193115 GLsizei width = static_cast<GLsizei>(c.width);
3116 GLsizei height = static_cast<GLsizei>(c.height);
3117 GLint border = static_cast<GLint>(c.border);
3118 GLenum format = static_cast<GLenum>(c.format);
3119 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:183120 uint32 size;
3121 if (!GLES2Util::ComputeImageDataSize(
3122 width, height, format, type, unpack_alignment_, &size)) {
3123 return error::kOutOfBounds;
3124 }
[email protected]07f54fcc2009-12-22 02:46:303125 const void* pixels = GetImmediateDataAs<const void*>(
3126 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:463127 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:143128 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:463129 }
[email protected]a93bb842010-02-16 23:03:473130 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:463131 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:473132 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:143133 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323134}
3135
[email protected]f7a64ee2010-02-01 22:24:143136error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:193137 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:363138 GLuint index = static_cast<GLuint>(c.index);
3139 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:253140 typedef gles2::GetVertexAttribPointerv::Result Result;
3141 Result* result = GetSharedMemoryAs<Result*>(
3142 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:363143 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:143144 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:363145 }
[email protected]07d0cc82010-02-17 04:51:403146 // Check that the client initialized the result.
3147 if (result->size != 0) {
3148 return error::kInvalidArguments;
3149 }
[email protected]8bf5a3e2010-01-29 04:21:363150 if (!ValidateGLenumVertexPointer(pname)) {
3151 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:143152 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:363153 }
[email protected]3916c97e2010-02-25 03:20:503154 if (index >= group_->max_vertex_attribs()) {
[email protected]8bf5a3e2010-01-29 04:21:363155 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:143156 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:363157 }
[email protected]0bfd9882010-02-05 23:02:253158 result->SetNumResults(1);
3159 *result->GetData() = vertex_attrib_infos_[index].offset();
[email protected]f7a64ee2010-02-01 22:24:143160 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323161}
3162
[email protected]f7b85372010-02-03 01:11:373163bool GLES2DecoderImpl::GetUniformSetup(
3164 GLuint program, GLint location,
3165 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:253166 error::Error* error, GLuint* service_id, void** result_pointer) {
[email protected]f7b85372010-02-03 01:11:373167 *error = error::kNoError;
3168 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:253169 SizedResult<GLint>* result;
3170 result = GetSharedMemoryAs<SizedResult<GLint>*>(
3171 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
3172 if (!result) {
[email protected]f7b85372010-02-03 01:11:373173 *error = error::kOutOfBounds;
3174 return false;
3175 }
[email protected]0bfd9882010-02-05 23:02:253176 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:373177 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:253178 result->SetNumResults(0);
[email protected]3916c97e2010-02-25 03:20:503179 if (!id_manager()->GetServiceId(program, service_id)) {
[email protected]f7b85372010-02-03 01:11:373180 SetGLError(GL_INVALID_VALUE);
3181 return error::kNoError;
3182 }
3183 ProgramManager::ProgramInfo* info = GetProgramInfo(*service_id);
3184 if (!info) {
3185 // Program was not linked successfully. (ie, glLinkProgram)
3186 SetGLError(GL_INVALID_OPERATION);
3187 return false;
3188 }
[email protected]0bfd9882010-02-05 23:02:253189 GLenum type;
3190 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:373191 // No such location.
3192 SetGLError(GL_INVALID_OPERATION);
3193 return false;
3194 }
[email protected]3916c97e2010-02-25 03:20:503195 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:373196 if (size == 0) {
3197 SetGLError(GL_INVALID_OPERATION);
3198 return false;
3199 }
[email protected]0bfd9882010-02-05 23:02:253200 result = GetSharedMemoryAs<SizedResult<GLint>*>(
3201 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
3202 if (!result) {
[email protected]f7b85372010-02-03 01:11:373203 *error = error::kOutOfBounds;
3204 return false;
3205 }
[email protected]0bfd9882010-02-05 23:02:253206 result->size = size;
[email protected]f7b85372010-02-03 01:11:373207 return true;
3208}
3209
[email protected]f7a64ee2010-02-01 22:24:143210error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:193211 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:373212 GLuint program = c.program;
3213 GLint location = c.location;
3214 GLuint service_id;
3215 Error error;
[email protected]0bfd9882010-02-05 23:02:253216 void* result;
[email protected]f7b85372010-02-03 01:11:373217 if (GetUniformSetup(
3218 program, location, c.params_shm_id, c.params_shm_offset,
3219 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:253220 glGetUniformiv(
3221 service_id, location,
3222 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:373223 }
3224 return error;
[email protected]96449d2c2009-11-25 00:01:323225}
3226
[email protected]f7a64ee2010-02-01 22:24:143227error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:193228 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:373229 GLuint program = c.program;
3230 GLint location = c.location;
3231 GLuint service_id;
3232 Error error;
[email protected]0bfd9882010-02-05 23:02:253233 void* result;
3234 typedef gles2::GetUniformfv::Result Result;
[email protected]f7b85372010-02-03 01:11:373235 if (GetUniformSetup(
3236 program, location, c.params_shm_id, c.params_shm_offset,
3237 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:253238 glGetUniformfv(
3239 service_id,
3240 location,
3241 static_cast<gles2::GetUniformfv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:373242 }
3243 return error;
[email protected]96449d2c2009-11-25 00:01:323244}
3245
[email protected]f7a64ee2010-02-01 22:24:143246error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:193247 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:253248 GLenum shader_type = static_cast<GLenum>(c.shadertype);
3249 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
3250 typedef gles2::GetShaderPrecisionFormat::Result Result;
3251 Result* result = GetSharedMemoryAs<Result*>(
3252 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3253 if (!result) {
3254 return error::kOutOfBounds;
3255 }
[email protected]07d0cc82010-02-17 04:51:403256 // Check that the client initialized the result.
3257 if (result->success != 0) {
3258 return error::kInvalidArguments;
3259 }
[email protected]0bfd9882010-02-05 23:02:253260 if (!ValidateGLenumShaderType(shader_type) ||
3261 !ValidateGLenumShaderPrecision(precision_type)) {
[email protected]0bfd9882010-02-05 23:02:253262 SetGLError(GL_INVALID_ENUM);
3263 } else {
3264 result->success = 1; // true
3265 switch (precision_type) {
3266 case GL_LOW_INT:
3267 case GL_MEDIUM_INT:
3268 case GL_HIGH_INT:
3269 result->min_range = -31;
3270 result->max_range = 31;
3271 result->precision = 0;
3272 case GL_LOW_FLOAT:
3273 case GL_MEDIUM_FLOAT:
3274 case GL_HIGH_FLOAT:
3275 result->min_range = -62;
3276 result->max_range = 62;
3277 result->precision = -16;
3278 break;
3279 default:
3280 NOTREACHED();
3281 break;
3282 }
3283 }
[email protected]f7a64ee2010-02-01 22:24:143284 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323285}
3286
[email protected]f7a64ee2010-02-01 22:24:143287error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:193288 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:253289 GLuint service_id;
3290 uint32 result_size = c.result_size;
[email protected]3916c97e2010-02-25 03:20:503291 if (!id_manager()->GetServiceId(c.program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:253292 SetGLError(GL_INVALID_VALUE);
3293 return error::kNoError;
3294 }
3295 typedef gles2::GetAttachedShaders::Result Result;
3296 uint32 max_count = Result::ComputeMaxResults(result_size);
3297 Result* result = GetSharedMemoryAs<Result*>(
3298 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
3299 if (!result) {
3300 return error::kOutOfBounds;
3301 }
[email protected]07d0cc82010-02-17 04:51:403302 // Check that the client initialized the result.
3303 if (result->size != 0) {
3304 return error::kInvalidArguments;
3305 }
[email protected]0bfd9882010-02-05 23:02:253306 GLsizei count = 0;
3307 glGetAttachedShaders(service_id, max_count, &count, result->GetData());
3308 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]3916c97e2010-02-25 03:20:503309 if (!id_manager()->GetClientId(result->GetData()[ii],
[email protected]0bfd9882010-02-05 23:02:253310 &result->GetData()[ii])) {
3311 NOTREACHED();
3312 return error::kGenericError;
3313 }
3314 }
3315 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:143316 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323317}
3318
[email protected]f7a64ee2010-02-01 22:24:143319error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:193320 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:253321 GLuint program = c.program;
3322 GLuint index = c.index;
3323 uint32 name_bucket_id = c.name_bucket_id;
3324 GLuint service_id;
3325 typedef gles2::GetActiveUniform::Result Result;
3326 Result* result = GetSharedMemoryAs<Result*>(
3327 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3328 if (!result) {
3329 return error::kOutOfBounds;
3330 }
[email protected]07d0cc82010-02-17 04:51:403331 // Check that the client initialized the result.
3332 if (result->success != 0) {
3333 return error::kInvalidArguments;
3334 }
[email protected]3916c97e2010-02-25 03:20:503335 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:253336 SetGLError(GL_INVALID_VALUE);
3337 return error::kNoError;
3338 }
3339 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
3340 if (!info) {
3341 // Program was not linked successfully. (ie, glLinkProgram)
3342 SetGLError(GL_INVALID_OPERATION);
3343 return error::kNoError;
3344 }
3345 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
3346 info->GetUniformInfo(index);
3347 if (!uniform_info) {
3348 SetGLError(GL_INVALID_VALUE);
3349 return error::kNoError;
3350 }
3351 result->success = 1; // true.
3352 result->size = uniform_info->size;
3353 result->type = uniform_info->type;
3354 Bucket* bucket = CreateBucket(name_bucket_id);
3355 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:143356 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323357}
3358
[email protected]f7a64ee2010-02-01 22:24:143359error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:193360 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:253361 GLuint program = c.program;
3362 GLuint index = c.index;
3363 uint32 name_bucket_id = c.name_bucket_id;
3364 GLuint service_id;
3365 typedef gles2::GetActiveAttrib::Result Result;
3366 Result* result = GetSharedMemoryAs<Result*>(
3367 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3368 if (!result) {
3369 return error::kOutOfBounds;
3370 }
[email protected]07d0cc82010-02-17 04:51:403371 // Check that the client initialized the result.
3372 if (result->success != 0) {
3373 return error::kInvalidArguments;
3374 }
[email protected]3916c97e2010-02-25 03:20:503375 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:253376 SetGLError(GL_INVALID_VALUE);
3377 return error::kNoError;
3378 }
3379 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
3380 if (!info) {
3381 // Program was not linked successfully. (ie, glLinkProgram)
3382 SetGLError(GL_INVALID_OPERATION);
3383 return error::kNoError;
3384 }
3385 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
3386 info->GetAttribInfo(index);
3387 if (!attrib_info) {
3388 SetGLError(GL_INVALID_VALUE);
3389 return error::kNoError;
3390 }
3391 result->success = 1; // true.
3392 result->size = attrib_info->size;
3393 result->type = attrib_info->type;
3394 Bucket* bucket = CreateBucket(name_bucket_id);
3395 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:143396 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323397}
3398
[email protected]b273e432010-04-12 17:23:583399error::Error GLES2DecoderImpl::HandleShaderBinary(
3400 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
3401#if 1 // No binary shader support.
3402 SetGLError(GL_INVALID_OPERATION);
3403 return error::kNoError;
3404#else
3405 GLsizei n = static_cast<GLsizei>(c.n);
3406 if (n < 0) {
3407 SetGLError(GL_INVALID_VALUE);
3408 return error::kNoError;
3409 }
3410 GLsizei length = static_cast<GLsizei>(c.length);
3411 if (length < 0) {
3412 SetGLError(GL_INVALID_VALUE);
3413 return error::kNoError;
3414 }
3415 uint32 data_size;
3416 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3417 return error::kOutOfBounds;
3418 }
3419 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
3420 c.shaders_shm_id, c.shaders_shm_offset, data_size);
3421 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
3422 const void* binary = GetSharedMemoryAs<const void*>(
3423 c.binary_shm_id, c.binary_shm_offset, length);
3424 if (shaders == NULL || binary == NULL) {
3425 return error::kOutOfBounds;
3426 }
3427 scoped_array<GLuint> service_ids(new GLuint[n]);
3428 for (GLsizei ii = 0; ii < n; ++ii) {
3429 if (!id_manager()->GetServiceId(shaders[ii], &service_ids[ii])) {
3430 SetGLError(GL_INVALID_VALUE);
3431 return error::kNoError;
3432 }
3433 // TODO(gman): Check that each shader exists.
3434 }
3435 // TODO(gman): call glShaderBinary
3436 return error::kNoError;
3437#endif
3438}
3439
[email protected]6217d392010-03-25 22:08:353440error::Error GLES2DecoderImpl::HandleSwapBuffers(
3441 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
3442 // Check a client created frame buffer is not bound. TODO(apatrick):
3443 // this error is overkill. It will require that the client recreate the
3444 // context to continue.
[email protected]051b1372010-04-12 02:42:083445 if (bound_framebuffer_)
[email protected]6217d392010-03-25 22:08:353446 return error::kLostContext;
3447
3448 // If offscreen then don't actually SwapBuffers to the display. Just copy
3449 // the rendered frame to another frame buffer.
3450 if (offscreen_target_frame_buffer_.get()) {
3451 ScopedGLErrorSuppressor suppressor(this);
3452
3453 // First check to see if a deferred offscreen render buffer resize is
3454 // pending.
3455 if (!UpdateOffscreenFrameBufferSize())
3456 return error::kLostContext;
3457
3458 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]d37231fa2010-04-09 21:16:023459 offscreen_saved_color_texture_->Copy(
3460 offscreen_saved_color_texture_->size());
[email protected]6217d392010-03-25 22:08:353461 } else {
[email protected]d37231fa2010-04-09 21:16:023462#if !defined(UNIT_TEST)
3463 context_->SwapBuffers();
[email protected]6217d392010-03-25 22:08:353464#endif
3465 }
3466
[email protected]7d9ce4f2010-04-14 18:39:403467 // TODO(kbr): when the back buffer is multisampled, then at least on Mac
3468 // OS X (and probably on all platforms, for best semantics), we will need
3469 // to perform the resolve step and bind the offscreen_saved_color_texture_
3470 // as the color attachment before calling the swap buffers callback, which
3471 // expects a normal (non-multisampled) frame buffer for glCopyTexImage2D /
3472 // glReadPixels. After the callback runs, the multisampled frame buffer
3473 // needs to be bound again.
3474
[email protected]6217d392010-03-25 22:08:353475 if (swap_buffers_callback_.get()) {
3476 swap_buffers_callback_->Run();
3477 }
3478
3479 return error::kNoError;
3480}
3481
[email protected]96449d2c2009-11-25 00:01:323482// Include the auto-generated part of this file. We split this because it means
3483// we can easily edit the non-auto generated parts right here in this file
3484// instead of having to edit some template or the code generator.
3485#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
3486
3487} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:253488} // namespace gpu