blob: 93f28f9e136b248d57602db64b77aed6dad03144 [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]5a6db6c2010-04-22 18:32:0613
14#include "app/gfx/gl/gl_context.h"
[email protected]2041cf342010-02-19 03:15:5915#include "base/callback.h"
[email protected]96449d2c2009-11-25 00:01:3216#include "base/scoped_ptr.h"
[email protected]6217d392010-03-25 22:08:3517#include "base/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0218#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3219#define GLES2_GPU_SERVICE 1
20#include "gpu/command_buffer/common/gles2_cmd_format.h"
21#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1022#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5023#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3224#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5025#include "gpu/command_buffer/service/context_group.h"
[email protected]a25fa872010-03-25 02:57:5826#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3227#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4628#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4729#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]de17df392010-04-23 21:09:4134// TODO(alokp): Remove GLES2_GPU_SERVICE_TRANSLATE_SHADER guard
35// as soon as translator is ready.
36//#define GLES2_GPU_SERVICE_TRANSLATE_SHADER
37#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
[email protected]3094c2a2010-04-29 21:50:4538#include "third_party/angle/include/GLSLANG/ShaderLang.h"
[email protected]de17df392010-04-23 21:09:4139#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
40
[email protected]6217d392010-03-25 22:08:3541#if !defined(GL_DEPTH24_STENCIL8)
42#define GL_DEPTH24_STENCIL8 0x88F0
43#endif
44
[email protected]58ae32f2010-04-14 01:26:0445#if defined(UNIT_TEST)
46
47// OpenGL constants not defined in OpenGL ES 2.0 needed when compiling
48// unit tests. For native OpenGL ES 2.0 backend these are not used. For OpenGL
49// backend these must be defined by the local system.
50#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
51#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
52#define GL_MAX_VARYING_FLOATS 0x8B4B
53
54#endif
55
[email protected]a7a27ace2009-12-12 00:11:2556namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3257namespace gles2 {
58
[email protected]6217d392010-03-25 22:08:3559class GLES2DecoderImpl;
60
[email protected]07f54fcc2009-12-22 02:46:3061// Check that certain assumptions the code makes are true. There are places in
62// the code where shared memory is passed direclty to GL. Example, glUniformiv,
63// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
64// a few others) are 32bits. If they are not 32bits the code will have to change
65// to call those GL functions with service side memory and then copy the results
66// to shared memory, converting the sizes.
67COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
68 GLint_not_same_size_as_uint32);
69COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
70 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3771COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
72 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3073
[email protected]43f28f832010-02-03 02:28:4874// TODO(kbr): the use of this anonymous namespace core dumps the
75// linker on Mac OS X 10.6 when the symbol ordering file is used
76// namespace {
[email protected]96449d2c2009-11-25 00:01:3277
78// Returns the address of the first byte after a struct.
79template <typename T>
80const void* AddressAfterStruct(const T& pod) {
81 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
82}
83
[email protected]07f54fcc2009-12-22 02:46:3084// Returns the address of the frst byte after the struct or NULL if size >
85// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3286template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3087RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
88 uint32 size,
89 uint32 immediate_data_size) {
90 return (size <= immediate_data_size) ?
91 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
92 NULL;
[email protected]96449d2c2009-11-25 00:01:3293}
94
[email protected]07f54fcc2009-12-22 02:46:3095// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1896bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3297 GLuint count,
98 size_t size,
[email protected]a76b0052010-03-05 00:33:1899 unsigned int elements_per_unit,
100 uint32* dst) {
101 uint32 value;
102 if (!SafeMultiplyUint32(count, size, &value)) {
103 return false;
104 }
105 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
106 return false;
107 }
108 *dst = value;
109 return true;
[email protected]96449d2c2009-11-25 00:01:32110}
111
112// A struct to hold info about each command.
113struct CommandInfo {
114 int arg_flags; // How to handle the arguments for this command
115 int arg_count; // How many arguments are expected for this command.
116};
117
118// A table of CommandInfo for all the commands.
119const CommandInfo g_command_info[] = {
120 #define GLES2_CMD_OP(name) { \
121 name::kArgFlags, \
122 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
123
124 GLES2_COMMAND_LIST(GLES2_CMD_OP)
125
126 #undef GLES2_CMD_OP
127};
128
[email protected]6217d392010-03-25 22:08:35129// This class prevents any GL errors that occur when it is in scope from
130// being reported to the client.
131class ScopedGLErrorSuppressor {
132 public:
133 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
134 ~ScopedGLErrorSuppressor();
135 private:
136 GLES2DecoderImpl* decoder_;
137 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
138};
139
140// Temporarily changes a decoder's bound 2D texture and restore it when this
141// object goes out of scope. Also temporarily switches to using active texture
142// unit zero in case the client has changed that to something invalid.
143class ScopedTexture2DBinder {
144 public:
145 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
146 ~ScopedTexture2DBinder();
147
148 private:
149 GLES2DecoderImpl* decoder_;
150 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
151};
152
153// Temporarily changes a decoder's bound render buffer and restore it when this
154// object goes out of scope.
155class ScopedRenderBufferBinder {
156 public:
157 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
158 ~ScopedRenderBufferBinder();
159
160 private:
161 GLES2DecoderImpl* decoder_;
162 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
163};
164
165// Temporarily changes a decoder's bound frame buffer and restore it when this
166// object goes out of scope.
167class ScopedFrameBufferBinder {
168 public:
169 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
170 ~ScopedFrameBufferBinder();
171
172 private:
173 GLES2DecoderImpl* decoder_;
174 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
175};
176
[email protected]2f2d7042010-04-14 21:45:58177// Temporarily switch to a decoder's default GL context, having known default
178// state.
179class ScopedDefaultGLContext {
180 public:
181 explicit ScopedDefaultGLContext(GLES2DecoderImpl* decoder);
182 ~ScopedDefaultGLContext();
183
184 private:
185 GLES2DecoderImpl* decoder_;
186 DISALLOW_COPY_AND_ASSIGN(ScopedDefaultGLContext);
187};
188
[email protected]6217d392010-03-25 22:08:35189// Encapsulates an OpenGL texture.
190class Texture {
191 public:
192 explicit Texture(GLES2DecoderImpl* decoder);
193 ~Texture();
194
195 // Create a new render texture.
196 void Create();
197
198 // Set the initial size and format of a render texture or resize it.
199 bool AllocateStorage(const gfx::Size& size);
200
201 // Copy the contents of the currently bound frame buffer.
202 void Copy(const gfx::Size& size);
203
204 // Destroy the render texture. This must be explicitly called before
205 // destroying this object.
206 void Destroy();
207
208 GLuint id() const {
209 return id_;
210 }
211
[email protected]d37231fa2010-04-09 21:16:02212 gfx::Size size() const {
213 return size_;
214 }
215
[email protected]6217d392010-03-25 22:08:35216 private:
217 GLES2DecoderImpl* decoder_;
218 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02219 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35220 DISALLOW_COPY_AND_ASSIGN(Texture);
221};
222
223// Encapsulates an OpenGL render buffer of any format.
224class RenderBuffer {
225 public:
226 explicit RenderBuffer(GLES2DecoderImpl* decoder);
227 ~RenderBuffer();
228
229 // Create a new render buffer.
230 void Create();
231
232 // Set the initial size and format of a render buffer or resize it.
233 bool AllocateStorage(const gfx::Size& size, GLenum format);
234
235 // Destroy the render buffer. This must be explicitly called before destroying
236 // this object.
237 void Destroy();
238
239 GLuint id() const {
240 return id_;
241 }
242
243 private:
244 GLES2DecoderImpl* decoder_;
245 GLuint id_;
246 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
247};
248
249// Encapsulates an OpenGL frame buffer.
250class FrameBuffer {
251 public:
252 explicit FrameBuffer(GLES2DecoderImpl* decoder);
253 ~FrameBuffer();
254
255 // Create a new frame buffer.
256 void Create();
257
258 // Attach a color render buffer to a frame buffer.
259 void AttachRenderTexture(Texture* texture);
260
261 // Attach a depth stencil render buffer to a frame buffer. Note that
262 // this unbinds any currently bound frame buffer.
263 void AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer);
264
265 // Clear the given attached buffers.
266 void Clear(GLbitfield buffers);
267
268 // Destroy the frame buffer. This must be explicitly called before destroying
269 // this object.
270 void Destroy();
271
272 // See glCheckFramebufferStatusEXT.
273 GLenum CheckStatus();
274
275 GLuint id() const {
276 return id_;
277 }
278
279 private:
280 GLES2DecoderImpl* decoder_;
281 GLuint id_;
282 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
283};
[email protected]43f28f832010-02-03 02:28:48284// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32285
[email protected]3916c97e2010-02-25 03:20:50286GLES2Decoder::GLES2Decoder(ContextGroup* group)
287 : group_(group),
[email protected]3916c97e2010-02-25 03:20:50288 debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32289}
290
[email protected]3916c97e2010-02-25 03:20:50291GLES2Decoder::~GLES2Decoder() {
292}
293
[email protected]96449d2c2009-11-25 00:01:32294// This class implements GLES2Decoder so we don't have to expose all the GLES2
295// cmd stuff to outside this class.
[email protected]6217d392010-03-25 22:08:35296class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
297 public GLES2Decoder {
[email protected]96449d2c2009-11-25 00:01:32298 public:
[email protected]3916c97e2010-02-25 03:20:50299 explicit GLES2DecoderImpl(ContextGroup* group);
300
[email protected]07f54fcc2009-12-22 02:46:30301 // Info about Vertex Attributes. This is used to track what the user currently
302 // has bound on each Vertex Attribute so that checking can be done at
303 // glDrawXXX time.
304 class VertexAttribInfo {
305 public:
306 VertexAttribInfo()
307 : enabled_(false),
308 size_(0),
309 type_(0),
310 offset_(0),
[email protected]3916c97e2010-02-25 03:20:50311 real_stride_(0) {
[email protected]07f54fcc2009-12-22 02:46:30312 }
[email protected]3916c97e2010-02-25 03:20:50313
[email protected]07f54fcc2009-12-22 02:46:30314 // Returns true if this VertexAttrib can access index.
315 bool CanAccess(GLuint index);
316
317 void set_enabled(bool enabled) {
318 enabled_ = enabled;
319 }
320
[email protected]3916c97e2010-02-25 03:20:50321 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30322 return buffer_;
323 }
324
[email protected]8bf5a3e2010-01-29 04:21:36325 GLsizei offset() const {
326 return offset_;
327 }
328
[email protected]07f54fcc2009-12-22 02:46:30329 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50330 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30331 GLint size,
332 GLenum type,
333 GLsizei real_stride,
334 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24335 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30336 buffer_ = buffer;
337 size_ = size;
338 type_ = type;
339 real_stride_ = real_stride;
340 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50341 }
342
343 void ClearBuffer() {
344 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30345 }
346
347 private:
348 // Whether or not this attribute is enabled.
349 bool enabled_;
350
351 // number of components (1, 2, 3, 4)
352 GLint size_;
353
354 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
355 GLenum type_;
356
357 // The offset into the buffer.
358 GLsizei offset_;
359
360 // The stride that will be used to access the buffer. This is the actual
361 // stide, NOT the GL bogus stride. In other words there is never a stride
362 // of 0.
363 GLsizei real_stride_;
364
[email protected]3916c97e2010-02-25 03:20:50365 // The buffer bound to this attribute.
366 BufferManager::BufferInfo::Ref buffer_;
[email protected]07f54fcc2009-12-22 02:46:30367 };
368
[email protected]96449d2c2009-11-25 00:01:32369 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14370 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50371 unsigned int arg_count,
372 const void* args);
[email protected]96449d2c2009-11-25 00:01:32373
374 // Overridden from AsyncAPIInterface.
375 virtual const char* GetCommandName(unsigned int command_id) const;
376
377 // Overridden from GLES2Decoder.
[email protected]5a6db6c2010-04-22 18:32:06378 virtual bool Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:35379 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:02380 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35381 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32382 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35383 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]eb54a562010-01-20 21:55:18384 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55385 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]5a6db6c2010-04-22 18:32:06386 virtual gfx::GLContext* GetGLContext() { return context_; }
[email protected]43f28f832010-02-03 02:28:48387
388 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
389
[email protected]96449d2c2009-11-25 00:01:32390 private:
[email protected]6217d392010-03-25 22:08:35391 friend class ScopedGLErrorSuppressor;
392 friend class ScopedTexture2DBinder;
393 friend class ScopedFrameBufferBinder;
394 friend class ScopedRenderBufferBinder;
[email protected]2f2d7042010-04-14 21:45:58395 friend class ScopedDefaultGLContext;
[email protected]6217d392010-03-25 22:08:35396 friend class RenderBuffer;
397 friend class FrameBuffer;
398
[email protected]3916c97e2010-02-25 03:20:50399 // State associated with each texture unit.
400 struct TextureUnit {
401 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
402
403 // The last target that was bound to this texture unit.
404 GLenum bind_target;
405
406 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
407 TextureManager::TextureInfo::Ref bound_texture_2d;
408
409 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
410 // glBindTexture
411 TextureManager::TextureInfo::Ref bound_texture_cube_map;
412 };
413
[email protected]ae51d192010-04-27 00:48:03414 // Helpers for the glGen and glDelete functions.
415 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
416 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
417 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
418 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
419 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
420 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
421 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
422 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47423
[email protected]3916c97e2010-02-25 03:20:50424 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50425 BufferManager* buffer_manager() {
426 return group_->buffer_manager();
427 }
428
[email protected]a25fa872010-03-25 02:57:58429 RenderbufferManager* renderbuffer_manager() {
430 return group_->renderbuffer_manager();
431 }
432
433 FramebufferManager* framebuffer_manager() {
434 return group_->framebuffer_manager();
435 }
436
[email protected]3916c97e2010-02-25 03:20:50437 ProgramManager* program_manager() {
438 return group_->program_manager();
439 }
440
441 ShaderManager* shader_manager() {
442 return group_->shader_manager();
443 }
444
445 TextureManager* texture_manager() {
446 return group_->texture_manager();
447 }
448
[email protected]6217d392010-03-25 22:08:35449 bool UpdateOffscreenFrameBufferSize();
450
[email protected]a93bb842010-02-16 23:03:47451 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03452 TextureManager::TextureInfo* CreateTextureInfo(
453 GLuint client_id, GLuint service_id) {
454 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47455 }
456
457 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03458 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50459 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03460 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50461 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47462 }
463
464 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03465 void RemoveTextureInfo(GLuint client_id) {
466 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50467 }
[email protected]a93bb842010-02-16 23:03:47468
[email protected]d37231fa2010-04-09 21:16:02469 // Get the size (in pixels) of the currently bound frame buffer (either FBO
470 // or regular back buffer).
471 gfx::Size GetBoundFrameBufferSize();
472
[email protected]a93bb842010-02-16 23:03:47473 // Wrapper for CompressedTexImage2D commands.
474 error::Error DoCompressedTexImage2D(
475 GLenum target,
476 GLint level,
477 GLenum internal_format,
478 GLsizei width,
479 GLsizei height,
480 GLint border,
481 GLsizei image_size,
482 const void* data);
483
484 // Wrapper for TexImage2D commands.
485 error::Error DoTexImage2D(
486 GLenum target,
487 GLint level,
488 GLenum internal_format,
489 GLsizei width,
490 GLsizei height,
491 GLint border,
492 GLenum format,
493 GLenum type,
494 const void* pixels,
495 uint32 pixels_size);
496
497 // Creates a ProgramInfo for the given program.
[email protected]ae51d192010-04-27 00:48:03498 void CreateProgramInfo(GLuint client_id, GLuint service_id) {
499 program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47500 }
501
[email protected]07f54fcc2009-12-22 02:46:30502 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03503 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50504 ProgramManager::ProgramInfo* info =
[email protected]ae51d192010-04-27 00:48:03505 program_manager()->GetProgramInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50506 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46507 }
[email protected]07f54fcc2009-12-22 02:46:30508
[email protected]6b8cf1a2010-05-06 16:13:58509 // Gets the program info for the given program. If it's not a program
510 // generates a GL error. Returns NULL if not program.
511 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
512 GLuint client_id, const char* function_name) {
513 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
514 if (!info) {
515 if (GetShaderInfo(client_id)) {
516 SetGLError(GL_INVALID_OPERATION,
517 (std::string(function_name) +
518 ": shader passed for program").c_str());
519 } else {
520 SetGLError(GL_INVALID_VALUE,
521 (std::string(function_name) + ": unknown program").c_str());
522 }
523 }
524 return info;
525 }
526
527
[email protected]07f54fcc2009-12-22 02:46:30528 // Deletes the program info for the given program.
[email protected]ae51d192010-04-27 00:48:03529 void RemoveProgramInfo(GLuint client_id) {
530 program_manager()->RemoveProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46531 }
[email protected]07f54fcc2009-12-22 02:46:30532
[email protected]45bf5152010-02-12 00:11:31533 // Creates a ShaderInfo for the given shader.
[email protected]7cea56d92010-04-28 17:21:38534 void CreateShaderInfo(GLuint client_id,
535 GLuint service_id,
536 GLenum shader_type) {
537 shader_manager()->CreateShaderInfo(client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31538 }
539
540 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03541 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
542 ShaderManager::ShaderInfo* info =
543 shader_manager()->GetShaderInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50544 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]45bf5152010-02-12 00:11:31545 }
546
[email protected]6b8cf1a2010-05-06 16:13:58547 // Gets the shader info for the given shader. If it's not a shader generates a
548 // GL error. Returns NULL if not shader.
549 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
550 GLuint client_id, const char* function_name) {
551 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
552 if (!info) {
553 if (GetProgramInfo(client_id)) {
554 SetGLError(
555 GL_INVALID_OPERATION,
556 (std::string(function_name) +
557 ": program passed for shader").c_str());
558 } else {
559 SetGLError(GL_INVALID_VALUE,
560 (std::string(function_name) + ": unknown shader").c_str());
561 }
562 }
563 return info;
564 }
565
[email protected]45bf5152010-02-12 00:11:31566 // Deletes the shader info for the given shader.
[email protected]ae51d192010-04-27 00:48:03567 void RemoveShaderInfo(GLuint client_id) {
568 shader_manager()->RemoveShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31569 }
570
[email protected]a93bb842010-02-16 23:03:47571 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03572 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
573 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47574 }
575
[email protected]07f54fcc2009-12-22 02:46:30576 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03577 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
578 BufferManager::BufferInfo* info =
579 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50580 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46581 }
[email protected]07f54fcc2009-12-22 02:46:30582
[email protected]a93bb842010-02-16 23:03:47583 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
584 // on glDeleteBuffers so we can make sure the user does not try to render
585 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03586 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47587
[email protected]a25fa872010-03-25 02:57:58588 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03589 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
590 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58591 }
592
593 // Gets the framebuffer info for the given framebuffer.
594 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03595 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58596 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03597 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58598 return (info && !info->IsDeleted()) ? info : NULL;
599 }
600
601 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03602 void RemoveFramebufferInfo(GLuint client_id) {
603 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58604 }
605
606 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03607 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
608 return renderbuffer_manager()->CreateRenderbufferInfo(
609 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58610 }
611
612 // Gets the renderbuffer info for the given renderbuffer.
613 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03614 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58615 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03616 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58617 return (info && !info->IsDeleted()) ? info : NULL;
618 }
619
620 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03621 void RemoveRenderbufferInfo(GLuint client_id) {
622 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58623 }
624
[email protected]558847a2010-03-24 07:02:54625 error::Error GetAttribLocationHelper(
626 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
627 const std::string& name_str);
628
629 error::Error GetUniformLocationHelper(
630 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
631 const std::string& name_str);
632
[email protected]3916c97e2010-02-25 03:20:50633 // Helper for glShaderSource.
634 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03635 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30636
[email protected]b273e432010-04-12 17:23:58637 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
638 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
639
[email protected]96449d2c2009-11-25 00:01:32640 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03641 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32642
643 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03644 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32645
[email protected]3916c97e2010-02-25 03:20:50646 // Wrapper for glActiveTexture
647 void DoActiveTexture(GLenum texture_unit);
648
[email protected]ae51d192010-04-27 00:48:03649 // Wrapper for glAttachShader
650 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
651
[email protected]96449d2c2009-11-25 00:01:32652 // Wrapper for glBindBuffer since we need to track the current targets.
653 void DoBindBuffer(GLenum target, GLuint buffer);
654
[email protected]86093972010-03-11 00:13:56655 // Wrapper for glBindFramebuffer since we need to track the current targets.
656 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
657
658 // Wrapper for glBindRenderbuffer since we need to track the current targets.
659 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
660
[email protected]a93bb842010-02-16 23:03:47661 // Wrapper for glBindTexture since we need to track the current targets.
662 void DoBindTexture(GLenum target, GLuint texture);
663
[email protected]36cef8ce2010-03-16 07:34:45664 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11665 void DoBufferData(
666 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
667
[email protected]36cef8ce2010-03-16 07:34:45668 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11669 void DoBufferSubData(
670 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
671
[email protected]36cef8ce2010-03-16 07:34:45672 // Wrapper for glCheckFramebufferStatus
673 GLenum DoCheckFramebufferStatus(GLenum target);
674
[email protected]45bf5152010-02-12 00:11:31675 // Wrapper for glCompileShader.
676 void DoCompileShader(GLuint shader);
677
[email protected]066849e32010-05-03 19:14:10678 // Helper for DeleteSharedIds commands.
679 void DoDeleteSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
680
[email protected]ae51d192010-04-27 00:48:03681 // Wrapper for glDetachShader
682 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
683
[email protected]07f54fcc2009-12-22 02:46:30684 // Wrapper for glDrawArrays.
685 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
686
687 // Wrapper for glDisableVertexAttribArray.
688 void DoDisableVertexAttribArray(GLuint index);
689
690 // Wrapper for glEnableVertexAttribArray.
691 void DoEnableVertexAttribArray(GLuint index);
692
[email protected]36cef8ce2010-03-16 07:34:45693 // Wrapper for glFramebufferRenderbufffer.
694 void DoFramebufferRenderbuffer(
695 GLenum target, GLenum attachment, GLenum renderbuffertarget,
696 GLuint renderbuffer);
697
698 // Wrapper for glFramebufferTexture2D.
699 void DoFramebufferTexture2D(
700 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
701 GLint level);
702
[email protected]a93bb842010-02-16 23:03:47703 // Wrapper for glGenerateMipmap
704 void DoGenerateMipmap(GLenum target);
705
[email protected]066849e32010-05-03 19:14:10706 // Helper for GenSharedIds commands.
707 void DoGenSharedIds(
708 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
709
[email protected]b273e432010-04-12 17:23:58710 // Wrapper for DoGetBooleanv.
711 void DoGetBooleanv(GLenum pname, GLboolean* params);
712
713 // Wrapper for DoGetFloatv.
714 void DoGetFloatv(GLenum pname, GLfloat* params);
715
[email protected]36cef8ce2010-03-16 07:34:45716 // Wrapper for glGetFramebufferAttachmentParameteriv.
717 void DoGetFramebufferAttachmentParameteriv(
718 GLenum target, GLenum attachment, GLenum pname, GLint* params);
719
[email protected]a0c3e972010-04-21 00:49:13720 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:58721 void DoGetIntegerv(GLenum pname, GLint* params);
722
[email protected]29a9eb52010-04-13 09:04:23723 // Gets the max value in a range in a buffer.
724 GLuint DoGetMaxValueInBuffer(
725 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
726
[email protected]a0c3e972010-04-21 00:49:13727 // Wrapper for glGetProgramiv.
728 void DoGetProgramiv(
729 GLuint program_id, GLenum pname, GLint* params);
730
[email protected]36cef8ce2010-03-16 07:34:45731 // Wrapper for glRenderbufferParameteriv.
732 void DoGetRenderbufferParameteriv(
733 GLenum target, GLenum pname, GLint* params);
734
[email protected]ddd968b82010-03-02 00:44:29735 // Wrapper for glGetShaderiv
736 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
737
[email protected]1958e0e2010-04-22 05:17:15738 // Wrappers for glIsXXX functions.
739 bool DoIsBuffer(GLuint client_id);
740 bool DoIsFramebuffer(GLuint client_id);
741 bool DoIsProgram(GLuint client_id);
742 bool DoIsRenderbuffer(GLuint client_id);
743 bool DoIsShader(GLuint client_id);
744 bool DoIsTexture(GLuint client_id);
745
[email protected]07f54fcc2009-12-22 02:46:30746 // Wrapper for glLinkProgram
747 void DoLinkProgram(GLuint program);
748
[email protected]066849e32010-05-03 19:14:10749 // Helper for RegisterSharedIds.
750 void DoRegisterSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
751
[email protected]36cef8ce2010-03-16 07:34:45752 // Wrapper for glRenderbufferStorage.
753 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:03754 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:45755
[email protected]b273e432010-04-12 17:23:58756 // Wrapper for glReleaseShaderCompiler.
757 void DoReleaseShaderCompiler() { }
758
[email protected]3916c97e2010-02-25 03:20:50759 // Wrappers for glTexParameter functions.
760 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
761 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
762 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
763 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
764
765 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
766 // spec only these 2 functions can be used to set sampler uniforms.
767 void DoUniform1i(GLint location, GLint v0);
768 void DoUniform1iv(GLint location, GLsizei count, const GLint *value);
769
[email protected]07f54fcc2009-12-22 02:46:30770 // Wrapper for glUseProgram
771 void DoUseProgram(GLuint program);
772
[email protected]ae51d192010-04-27 00:48:03773 // Wrapper for glValidateProgram.
774 void DoValidateProgram(GLuint program_client_id);
775
[email protected]96449d2c2009-11-25 00:01:32776 // Gets the GLError through our wrapper.
777 GLenum GetGLError();
778
779 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:29780 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:32781
[email protected]07f54fcc2009-12-22 02:46:30782 // Copies the real GL errors to the wrapper. This is so we can
783 // make sure there are no native GL errors before calling some GL function
784 // so that on return we know any error generated was for that specific
785 // command.
786 void CopyRealGLErrorsToWrapper();
787
[email protected]6217d392010-03-25 22:08:35788 // Clear all real GL errors. This is to prevent the client from seeing any
789 // errors caused by GL calls that it was not responsible for issuing.
790 void ClearRealGLErrors();
791
[email protected]07f54fcc2009-12-22 02:46:30792 // Checks if the current program and vertex attributes are valid for drawing.
793 bool IsDrawValid(GLuint max_vertex_accessed);
794
[email protected]3916c97e2010-02-25 03:20:50795 void SetBlackTextureForNonRenderableTextures(
796 bool* has_non_renderable_textures);
797 void RestoreStateForNonRenderableTextures();
798
[email protected]07f54fcc2009-12-22 02:46:30799 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:50800 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:30801 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:50802 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
803 bound_array_buffer_ : bound_element_array_buffer_;
804 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:30805 }
806
[email protected]a93bb842010-02-16 23:03:47807 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:50808 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
809 TextureUnit& unit = texture_units_[active_texture_unit_];
810 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:47811 switch (target) {
812 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:50813 info = unit.bound_texture_2d;
814 break;
[email protected]a93bb842010-02-16 23:03:47815 case GL_TEXTURE_CUBE_MAP:
816 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
817 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
818 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
819 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
820 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
821 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:50822 info = unit.bound_texture_cube_map;
823 break;
[email protected]1aef98132010-02-23 18:00:07824 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
825 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
826 // because |texture_| is used by the FBO rendering mechanism for readback
827 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:47828 default:
829 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:50830 return NULL;
[email protected]a93bb842010-02-16 23:03:47831 }
[email protected]3916c97e2010-02-25 03:20:50832 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47833 }
834
[email protected]f7b85372010-02-03 01:11:37835 // Validates the program and location for a glGetUniform call and returns
836 // a SizeResult setup to receive the result. Returns true if glGetUniform
837 // should be called.
838 bool GetUniformSetup(
839 GLuint program, GLint location,
840 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:25841 error::Error* error, GLuint* service_id, void** result);
[email protected]f7b85372010-02-03 01:11:37842
[email protected]86093972010-03-11 00:13:56843 bool ValidateGLenumCompressedTextureInternalFormat(GLenum format);
844
[email protected]96449d2c2009-11-25 00:01:32845 // Generate a member function prototype for each command in an automated and
846 // typesafe way.
847 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:14848 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:19849 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:32850 const gles2::name& args); \
851
852 GLES2_COMMAND_LIST(GLES2_CMD_OP)
853
854 #undef GLES2_CMD_OP
855
[email protected]2f2d7042010-04-14 21:45:58856 // The GL context this decoder renders to on behalf of the client.
[email protected]5a6db6c2010-04-22 18:32:06857 gfx::GLContext* context_;
[email protected]d37231fa2010-04-09 21:16:02858
[email protected]2f2d7042010-04-14 21:45:58859 // A GLContext that is kept in its default state. It is used to perform
860 // operations that should not be dependent on client set GLContext state, like
861 // clearing a render buffer when it is created.
862 // TODO(apatrick): Decoders in the same ContextGroup could potentially share
863 // the same default GL context.
[email protected]5a6db6c2010-04-22 18:32:06864 scoped_ptr<gfx::GLContext> default_context_;
[email protected]2f2d7042010-04-14 21:45:58865
[email protected]6217d392010-03-25 22:08:35866 // A parent decoder can access this decoders saved offscreen frame buffer.
867 // The parent pointer is reset if the parent is destroyed.
868 base::WeakPtr<GLES2DecoderImpl> parent_;
869
870 // Width and height to which an offscreen frame buffer should be resized on
871 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:02872 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:35873
[email protected]96449d2c2009-11-25 00:01:32874 // Current GL error bits.
875 uint32 error_bits_;
876
[email protected]96449d2c2009-11-25 00:01:32877 // Util to help with GL.
878 GLES2Util util_;
879
880 // pack alignment as last set by glPixelStorei
881 GLint pack_alignment_;
882
883 // unpack alignment as last set by glPixelStorei
884 GLint unpack_alignment_;
885
886 // The currently bound array buffer. If this is 0 it is illegal to call
887 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:50888 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:32889
890 // The currently bound element array buffer. If this is 0 it is illegal
891 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:50892 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:30893
894 // Info for each vertex attribute saved so we can check at glDrawXXX time
895 // if it is safe to draw.
896 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
897
[email protected]3916c97e2010-02-25 03:20:50898 // Current active texture by 0 - n index.
899 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
900 // be 2.
901 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:30902
[email protected]3916c97e2010-02-25 03:20:50903 // Which textures are bound to texture units through glActiveTexture.
904 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:47905
[email protected]3916c97e2010-02-25 03:20:50906 // Black (0,0,0,0) textures for when non-renderable textures are used.
907 // NOTE: There is no corresponding TextureInfo for these textures.
908 // TextureInfos are only for textures the client side can access.
909 GLuint black_2d_texture_id_;
910 GLuint black_cube_texture_id_;
[email protected]45bf5152010-02-12 00:11:31911
[email protected]1d32bc82010-01-13 22:06:46912 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:50913 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:30914
[email protected]86093972010-03-11 00:13:56915 // The currently bound framebuffer
[email protected]051b1372010-04-12 02:42:08916 FramebufferManager::FramebufferInfo::Ref bound_framebuffer_;
[email protected]86093972010-03-11 00:13:56917
918 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:08919 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:56920
[email protected]96449d2c2009-11-25 00:01:32921 bool anti_aliased_;
922
[email protected]6217d392010-03-25 22:08:35923 // The offscreen frame buffer that the client renders to.
924 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
925 scoped_ptr<Texture> offscreen_target_color_texture_;
926 scoped_ptr<RenderBuffer> offscreen_target_depth_stencil_render_buffer_;
927
928 // The copy that is saved when SwapBuffers is called.
929 scoped_ptr<Texture> offscreen_saved_color_texture_;
930
[email protected]43f28f832010-02-03 02:28:48931 scoped_ptr<Callback0::Type> swap_buffers_callback_;
932
[email protected]8eee29c2010-04-29 03:38:29933 // The last error message set.
934 std::string last_error_;
935
[email protected]96449d2c2009-11-25 00:01:32936 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
937};
938
[email protected]6217d392010-03-25 22:08:35939ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
940 : decoder_(decoder) {
941 decoder_->CopyRealGLErrorsToWrapper();
942}
943
944ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
945 decoder_->ClearRealGLErrors();
946}
947
948ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
949 GLuint id)
950 : decoder_(decoder) {
951 ScopedGLErrorSuppressor suppressor(decoder_);
952
953 // TODO(apatrick): Check if there are any other states that need to be reset
954 // before binding a new texture.
955 glActiveTexture(GL_TEXTURE0);
956 glBindTexture(GL_TEXTURE_2D, id);
957}
958
959ScopedTexture2DBinder::~ScopedTexture2DBinder() {
960 ScopedGLErrorSuppressor suppressor(decoder_);
961 GLES2DecoderImpl::TextureUnit& info = decoder_->texture_units_[0];
962 GLuint last_id;
963 if (info.bound_texture_2d)
[email protected]ae51d192010-04-27 00:48:03964 last_id = info.bound_texture_2d->service_id();
[email protected]6217d392010-03-25 22:08:35965 else
966 last_id = 0;
967
968 glBindTexture(GL_TEXTURE_2D, last_id);
969 glActiveTexture(GL_TEXTURE0 + decoder_->active_texture_unit_);
970}
971
972ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
973 GLuint id)
974 : decoder_(decoder) {
975 ScopedGLErrorSuppressor suppressor(decoder_);
976 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
977}
978
979ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
980 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:08981 glBindRenderbufferEXT(
982 GL_RENDERBUFFER,
983 decoder_->bound_renderbuffer_ ?
[email protected]ae51d192010-04-27 00:48:03984 decoder_->bound_renderbuffer_->service_id() : 0);
[email protected]6217d392010-03-25 22:08:35985}
986
987ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
988 GLuint id)
989 : decoder_(decoder) {
990 ScopedGLErrorSuppressor suppressor(decoder_);
991 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
992}
993
994ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
995 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:08996 FramebufferManager::FramebufferInfo* info =
997 decoder_->bound_framebuffer_.get();
[email protected]ae51d192010-04-27 00:48:03998 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]051b1372010-04-12 02:42:08999 if (framebuffer_id == 0 &&
[email protected]6217d392010-03-25 22:08:351000 decoder_->offscreen_target_frame_buffer_.get()) {
1001 glBindFramebufferEXT(GL_FRAMEBUFFER,
1002 decoder_->offscreen_target_frame_buffer_->id());
1003 } else {
[email protected]051b1372010-04-12 02:42:081004 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_id);
[email protected]6217d392010-03-25 22:08:351005 }
1006}
1007
[email protected]2f2d7042010-04-14 21:45:581008ScopedDefaultGLContext::ScopedDefaultGLContext(GLES2DecoderImpl* decoder)
1009 : decoder_(decoder) {
1010 decoder_->default_context_->MakeCurrent();
1011}
1012
1013ScopedDefaultGLContext::~ScopedDefaultGLContext() {
1014 decoder_->context_->MakeCurrent();
1015}
1016
[email protected]6217d392010-03-25 22:08:351017Texture::Texture(GLES2DecoderImpl* decoder)
1018 : decoder_(decoder),
1019 id_(0) {
1020}
1021
1022Texture::~Texture() {
1023 // This does not destroy the render texture because that would require that
1024 // the associated GL context was current. Just check that it was explicitly
1025 // destroyed.
1026 DCHECK_EQ(id_, 0u);
1027}
1028
1029void Texture::Create() {
1030 ScopedGLErrorSuppressor suppressor(decoder_);
1031 Destroy();
1032 glGenTextures(1, &id_);
1033}
1034
1035bool Texture::AllocateStorage(const gfx::Size& size) {
1036 DCHECK_NE(id_, 0u);
1037 ScopedGLErrorSuppressor suppressor(decoder_);
1038 ScopedTexture2DBinder binder(decoder_, id_);
1039 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1040 glTexParameteri(
1041 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1042 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1043 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1044 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
1045
1046 glTexImage2D(GL_TEXTURE_2D,
1047 0, // mip level
1048 GL_RGBA,
1049 size.width(),
1050 size.height(),
1051 0, // border
1052 GL_RGBA,
1053 GL_UNSIGNED_BYTE,
1054 NULL);
1055
[email protected]d37231fa2010-04-09 21:16:021056 size_ = size;
1057
[email protected]6217d392010-03-25 22:08:351058 return glGetError() == GL_NO_ERROR;
1059}
1060
1061void Texture::Copy(const gfx::Size& size) {
1062 DCHECK_NE(id_, 0u);
1063 ScopedGLErrorSuppressor suppressor(decoder_);
1064 ScopedTexture2DBinder binder(decoder_, id_);
1065 glCopyTexImage2D(GL_TEXTURE_2D,
1066 0, // level
1067 GL_RGBA,
1068 0, 0,
1069 size.width(),
1070 size.height(),
1071 0); // border
1072}
1073
1074void Texture::Destroy() {
1075 if (id_ != 0) {
1076 ScopedGLErrorSuppressor suppressor(decoder_);
1077 glDeleteTextures(1, &id_);
1078 id_ = 0;
1079 }
1080}
1081
1082RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1083 : decoder_(decoder),
1084 id_(0) {
1085}
1086
1087RenderBuffer::~RenderBuffer() {
1088 // This does not destroy the render buffer because that would require that
1089 // the associated GL context was current. Just check that it was explicitly
1090 // destroyed.
1091 DCHECK_EQ(id_, 0u);
1092}
1093
1094void RenderBuffer::Create() {
1095 ScopedGLErrorSuppressor suppressor(decoder_);
1096 Destroy();
1097 glGenRenderbuffersEXT(1, &id_);
1098}
1099
1100bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format) {
1101 ScopedGLErrorSuppressor suppressor(decoder_);
1102 ScopedRenderBufferBinder binder(decoder_, id_);
1103 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1104 format,
1105 size.width(),
1106 size.height());
1107 return glGetError() == GL_NO_ERROR;
1108}
1109
1110void RenderBuffer::Destroy() {
1111 if (id_ != 0) {
1112 ScopedGLErrorSuppressor suppressor(decoder_);
1113 glDeleteRenderbuffersEXT(1, &id_);
1114 id_ = 0;
1115 }
1116}
1117
1118FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1119 : decoder_(decoder),
1120 id_(0) {
1121}
1122
1123FrameBuffer::~FrameBuffer() {
1124 // This does not destroy the frame buffer because that would require that
1125 // the associated GL context was current. Just check that it was explicitly
1126 // destroyed.
1127 DCHECK_EQ(id_, 0u);
1128}
1129
1130void FrameBuffer::Create() {
1131 ScopedGLErrorSuppressor suppressor(decoder_);
1132 Destroy();
1133 glGenFramebuffersEXT(1, &id_);
1134}
1135
1136void FrameBuffer::AttachRenderTexture(Texture* texture) {
1137 DCHECK_NE(id_, 0u);
1138 ScopedGLErrorSuppressor suppressor(decoder_);
1139 ScopedFrameBufferBinder binder(decoder_, id_);
1140 GLuint attach_id = texture ? texture->id() : 0;
1141 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1142 GL_COLOR_ATTACHMENT0,
1143 GL_TEXTURE_2D,
1144 attach_id,
1145 0);
1146}
1147
1148void FrameBuffer::AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer) {
1149 DCHECK_NE(id_, 0u);
1150 ScopedGLErrorSuppressor suppressor(decoder_);
1151 ScopedFrameBufferBinder binder(decoder_, id_);
1152 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1153 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
1154 GL_DEPTH_ATTACHMENT,
1155 GL_RENDERBUFFER,
1156 attach_id);
1157 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
1158 GL_STENCIL_ATTACHMENT,
1159 GL_RENDERBUFFER,
1160 attach_id);
1161}
1162
1163void FrameBuffer::Clear(GLbitfield buffers) {
1164 ScopedGLErrorSuppressor suppressor(decoder_);
1165 ScopedFrameBufferBinder binder(decoder_, id_);
1166 glClear(buffers);
1167}
1168
1169void FrameBuffer::Destroy() {
1170 if (id_ != 0) {
1171 ScopedGLErrorSuppressor suppressor(decoder_);
1172 glDeleteFramebuffersEXT(1, &id_);
1173 id_ = 0;
1174 }
1175}
1176
1177GLenum FrameBuffer::CheckStatus() {
1178 DCHECK_NE(id_, 0u);
1179 ScopedGLErrorSuppressor suppressor(decoder_);
1180 ScopedFrameBufferBinder binder(decoder_, id_);
1181 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1182}
1183
[email protected]3916c97e2010-02-25 03:20:501184GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1185 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321186}
1187
[email protected]3916c97e2010-02-25 03:20:501188GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
1189 : GLES2Decoder(group),
[email protected]d37231fa2010-04-09 21:16:021190 context_(NULL),
[email protected]96449d2c2009-11-25 00:01:321191 error_bits_(0),
1192 util_(0), // TODO(gman): Set to actual num compress texture formats.
1193 pack_alignment_(4),
1194 unpack_alignment_(4),
[email protected]3916c97e2010-02-25 03:20:501195 active_texture_unit_(0),
1196 black_2d_texture_id_(0),
1197 black_cube_texture_id_(0),
[email protected]96449d2c2009-11-25 00:01:321198 anti_aliased_(false) {
1199}
1200
[email protected]5a6db6c2010-04-22 18:32:061201bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:351202 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:021203 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:351204 uint32 parent_client_texture_id) {
[email protected]4bedba72010-04-20 22:08:541205 DCHECK(context);
[email protected]d37231fa2010-04-09 21:16:021206 DCHECK(!context_);
1207 context_ = context;
1208
[email protected]2f2d7042010-04-14 21:45:581209 // Create a GL context that is kept in a default state and shares a namespace
1210 // with the main GL context.
[email protected]5a6db6c2010-04-22 18:32:061211 default_context_.reset(gfx::GLContext::CreateOffscreenGLContext(
[email protected]4bedba72010-04-20 22:08:541212 context_->GetHandle()));
1213 if (!default_context_.get()) {
[email protected]2f2d7042010-04-14 21:45:581214 Destroy();
1215 return false;
1216 }
1217
[email protected]6217d392010-03-25 22:08:351218 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021219 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351220 if (parent)
1221 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1222
[email protected]246a70452010-03-05 21:53:501223 if (!MakeCurrent()) {
1224 Destroy();
1225 return false;
[email protected]eb54a562010-01-20 21:55:181226 }
1227
[email protected]246a70452010-03-05 21:53:501228 CHECK_GL_ERROR();
1229
1230 if (!group_->Initialize()) {
1231 Destroy();
1232 return false;
1233 }
1234
1235 vertex_attrib_infos_.reset(
1236 new VertexAttribInfo[group_->max_vertex_attribs()]);
1237 texture_units_.reset(
1238 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151239 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
1240 texture_units_[tt].bound_texture_2d =
1241 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1242 texture_units_[tt].bound_texture_cube_map =
1243 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
1244 }
[email protected]246a70452010-03-05 21:53:501245 GLuint ids[2];
1246 glGenTextures(2, ids);
1247 // Make black textures for replacing non-renderable textures.
1248 black_2d_texture_id_ = ids[0];
1249 black_cube_texture_id_ = ids[1];
1250 static int8 black[] = {0, 0, 0, 0};
1251 glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
1252 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
1253 GL_UNSIGNED_BYTE, black);
1254 glBindTexture(GL_TEXTURE_2D, 0);
1255 glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
[email protected]1958e0e2010-04-22 05:17:151256 for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
1257 glTexImage2D(GLES2Util::IndexToGLFaceTarget(ii), 0, GL_RGBA, 1, 1, 0,
1258 GL_RGBA, GL_UNSIGNED_BYTE, black);
[email protected]246a70452010-03-05 21:53:501259 }
1260 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
1261 CHECK_GL_ERROR();
1262
[email protected]d37231fa2010-04-09 21:16:021263#if !defined(UNIT_TEST)
1264 if (context_->IsOffscreen()) {
[email protected]6217d392010-03-25 22:08:351265 // Create the target frame buffer. This is the one that the client renders
1266 // directly to.
1267 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1268 offscreen_target_frame_buffer_->Create();
1269 offscreen_target_color_texture_.reset(new Texture(this));
1270 offscreen_target_color_texture_->Create();
1271 offscreen_target_depth_stencil_render_buffer_.reset(
1272 new RenderBuffer(this));
1273 offscreen_target_depth_stencil_render_buffer_->Create();
1274
1275 // Create the saved offscreen texture. The target frame buffer is copied
1276 // here when SwapBuffers is called.
1277 offscreen_saved_color_texture_.reset(new Texture(this));
1278 offscreen_saved_color_texture_->Create();
1279
[email protected]6217d392010-03-25 22:08:351280 // Map the ID of the saved offscreen texture into the parent so that
1281 // it can reference it.
1282 if (parent_) {
1283 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]6217d392010-03-25 22:08:351284 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:031285 parent_->CreateTextureInfo(parent_client_texture_id, service_id);
[email protected]6217d392010-03-25 22:08:351286 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
1287 }
1288
1289 // Allocate the render buffers at their initial size and check the status
1290 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021291 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351292 if (!UpdateOffscreenFrameBufferSize()) {
1293 DLOG(ERROR) << "Could not allocate offscreen buffer storage.";
1294 Destroy();
1295 return false;
1296 }
1297
1298 // Bind to the new default frame buffer (the offscreen target frame buffer).
1299 // This should now be associated with ID zero.
1300 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
1301 }
[email protected]d37231fa2010-04-09 21:16:021302#endif // UNIT_TEST
[email protected]6217d392010-03-25 22:08:351303
[email protected]76a0ee102010-04-07 21:03:041304#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1305 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1306 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1307 // isn't well documented; it was discovered in the Khronos OpenGL ES
1308 // mailing list archives.
1309 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]de17df392010-04-23 21:09:411310
1311#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
1312 // Initialize GLSL ES to GLSL translator.
1313 if (!ShInitialize()) {
1314 DLOG(ERROR) << "Could not initialize GLSL translator.";
1315 Destroy();
1316 return false;
1317 }
1318#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
1319#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
[email protected]76a0ee102010-04-07 21:03:041320
[email protected]246a70452010-03-05 21:53:501321 return true;
[email protected]96449d2c2009-11-25 00:01:321322}
1323
[email protected]ae51d192010-04-27 00:48:031324bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471325 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031326 if (GetBufferInfo(client_ids[ii])) {
1327 return false;
1328 }
1329 }
1330 scoped_array<GLuint> service_ids(new GLuint[n]);
1331 glGenBuffersARB(n, service_ids.get());
1332 for (GLsizei ii = 0; ii < n; ++ii) {
1333 CreateBufferInfo(client_ids[ii], service_ids[ii]);
1334 }
1335 return true;
1336}
1337
1338bool GLES2DecoderImpl::GenFramebuffersHelper(
1339 GLsizei n, const GLuint* client_ids) {
1340 for (GLsizei ii = 0; ii < n; ++ii) {
1341 if (GetFramebufferInfo(client_ids[ii])) {
1342 return false;
1343 }
1344 }
1345 scoped_array<GLuint> service_ids(new GLuint[n]);
1346 glGenFramebuffersEXT(n, service_ids.get());
1347 for (GLsizei ii = 0; ii < n; ++ii) {
1348 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
1349 }
1350 return true;
1351}
1352
1353bool GLES2DecoderImpl::GenRenderbuffersHelper(
1354 GLsizei n, const GLuint* client_ids) {
1355 for (GLsizei ii = 0; ii < n; ++ii) {
1356 if (GetRenderbufferInfo(client_ids[ii])) {
1357 return false;
1358 }
1359 }
1360 scoped_array<GLuint> service_ids(new GLuint[n]);
1361 glGenRenderbuffersEXT(n, service_ids.get());
1362 for (GLsizei ii = 0; ii < n; ++ii) {
1363 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
1364 }
1365 return true;
1366}
1367
1368bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
1369 for (GLsizei ii = 0; ii < n; ++ii) {
1370 if (GetTextureInfo(client_ids[ii])) {
1371 return false;
1372 }
1373 }
1374 scoped_array<GLuint> service_ids(new GLuint[n]);
1375 glGenTextures(n, service_ids.get());
1376 for (GLsizei ii = 0; ii < n; ++ii) {
1377 CreateTextureInfo(client_ids[ii], service_ids[ii]);
1378 }
1379 return true;
1380}
1381
1382void GLES2DecoderImpl::DeleteBuffersHelper(
1383 GLsizei n, const GLuint* client_ids) {
1384 for (GLsizei ii = 0; ii < n; ++ii) {
1385 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
1386 if (info) {
1387 GLuint service_id = info->service_id();
1388 glDeleteBuffersARB(1, &service_id);
1389 RemoveBufferInfo(client_ids[ii]);
1390 }
[email protected]a93bb842010-02-16 23:03:471391 }
[email protected]07f54fcc2009-12-22 02:46:301392}
1393
[email protected]ae51d192010-04-27 00:48:031394void GLES2DecoderImpl::DeleteFramebuffersHelper(
1395 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:581396 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031397 FramebufferManager::FramebufferInfo* info =
1398 GetFramebufferInfo(client_ids[ii]);
1399 if (info) {
1400 GLuint service_id = info->service_id();
1401 glDeleteFramebuffersEXT(1, &service_id);
1402 RemoveFramebufferInfo(client_ids[ii]);
1403 }
[email protected]a25fa872010-03-25 02:57:581404 }
[email protected]07f54fcc2009-12-22 02:46:301405}
1406
[email protected]ae51d192010-04-27 00:48:031407void GLES2DecoderImpl::DeleteRenderbuffersHelper(
1408 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:581409 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031410 RenderbufferManager::RenderbufferInfo* info =
1411 GetRenderbufferInfo(client_ids[ii]);
1412 if (info) {
1413 GLuint service_id = info->service_id();
1414 glDeleteRenderbuffersEXT(1, &service_id);
1415 RemoveRenderbufferInfo(client_ids[ii]);
1416 }
[email protected]a25fa872010-03-25 02:57:581417 }
[email protected]07f54fcc2009-12-22 02:46:301418}
1419
[email protected]ae51d192010-04-27 00:48:031420void GLES2DecoderImpl::DeleteTexturesHelper(
1421 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471422 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031423 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
1424 if (info) {
1425 GLuint service_id = info->service_id();
1426 glDeleteTextures(1, &service_id);
1427 RemoveTextureInfo(client_ids[ii]);
1428 }
[email protected]a93bb842010-02-16 23:03:471429 }
[email protected]07f54fcc2009-12-22 02:46:301430}
1431
[email protected]43f28f832010-02-03 02:28:481432// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:321433
[email protected]eb54a562010-01-20 21:55:181434bool GLES2DecoderImpl::MakeCurrent() {
1435#if defined(UNIT_TEST)
1436 return true;
[email protected]eb54a562010-01-20 21:55:181437#else
[email protected]d37231fa2010-04-09 21:16:021438 return context_->MakeCurrent();
[email protected]eb54a562010-01-20 21:55:181439#endif
1440}
1441
[email protected]d37231fa2010-04-09 21:16:021442gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() {
1443 if (bound_framebuffer_ != 0) {
1444 int width = 0;
1445 int height = 0;
[email protected]246a70452010-03-05 21:53:501446
[email protected]d37231fa2010-04-09 21:16:021447 // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
1448 // stencil.
1449 GLint fb_type = 0;
1450 glGetFramebufferAttachmentParameterivEXT(
1451 GL_FRAMEBUFFER,
1452 GL_COLOR_ATTACHMENT0,
1453 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
1454 &fb_type);
1455 switch (fb_type) {
1456 case GL_RENDERBUFFER:
1457 {
1458 GLint renderbuffer_id = 0;
1459 glGetFramebufferAttachmentParameterivEXT(
1460 GL_FRAMEBUFFER,
1461 GL_COLOR_ATTACHMENT0,
1462 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1463 &renderbuffer_id);
1464 if (renderbuffer_id != 0) {
1465 glGetRenderbufferParameterivEXT(
1466 GL_RENDERBUFFER,
1467 GL_RENDERBUFFER_WIDTH,
1468 &width);
1469 glGetRenderbufferParameterivEXT(
1470 GL_RENDERBUFFER,
1471 GL_RENDERBUFFER_HEIGHT,
1472 &height);
1473 }
1474 break;
1475 }
1476 case GL_TEXTURE:
1477 {
1478 GLint texture_id = 0;
1479 glGetFramebufferAttachmentParameterivEXT(
1480 GL_FRAMEBUFFER,
1481 GL_COLOR_ATTACHMENT0,
1482 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1483 &texture_id);
1484 if (texture_id != 0) {
[email protected]ae51d192010-04-27 00:48:031485 GLuint client_id = 0;
1486 if (texture_manager()->GetClientId(texture_id, &client_id)) {
1487 TextureManager::TextureInfo* texture_info =
1488 GetTextureInfo(client_id);
1489 if (texture_info) {
1490 GLint level = 0;
1491 GLint face = 0;
1492 glGetFramebufferAttachmentParameterivEXT(
1493 GL_FRAMEBUFFER,
1494 GL_COLOR_ATTACHMENT0,
1495 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
1496 &level);
1497 glGetFramebufferAttachmentParameterivEXT(
1498 GL_FRAMEBUFFER,
1499 GL_COLOR_ATTACHMENT0,
1500 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
1501 &face);
1502 texture_info->GetLevelSize(
1503 face ? face : GL_TEXTURE_2D, level, &width, &height);
1504 }
[email protected]d37231fa2010-04-09 21:16:021505 }
1506 }
1507 break;
1508 }
1509 default:
1510 // unknown so assume width and height are zero.
1511 break;
[email protected]246a70452010-03-05 21:53:501512 }
1513
[email protected]d37231fa2010-04-09 21:16:021514 return gfx::Size(width, height);
1515 } else if (offscreen_target_color_texture_.get()) {
1516 return offscreen_target_color_texture_->size();
[email protected]6217d392010-03-25 22:08:351517 } else {
[email protected]246a70452010-03-05 21:53:501518#if defined(UNIT_TEST)
[email protected]d37231fa2010-04-09 21:16:021519 return gfx::Size(INT_MAX, INT_MAX);
1520#else
1521 return context_->GetSize();
[email protected]246a70452010-03-05 21:53:501522#endif
[email protected]d37231fa2010-04-09 21:16:021523 }
[email protected]246a70452010-03-05 21:53:501524}
1525
[email protected]6217d392010-03-25 22:08:351526bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]d37231fa2010-04-09 21:16:021527 if (offscreen_target_color_texture_->size() == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:351528 return true;
1529
[email protected]2f2d7042010-04-14 21:45:581530 if (parent_) {
1531 // Create the saved offscreen color texture (only accessible to parent).
1532 offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
1533
1534 // Attach the saved offscreen color texture to a frame buffer so we can
1535 // clear it with glClear.
1536 offscreen_target_frame_buffer_->AttachRenderTexture(
1537 offscreen_saved_color_texture_.get());
1538 if (offscreen_target_frame_buffer_->CheckStatus() !=
1539 GL_FRAMEBUFFER_COMPLETE) {
1540 return false;
1541 }
1542
1543#if !defined(UNIT_TEST)
1544 // Clear the saved offscreen color texture. Use default GL context
1545 // to ensure clear is not affected by client set state.
[email protected]1958e0e2010-04-22 05:17:151546 { // NOLINT
[email protected]2f2d7042010-04-14 21:45:581547 ScopedDefaultGLContext scoped_context(this);
1548 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
1549 offscreen_target_frame_buffer_->id());
1550 glClear(GL_COLOR_BUFFER_BIT);
1551 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1552
1553 if (glGetError() != GL_NO_ERROR)
1554 return false;
1555 }
1556#endif
1557 }
1558
[email protected]6217d392010-03-25 22:08:351559 // Reallocate the offscreen target buffers.
[email protected]d37231fa2010-04-09 21:16:021560 if (!offscreen_target_color_texture_->AllocateStorage(
1561 pending_offscreen_size_)) {
[email protected]6217d392010-03-25 22:08:351562 return false;
1563 }
1564
1565 if (!offscreen_target_depth_stencil_render_buffer_->AllocateStorage(
[email protected]d37231fa2010-04-09 21:16:021566 pending_offscreen_size_, GL_DEPTH24_STENCIL8)) {
[email protected]6217d392010-03-25 22:08:351567 return false;
1568 }
1569
[email protected]2f2d7042010-04-14 21:45:581570 // Attach the offscreen target buffers to the target frame buffer.
[email protected]6217d392010-03-25 22:08:351571 offscreen_target_frame_buffer_->AttachRenderTexture(
1572 offscreen_target_color_texture_.get());
1573 offscreen_target_frame_buffer_->AttachDepthStencilRenderBuffer(
1574 offscreen_target_depth_stencil_render_buffer_.get());
1575 if (offscreen_target_frame_buffer_->CheckStatus() !=
1576 GL_FRAMEBUFFER_COMPLETE) {
1577 return false;
1578 }
1579
[email protected]2f2d7042010-04-14 21:45:581580#if !defined(UNIT_TEST)
1581 // Clear offscreen frame buffer to its initial state. Use default GL context
1582 // to ensure clear is not affected by client set state.
[email protected]1958e0e2010-04-22 05:17:151583 { // NOLINT
[email protected]2f2d7042010-04-14 21:45:581584 ScopedDefaultGLContext scoped_context(this);
1585 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
1586 offscreen_target_frame_buffer_->id());
1587 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1588 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1589
1590 if (glGetError() != GL_NO_ERROR)
1591 return false;
1592 }
1593#endif
1594
[email protected]6217d392010-03-25 22:08:351595 if (parent_) {
[email protected]d37231fa2010-04-09 21:16:021596 // Create the saved offscreen color texture (only accessible to parent).
1597 offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
1598
[email protected]2f2d7042010-04-14 21:45:581599 // Update the info about the offscreen saved color texture in the parent.
1600 // The reference to the parent is a weak pointer and will become null if the
1601 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:351602 GLuint service_id = offscreen_saved_color_texture_->id();
1603
1604 TextureManager::TextureInfo* info =
1605 parent_->texture_manager()->GetTextureInfo(service_id);
1606 DCHECK(info);
1607
1608 info->SetLevelInfo(GL_TEXTURE_2D,
1609 0, // level
1610 GL_RGBA,
[email protected]d37231fa2010-04-09 21:16:021611 pending_offscreen_size_.width(),
1612 pending_offscreen_size_.height(),
[email protected]6217d392010-03-25 22:08:351613 1, // depth
1614 0, // border
1615 GL_RGBA,
1616 GL_UNSIGNED_BYTE);
1617 }
1618
[email protected]6217d392010-03-25 22:08:351619 return true;
1620}
1621
[email protected]43f28f832010-02-03 02:28:481622void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
1623 swap_buffers_callback_.reset(callback);
1624}
1625
[email protected]96449d2c2009-11-25 00:01:321626void GLES2DecoderImpl::Destroy() {
[email protected]4bedba72010-04-20 22:08:541627 if (context_) {
1628 MakeCurrent();
[email protected]6217d392010-03-25 22:08:351629
[email protected]4bedba72010-04-20 22:08:541630 // Remove the saved frame buffer mapping from the parent decoder. The
1631 // parent pointer is a weak pointer so it will be null if the parent has
1632 // already been destroyed.
1633 if (parent_) {
1634 // First check the texture has been mapped into the parent. This might not
1635 // be the case if initialization failed midway through.
1636 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]ae51d192010-04-27 00:48:031637 GLuint client_id = 0;
1638 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
1639 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]4bedba72010-04-20 22:08:541640 }
[email protected]6217d392010-03-25 22:08:351641 }
[email protected]6217d392010-03-25 22:08:351642
[email protected]4bedba72010-04-20 22:08:541643 if (offscreen_target_frame_buffer_.get()) {
1644 offscreen_target_frame_buffer_->Destroy();
1645 offscreen_target_frame_buffer_.reset();
1646 }
[email protected]6217d392010-03-25 22:08:351647
[email protected]4bedba72010-04-20 22:08:541648 if (offscreen_target_color_texture_.get()) {
1649 offscreen_target_color_texture_->Destroy();
1650 offscreen_target_color_texture_.reset();
1651 }
[email protected]6217d392010-03-25 22:08:351652
[email protected]4bedba72010-04-20 22:08:541653 if (offscreen_target_depth_stencil_render_buffer_.get()) {
1654 offscreen_target_depth_stencil_render_buffer_->Destroy();
1655 offscreen_target_depth_stencil_render_buffer_.reset();
1656 }
[email protected]6217d392010-03-25 22:08:351657
[email protected]4bedba72010-04-20 22:08:541658 if (offscreen_saved_color_texture_.get()) {
1659 offscreen_saved_color_texture_->Destroy();
1660 offscreen_saved_color_texture_.reset();
1661 }
[email protected]d37231fa2010-04-09 21:16:021662 }
[email protected]2f2d7042010-04-14 21:45:581663
1664 if (default_context_.get()) {
1665 default_context_->Destroy();
1666 default_context_.reset();
1667 }
[email protected]de17df392010-04-23 21:09:411668
1669#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1670#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
1671 // Terminate GLSL translator.
1672 ShFinalize();
1673#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
1674#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
[email protected]96449d2c2009-11-25 00:01:321675}
1676
[email protected]6217d392010-03-25 22:08:351677void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
1678 // We can't resize the render buffers immediately because there might be a
1679 // partial frame rendered into them and we don't want the tail end of that
1680 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021681 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351682}
1683
[email protected]96449d2c2009-11-25 00:01:321684const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
1685 if (command_id > kStartPoint && command_id < kNumCommands) {
1686 return gles2::GetCommandName(static_cast<CommandId>(command_id));
1687 }
1688 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
1689}
1690
1691// Decode command with its arguments, and call the corresponding GL function.
1692// Note: args is a pointer to the command buffer. As such, it could be changed
1693// by a (malicious) client at any time, so if validation has to happen, it
1694// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:141695error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:321696 unsigned int command,
1697 unsigned int arg_count,
1698 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:141699 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191700 if (debug()) {
1701 // TODO(gman): Change output to something useful for NaCl.
[email protected]b9849abf2009-11-25 19:13:191702 printf("cmd: %s\n", GetCommandName(command));
1703 }
[email protected]96449d2c2009-11-25 00:01:321704 unsigned int command_index = command - kStartPoint - 1;
1705 if (command_index < arraysize(g_command_info)) {
1706 const CommandInfo& info = g_command_info[command_index];
1707 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
1708 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
1709 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:191710 uint32 immediate_data_size =
1711 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:321712 switch (command) {
1713 #define GLES2_CMD_OP(name) \
1714 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:191715 result = Handle ## name( \
1716 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321717 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:191718 break; \
[email protected]96449d2c2009-11-25 00:01:321719
1720 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:321721 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:381722 }
1723 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:301724 GLenum error;
1725 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:381726 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:291727 SetGLError(error, NULL);
[email protected]bf0985e2009-12-17 03:04:381728 printf("GL ERROR b4: %s\n", GetCommandName(command));
[email protected]b9849abf2009-11-25 19:13:191729 }
[email protected]96449d2c2009-11-25 00:01:321730 }
1731 } else {
[email protected]f7a64ee2010-02-01 22:24:141732 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:321733 }
[email protected]b9849abf2009-11-25 19:13:191734 } else {
1735 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:321736 }
[email protected]b9849abf2009-11-25 19:13:191737 return result;
[email protected]96449d2c2009-11-25 00:01:321738}
1739
[email protected]ae51d192010-04-27 00:48:031740void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
1741 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:501742}
1743
[email protected]ae51d192010-04-27 00:48:031744bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
1745 if (GetProgramInfo(client_id)) {
1746 return false;
1747 }
[email protected]96449d2c2009-11-25 00:01:321748 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:031749 if (service_id != 0) {
1750 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:321751 }
[email protected]ae51d192010-04-27 00:48:031752 return true;
[email protected]96449d2c2009-11-25 00:01:321753}
1754
[email protected]ae51d192010-04-27 00:48:031755bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
1756 if (GetShaderInfo(client_id)) {
1757 return false;
[email protected]96449d2c2009-11-25 00:01:321758 }
[email protected]ae51d192010-04-27 00:48:031759 GLuint service_id = glCreateShader(type);
1760 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:381761 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:031762 }
1763 return true;
[email protected]96449d2c2009-11-25 00:01:321764}
1765
[email protected]86093972010-03-11 00:13:561766bool GLES2DecoderImpl::ValidateGLenumCompressedTextureInternalFormat(GLenum) {
1767 // TODO(gman): Add support for compressed texture formats.
1768 return false;
1769}
1770
[email protected]3916c97e2010-02-25 03:20:501771void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:451772 GLuint texture_index = texture_unit - GL_TEXTURE0;
1773 if (texture_index > group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:291774 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:501775 return;
1776 }
[email protected]36cef8ce2010-03-16 07:34:451777 active_texture_unit_ = texture_index;
1778 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:501779}
1780
[email protected]051b1372010-04-12 02:42:081781void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:501782 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:081783 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:031784 if (client_id != 0) {
1785 info = GetBufferInfo(client_id);
1786 if (!info) {
1787 // It's a new id so make a buffer info for it.
1788 glGenBuffersARB(1, &service_id);
1789 CreateBufferInfo(client_id, service_id);
1790 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:101791 IdAllocator* id_allocator =
1792 group_->GetIdAllocator(id_namespaces::kBuffers);
1793 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:031794 }
[email protected]051b1372010-04-12 02:42:081795 }
[email protected]ae51d192010-04-27 00:48:031796 if (info) {
[email protected]0c86dbf2010-03-05 08:14:111797 // Check the buffer exists
1798 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:031799 if ((info->target() != 0 && info->target() != target)) {
[email protected]8eee29c2010-04-29 03:38:291800 SetGLError(GL_INVALID_OPERATION,
1801 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:471802 return;
1803 }
[email protected]0c86dbf2010-03-05 08:14:111804 if (info->target() == 0) {
1805 info->set_target(target);
1806 }
[email protected]ae51d192010-04-27 00:48:031807 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:471808 }
[email protected]96449d2c2009-11-25 00:01:321809 switch (target) {
1810 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501811 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321812 break;
1813 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501814 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321815 break;
1816 default:
[email protected]a93bb842010-02-16 23:03:471817 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:321818 break;
1819 }
[email protected]051b1372010-04-12 02:42:081820 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:321821}
1822
[email protected]051b1372010-04-12 02:42:081823void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
1824 FramebufferManager::FramebufferInfo* info = NULL;
1825 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:031826 if (client_id != 0) {
1827 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:081828 if (!info) {
[email protected]ae51d192010-04-27 00:48:031829 // It's a new id so make a framebuffer info for it.
1830 glGenFramebuffersEXT(1, &service_id);
1831 CreateFramebufferInfo(client_id, service_id);
1832 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:101833 IdAllocator* id_allocator =
1834 group_->GetIdAllocator(id_namespaces::kFramebuffers);
1835 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:031836 } else {
1837 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:081838 }
1839 }
1840 bound_framebuffer_ = info;
[email protected]6217d392010-03-25 22:08:351841
1842 // When rendering to an offscreen frame buffer, instead of unbinding from
1843 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:081844 if (info == NULL && offscreen_target_frame_buffer_.get())
1845 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:351846
[email protected]051b1372010-04-12 02:42:081847 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:561848}
1849
[email protected]051b1372010-04-12 02:42:081850void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
1851 RenderbufferManager::RenderbufferInfo* info = NULL;
1852 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:031853 if (client_id != 0) {
1854 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:081855 if (!info) {
[email protected]ae51d192010-04-27 00:48:031856 // It's a new id so make a renderbuffer info for it.
1857 glGenRenderbuffersEXT(1, &service_id);
1858 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:101859 info = GetRenderbufferInfo(client_id);
1860 IdAllocator* id_allocator =
1861 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
1862 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:031863 } else {
1864 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:081865 }
1866 }
1867 bound_renderbuffer_ = info;
1868 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:561869}
1870
[email protected]051b1372010-04-12 02:42:081871void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:031872 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:081873 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:031874 if (client_id != 0) {
1875 info = GetTextureInfo(client_id);
1876 if (!info) {
1877 // It's a new id so make a texture info for it.
1878 glGenTextures(1, &service_id);
1879 CreateTextureInfo(client_id, service_id);
1880 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:101881 IdAllocator* id_allocator =
1882 group_->GetIdAllocator(id_namespaces::kTextures);
1883 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:031884 }
1885 } else {
1886 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:081887 }
[email protected]ae51d192010-04-27 00:48:031888
[email protected]1958e0e2010-04-22 05:17:151889 // Check the texture exists
1890 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:031891 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:291892 SetGLError(GL_INVALID_OPERATION,
1893 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:151894 return;
1895 }
1896 if (info->target() == 0) {
1897 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:471898 }
[email protected]ae51d192010-04-27 00:48:031899 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:501900 TextureUnit& unit = texture_units_[active_texture_unit_];
1901 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:471902 switch (target) {
1903 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501904 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:471905 break;
1906 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:501907 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:471908 break;
1909 default:
1910 NOTREACHED(); // Validation should prevent us getting here.
1911 break;
1912 }
1913}
1914
[email protected]07f54fcc2009-12-22 02:46:301915void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501916 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301917 vertex_attrib_infos_[index].set_enabled(false);
[email protected]8a837bb2010-01-05 00:21:241918 glDisableVertexAttribArray(index);
[email protected]07f54fcc2009-12-22 02:46:301919 } else {
[email protected]8eee29c2010-04-29 03:38:291920 SetGLError(GL_INVALID_VALUE,
1921 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:301922 }
1923}
1924
1925void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501926 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301927 vertex_attrib_infos_[index].set_enabled(true);
1928 glEnableVertexAttribArray(index);
1929 } else {
[email protected]8eee29c2010-04-29 03:38:291930 SetGLError(GL_INVALID_VALUE,
1931 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:301932 }
1933}
1934
[email protected]a93bb842010-02-16 23:03:471935void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:501936 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1937 if (!info || !info->MarkMipmapsGenerated()) {
[email protected]8eee29c2010-04-29 03:38:291938 SetGLError(GL_INVALID_OPERATION,
1939 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:471940 return;
1941 }
1942 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:471943}
1944
[email protected]b273e432010-04-12 17:23:581945bool GLES2DecoderImpl::GetHelper(
1946 GLenum pname, GLint* params, GLsizei* num_written) {
1947 DCHECK(params);
1948 DCHECK(num_written);
1949 switch (pname) {
[email protected]58ae32f2010-04-14 01:26:041950#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]b273e432010-04-12 17:23:581951 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1952 *num_written = 1;
[email protected]58ae32f2010-04-14 01:26:041953 *params = GL_RGBA; // TODO(gman): get correct format.
[email protected]b273e432010-04-12 17:23:581954 return true;
1955 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1956 *num_written = 1;
1957 *params = GL_UNSIGNED_BYTE; // TODO(gman): get correct type.
1958 return true;
1959 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
[email protected]58ae32f2010-04-14 01:26:041960 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, params);
[email protected]b273e432010-04-12 17:23:581961 *num_written = 1;
[email protected]58ae32f2010-04-14 01:26:041962 *params /= 4;
[email protected]b273e432010-04-12 17:23:581963 return true;
1964 case GL_MAX_VARYING_VECTORS:
[email protected]58ae32f2010-04-14 01:26:041965 glGetIntegerv(GL_MAX_VARYING_FLOATS, params);
[email protected]b273e432010-04-12 17:23:581966 *num_written = 1;
[email protected]58ae32f2010-04-14 01:26:041967 *params /= 4;
[email protected]b273e432010-04-12 17:23:581968 return true;
1969 case GL_MAX_VERTEX_UNIFORM_VECTORS:
[email protected]58ae32f2010-04-14 01:26:041970 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, params);
[email protected]b273e432010-04-12 17:23:581971 *num_written = 1;
[email protected]58ae32f2010-04-14 01:26:041972 *params /= 4;
[email protected]b273e432010-04-12 17:23:581973 return true;
[email protected]58ae32f2010-04-14 01:26:041974#endif
[email protected]b273e432010-04-12 17:23:581975 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1976 *num_written = 1;
1977 *params = 0; // We don't support compressed textures.
1978 return true;
1979 case GL_NUM_SHADER_BINARY_FORMATS:
1980 *num_written = 1;
1981 *params = 0; // We don't support binary shader formats.
1982 return true;
1983 case GL_SHADER_BINARY_FORMATS:
1984 *num_written = 0;
1985 return true; // We don't support binary shader format.s
1986 case GL_SHADER_COMPILER:
1987 *num_written = 1;
1988 *params = GL_TRUE;
1989 return true;
[email protected]6b8cf1a2010-05-06 16:13:581990 case GL_ARRAY_BUFFER_BINDING:
1991 *num_written = 1;
1992 if (bound_array_buffer_) {
1993 GLuint client_id = 0;
1994 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
1995 &client_id);
1996 *params = client_id;
1997 } else {
1998 *params = 0;
1999 }
2000 return true;
2001 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
2002 *num_written = 1;
2003 if (bound_element_array_buffer_) {
2004 GLuint client_id = 0;
2005 buffer_manager()->GetClientId(bound_element_array_buffer_->service_id(),
2006 &client_id);
2007 *params = client_id;
2008 } else {
2009 *params = 0;
2010 }
2011 return true;
2012 case GL_FRAMEBUFFER_BINDING:
2013 *num_written = 1;
2014 if (bound_framebuffer_) {
2015 GLuint client_id = 0;
2016 framebuffer_manager()->GetClientId(
2017 bound_framebuffer_->service_id(), &client_id);
2018 *params = client_id;
2019 } else {
2020 *params = 0;
2021 }
2022 return true;
2023 case GL_RENDERBUFFER_BINDING:
2024 *num_written = 1;
2025 if (bound_renderbuffer_) {
2026 GLuint client_id = 0;
2027 renderbuffer_manager()->GetClientId(
2028 bound_renderbuffer_->service_id(), &client_id);
2029 *params = client_id;
2030 } else {
2031 *params = 0;
2032 }
2033 return true;
2034 case GL_CURRENT_PROGRAM:
2035 *num_written = 1;
2036 if (current_program_) {
2037 GLuint client_id = 0;
2038 program_manager()->GetClientId(
2039 current_program_->service_id(), &client_id);
2040 *params = client_id;
2041 } else {
2042 *params = 0;
2043 }
2044 return true;
2045 case GL_TEXTURE_BINDING_2D: {
2046 *num_written = 1;
2047 TextureUnit& unit = texture_units_[active_texture_unit_];
2048 if (unit.bound_texture_2d) {
2049 GLuint client_id = 0;
2050 texture_manager()->GetClientId(
2051 unit.bound_texture_2d->service_id(), &client_id);
2052 *params = client_id;
2053 } else {
2054 *params = 0;
2055 }
2056 return true;
2057 }
2058 case GL_TEXTURE_BINDING_CUBE_MAP: {
2059 *num_written = 1;
2060 TextureUnit& unit = texture_units_[active_texture_unit_];
2061 if (unit.bound_texture_cube_map) {
2062 GLuint client_id = 0;
2063 texture_manager()->GetClientId(
2064 unit.bound_texture_cube_map->service_id(), &client_id);
2065 *params = client_id;
2066 } else {
2067 *params = 0;
2068 }
2069 return true;
2070 }
[email protected]b273e432010-04-12 17:23:582071 default:
2072 return false;
2073 }
2074}
2075
2076void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
2077 DCHECK(params);
2078 GLint values[16];
2079 GLsizei num_written;
2080 if (GetHelper(pname, &values[0], &num_written)) {
2081 DCHECK_LE(static_cast<size_t>(num_written), arraysize(values));
2082 for (GLsizei ii = 0; ii < num_written; ++ii) {
2083 params[ii] = static_cast<GLboolean>(values[ii]);
2084 }
2085 } else {
2086 glGetBooleanv(pname, params);
2087 }
2088}
2089
2090void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
2091 DCHECK(params);
2092 GLint values[16];
2093 GLsizei num_written;
2094 if (GetHelper(pname, &values[0], &num_written)) {
2095 DCHECK_LE(static_cast<size_t>(num_written), arraysize(values));
2096 for (GLsizei ii = 0; ii < num_written; ++ii) {
2097 params[ii] = static_cast<GLfloat>(values[ii]);
2098 }
2099 } else {
2100 glGetFloatv(pname, params);
2101 }
2102}
2103
2104void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
2105 DCHECK(params);
2106 GLsizei num_written;
2107 if (!GetHelper(pname, params, &num_written)) {
2108 glGetIntegerv(pname, params);
2109 }
2110}
2111
[email protected]a0c3e972010-04-21 00:49:132112void GLES2DecoderImpl::DoGetProgramiv(
2113 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:582114 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2115 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:132116 if (!info) {
[email protected]a0c3e972010-04-21 00:49:132117 return;
2118 }
2119 info->GetProgramiv(pname, params);
2120}
2121
[email protected]558847a2010-03-24 07:02:542122error::Error GLES2DecoderImpl::HandleBindAttribLocation(
2123 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:582124 GLuint program = static_cast<GLuint>(c.program);
2125 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2126 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032127 if (!info) {
[email protected]558847a2010-03-24 07:02:542128 return error::kNoError;
2129 }
2130 GLuint index = static_cast<GLuint>(c.index);
2131 uint32 name_size = c.data_size;
2132 const char* name = GetSharedMemoryAs<const char*>(
2133 c.name_shm_id, c.name_shm_offset, name_size);
2134 if (name == NULL) {
2135 return error::kOutOfBounds;
2136 }
2137 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:032138 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542139 return error::kNoError;
2140}
2141
2142error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
2143 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:582144 GLuint program = static_cast<GLuint>(c.program);
2145 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2146 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032147 if (!info) {
[email protected]558847a2010-03-24 07:02:542148 return error::kNoError;
2149 }
2150 GLuint index = static_cast<GLuint>(c.index);
2151 uint32 name_size = c.data_size;
2152 const char* name = GetImmediateDataAs<const char*>(
2153 c, name_size, immediate_data_size);
2154 if (name == NULL) {
2155 return error::kOutOfBounds;
2156 }
2157 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:032158 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542159 return error::kNoError;
2160}
2161
2162error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
2163 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:582164 GLuint program = static_cast<GLuint>(c.program);
2165 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2166 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032167 if (!info) {
[email protected]558847a2010-03-24 07:02:542168 return error::kNoError;
2169 }
2170 GLuint index = static_cast<GLuint>(c.index);
2171 Bucket* bucket = GetBucket(c.name_bucket_id);
2172 if (!bucket || bucket->size() == 0) {
2173 return error::kInvalidArguments;
2174 }
2175 std::string name_str;
2176 bucket->GetAsString(&name_str);
[email protected]ae51d192010-04-27 00:48:032177 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542178 return error::kNoError;
2179}
2180
[email protected]f7a64ee2010-02-01 22:24:142181error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:462182 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:032183 GLuint client_id = c.shader;
2184 if (client_id) {
2185 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
2186 if (info) {
2187 glDeleteShader(info->service_id());
2188 RemoveShaderInfo(client_id);
2189 } else {
[email protected]8eee29c2010-04-29 03:38:292190 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:032191 }
[email protected]96449d2c2009-11-25 00:01:322192 }
[email protected]f7a64ee2010-02-01 22:24:142193 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322194}
2195
[email protected]f7a64ee2010-02-01 22:24:142196error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:462197 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:032198 GLuint client_id = c.program;
2199 if (client_id) {
2200 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
2201 if (info) {
2202 glDeleteProgram(info->service_id());
2203 RemoveProgramInfo(client_id);
2204 } else {
[email protected]8eee29c2010-04-29 03:38:292205 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:032206 }
[email protected]96449d2c2009-11-25 00:01:322207 }
[email protected]f7a64ee2010-02-01 22:24:142208 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322209}
2210
[email protected]066849e32010-05-03 19:14:102211void GLES2DecoderImpl::DoDeleteSharedIds(
2212 GLuint namespace_id, GLsizei n, const GLuint* ids) {
2213 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2214 for (GLsizei ii = 0; ii < n; ++ii) {
2215 id_allocator->FreeID(ids[ii]);
2216 }
2217}
2218
2219error::Error GLES2DecoderImpl::HandleDeleteSharedIds(
2220 uint32 immediate_data_size, const gles2::DeleteSharedIds& c) {
2221 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2222 GLsizei n = static_cast<GLsizei>(c.n);
2223 uint32 data_size;
2224 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2225 return error::kOutOfBounds;
2226 }
2227 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
2228 c.ids_shm_id, c.ids_shm_offset, data_size);
2229 if (n < 0) {
2230 SetGLError(GL_INVALID_VALUE, "DeleteSharedIds: n < 0");
2231 return error::kNoError;
2232 }
2233 if (ids == NULL) {
2234 return error::kOutOfBounds;
2235 }
2236 DoDeleteSharedIds(namespace_id, n, ids);
2237 return error::kNoError;
2238}
2239
2240void GLES2DecoderImpl::DoGenSharedIds(
2241 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
2242 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2243 if (id_offset == 0) {
2244 for (GLsizei ii = 0; ii < n; ++ii) {
2245 ids[ii] = id_allocator->AllocateID();
2246 }
2247 } else {
2248 for (GLsizei ii = 0; ii < n; ++ii) {
2249 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
2250 id_offset = ids[ii] + 1;
2251 }
2252 }
2253}
2254
2255error::Error GLES2DecoderImpl::HandleGenSharedIds(
2256 uint32 immediate_data_size, const gles2::GenSharedIds& c) {
2257 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2258 GLuint id_offset = static_cast<GLuint>(c.id_offset);
2259 GLsizei n = static_cast<GLsizei>(c.n);
2260 uint32 data_size;
2261 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2262 return error::kOutOfBounds;
2263 }
2264 GLuint* ids = GetSharedMemoryAs<GLuint*>(
2265 c.ids_shm_id, c.ids_shm_offset, data_size);
2266 if (n < 0) {
2267 SetGLError(GL_INVALID_VALUE, "GenSharedIds: n < 0");
2268 return error::kNoError;
2269 }
2270 if (ids == NULL) {
2271 return error::kOutOfBounds;
2272 }
2273 DoGenSharedIds(namespace_id, id_offset, n, ids);
2274 return error::kNoError;
2275}
2276
2277void GLES2DecoderImpl::DoRegisterSharedIds(
2278 GLuint namespace_id, GLsizei n, const GLuint* ids) {
2279 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2280 for (GLsizei ii = 0; ii < n; ++ii) {
2281 if (!id_allocator->MarkAsUsed(ids[ii])) {
2282 for (GLsizei jj = 0; jj < ii; ++jj) {
2283 id_allocator->FreeID(ids[jj]);
2284 }
2285 SetGLError(
2286 GL_INVALID_VALUE,
2287 "RegisterSharedIds: attempt to register id that already exists");
2288 return;
2289 }
2290 }
2291}
2292
2293error::Error GLES2DecoderImpl::HandleRegisterSharedIds(
2294 uint32 immediate_data_size, const gles2::RegisterSharedIds& c) {
2295 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2296 GLsizei n = static_cast<GLsizei>(c.n);
2297 uint32 data_size;
2298 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2299 return error::kOutOfBounds;
2300 }
2301 GLuint* ids = GetSharedMemoryAs<GLuint*>(
2302 c.ids_shm_id, c.ids_shm_offset, data_size);
2303 if (n < 0) {
2304 SetGLError(GL_INVALID_VALUE, "RegisterSharedIds: n < 0");
2305 return error::kNoError;
2306 }
2307 if (ids == NULL) {
2308 return error::kOutOfBounds;
2309 }
2310 DoRegisterSharedIds(namespace_id, n, ids);
2311 return error::kNoError;
2312}
2313
[email protected]07f54fcc2009-12-22 02:46:302314void GLES2DecoderImpl::DoDrawArrays(
2315 GLenum mode, GLint first, GLsizei count) {
2316 if (IsDrawValid(first + count - 1)) {
[email protected]3916c97e2010-02-25 03:20:502317 bool has_non_renderable_textures;
2318 SetBlackTextureForNonRenderableTextures(&has_non_renderable_textures);
[email protected]07f54fcc2009-12-22 02:46:302319 glDrawArrays(mode, first, count);
[email protected]3916c97e2010-02-25 03:20:502320 if (has_non_renderable_textures) {
2321 RestoreStateForNonRenderableTextures();
2322 }
[email protected]07f54fcc2009-12-22 02:46:302323 }
2324}
2325
[email protected]36cef8ce2010-03-16 07:34:452326void GLES2DecoderImpl::DoFramebufferRenderbuffer(
2327 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:032328 GLuint client_renderbuffer_id) {
[email protected]051b1372010-04-12 02:42:082329 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292330 SetGLError(GL_INVALID_OPERATION,
2331 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452332 return;
2333 }
[email protected]ae51d192010-04-27 00:48:032334 GLuint service_id = 0;
2335 if (client_renderbuffer_id) {
2336 RenderbufferManager::RenderbufferInfo* info =
2337 GetRenderbufferInfo(client_renderbuffer_id);
2338 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292339 SetGLError(GL_INVALID_OPERATION,
2340 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:032341 return;
2342 }
2343 service_id = info->service_id();
2344 }
2345 glFramebufferRenderbufferEXT(
2346 target, attachment, renderbuffertarget, service_id);
[email protected]36cef8ce2010-03-16 07:34:452347}
2348
2349GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]051b1372010-04-12 02:42:082350 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452351 return GL_FRAMEBUFFER_COMPLETE;
2352 }
2353 return glCheckFramebufferStatusEXT(target);
2354}
2355
2356void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:032357 GLenum target, GLenum attachment, GLenum textarget,
2358 GLuint client_texture_id, GLint level) {
[email protected]051b1372010-04-12 02:42:082359 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292360 SetGLError(GL_INVALID_OPERATION,
2361 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:452362 return;
2363 }
[email protected]ae51d192010-04-27 00:48:032364 GLuint service_id = 0;
2365 if (client_texture_id) {
2366 TextureManager::TextureInfo* info = GetTextureInfo(client_texture_id);
2367 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292368 SetGLError(GL_INVALID_OPERATION,
2369 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:032370 return;
2371 }
2372 service_id = info->service_id();
2373 }
2374 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]36cef8ce2010-03-16 07:34:452375}
2376
2377void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
2378 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082379 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292380 SetGLError(GL_INVALID_OPERATION,
2381 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452382 return;
2383 }
2384 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
2385}
2386
2387void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
2388 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082389 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:292390 SetGLError(GL_INVALID_OPERATION,
2391 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452392 return;
2393 }
2394 glGetRenderbufferParameterivEXT(target, pname, params);
2395}
2396
2397void GLES2DecoderImpl::DoRenderbufferStorage(
2398 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:082399 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:292400 SetGLError(GL_INVALID_OPERATION,
2401 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452402 return;
2403 }
2404 glRenderbufferStorageEXT(target, internalformat, width, height);
2405}
2406
[email protected]07f54fcc2009-12-22 02:46:302407void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]6b8cf1a2010-05-06 16:13:582408 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2409 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:472410 if (!info) {
[email protected]a93bb842010-02-16 23:03:472411 return;
2412 }
[email protected]ae51d192010-04-27 00:48:032413 glLinkProgram(info->service_id());
[email protected]6b8cf1a2010-05-06 16:13:582414 GLint success = 0;
2415 glGetProgramiv(info->service_id(), GL_LINK_STATUS, &success);
2416 if (success) {
[email protected]a93bb842010-02-16 23:03:472417 info->Update();
[email protected]6b8cf1a2010-05-06 16:13:582418 } else {
2419 info->Reset();
[email protected]07f54fcc2009-12-22 02:46:302420 }
2421};
2422
[email protected]3916c97e2010-02-25 03:20:502423void GLES2DecoderImpl::DoTexParameterf(
2424 GLenum target, GLenum pname, GLfloat param) {
2425 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:302426 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292427 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]07f54fcc2009-12-22 02:46:302428 } else {
[email protected]3916c97e2010-02-25 03:20:502429 info->SetParameter(pname, static_cast<GLint>(param));
2430 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:302431 }
2432}
2433
[email protected]3916c97e2010-02-25 03:20:502434void GLES2DecoderImpl::DoTexParameteri(
2435 GLenum target, GLenum pname, GLint param) {
2436 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2437 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292438 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502439 } else {
2440 info->SetParameter(pname, param);
2441 glTexParameteri(target, pname, param);
2442 }
2443}
2444
2445void GLES2DecoderImpl::DoTexParameterfv(
2446 GLenum target, GLenum pname, const GLfloat* params) {
2447 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2448 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292449 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502450 } else {
2451 info->SetParameter(pname, *reinterpret_cast<const GLint*>(params));
2452 glTexParameterfv(target, pname, params);
2453 }
2454}
2455
2456void GLES2DecoderImpl::DoTexParameteriv(
2457 GLenum target, GLenum pname, const GLint* params) {
2458 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2459 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292460 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502461 } else {
2462 info->SetParameter(pname, *params);
2463 glTexParameteriv(target, pname, params);
2464 }
2465}
2466
2467void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
2468 if (!current_program_ || current_program_->IsDeleted()) {
2469 // The program does not exist.
[email protected]8eee29c2010-04-29 03:38:292470 SetGLError(GL_INVALID_OPERATION, "glUniform1i: no program in use");
[email protected]3916c97e2010-02-25 03:20:502471 return;
2472 }
2473 current_program_->SetSamplers(location, 1, &v0);
2474 glUniform1i(location, v0);
2475}
2476
2477void GLES2DecoderImpl::DoUniform1iv(
2478 GLint location, GLsizei count, const GLint *value) {
2479 if (!current_program_ || current_program_->IsDeleted()) {
2480 // The program does not exist.
[email protected]8eee29c2010-04-29 03:38:292481 SetGLError(GL_INVALID_OPERATION, "glUniform1iv: no program in use");
[email protected]3916c97e2010-02-25 03:20:502482 return;
2483 }
2484 current_program_->SetSamplers(location, count, value);
2485 glUniform1iv(location, count, value);
2486}
2487
2488void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:032489 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:502490 ProgramManager::ProgramInfo* info = NULL;
2491 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:582492 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:502493 if (!info) {
[email protected]ae51d192010-04-27 00:48:032494 return;
2495 }
2496 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:502497 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:292498 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:502499 return;
2500 }
[email protected]ae51d192010-04-27 00:48:032501 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:502502 }
2503 current_program_ = info;
[email protected]ae51d192010-04-27 00:48:032504 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:502505}
2506
[email protected]96449d2c2009-11-25 00:01:322507GLenum GLES2DecoderImpl::GetGLError() {
2508 // Check the GL error first, then our wrapped error.
2509 GLenum error = glGetError();
2510 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:372511 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:322512 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:292513 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:322514 break;
2515 }
2516 }
2517 }
2518
2519 if (error != GL_NO_ERROR) {
2520 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:292521 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322522 }
2523 return error;
2524}
2525
[email protected]8eee29c2010-04-29 03:38:292526void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
2527 if (msg) {
2528 last_error_ = msg;
2529 DLOG(ERROR) << last_error_;
2530 }
[email protected]ddd968b82010-03-02 00:44:292531 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322532}
2533
[email protected]07f54fcc2009-12-22 02:46:302534void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
2535 GLenum error;
2536 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:292537 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:302538 }
2539}
2540
[email protected]6217d392010-03-25 22:08:352541void GLES2DecoderImpl::ClearRealGLErrors() {
2542 GLenum error;
2543 while ((error = glGetError()) != GL_NO_ERROR) {
2544 NOTREACHED() << "GL error " << error << " was unhandled.";
2545 }
2546}
2547
[email protected]07f54fcc2009-12-22 02:46:302548bool GLES2DecoderImpl::VertexAttribInfo::CanAccess(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:502549 if (!enabled_) {
2550 return true;
2551 }
2552
2553 if (!buffer_ || buffer_->IsDeleted()) {
2554 return false;
2555 }
2556
2557 // The number of elements that can be accessed.
2558 GLsizeiptr buffer_size = buffer_->size();
2559 if (offset_ > buffer_size || real_stride_ == 0) {
2560 return false;
2561 }
2562
2563 uint32 usable_size = buffer_size - offset_;
2564 GLuint num_elements = usable_size / real_stride_ +
2565 ((usable_size % real_stride_) >=
2566 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
2567 return index < num_elements;
2568}
2569
2570void GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures(
2571 bool* has_non_renderable_textures) {
2572 DCHECK(has_non_renderable_textures);
2573 DCHECK(current_program_);
2574 DCHECK(!current_program_->IsDeleted());
2575 *has_non_renderable_textures = false;
2576 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
2577 current_program_->sampler_indices();
2578 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
2579 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2580 current_program_->GetUniformInfo(sampler_indices[ii]);
2581 DCHECK(uniform_info);
2582 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
2583 GLuint texture_unit_index = uniform_info->texture_units[jj];
2584 if (texture_unit_index < group_->max_texture_units()) {
2585 TextureUnit& texture_unit = texture_units_[texture_unit_index];
2586 TextureManager::TextureInfo* texture_info =
2587 uniform_info->type == GL_SAMPLER_2D ?
2588 texture_unit.bound_texture_2d :
2589 texture_unit.bound_texture_cube_map;
2590 if (!texture_info || !texture_info->CanRender()) {
2591 *has_non_renderable_textures = true;
2592 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
2593 glBindTexture(
2594 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
2595 GL_TEXTURE_CUBE_MAP,
2596 uniform_info->type == GL_SAMPLER_2D ? black_2d_texture_id_ :
2597 black_cube_texture_id_);
2598 }
2599 }
2600 // else: should this be an error?
2601 }
2602 }
2603}
2604
2605void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
2606 DCHECK(current_program_);
2607 DCHECK(!current_program_->IsDeleted());
2608 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
2609 current_program_->sampler_indices();
2610 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
2611 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2612 current_program_->GetUniformInfo(sampler_indices[ii]);
2613 DCHECK(uniform_info);
2614 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
2615 GLuint texture_unit_index = uniform_info->texture_units[jj];
2616 if (texture_unit_index < group_->max_texture_units()) {
2617 TextureUnit& texture_unit = texture_units_[texture_unit_index];
2618 TextureManager::TextureInfo* texture_info =
2619 uniform_info->type == GL_SAMPLER_2D ?
2620 texture_unit.bound_texture_2d :
2621 texture_unit.bound_texture_cube_map;
2622 if (!texture_info || !texture_info->CanRender()) {
2623 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
2624 // Get the texture info that was previously bound here.
2625 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
2626 texture_unit.bound_texture_2d :
2627 texture_unit.bound_texture_cube_map;
2628 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:032629 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:502630 }
2631 }
2632 }
2633 }
2634 // Set the active texture back to whatever the user had it as.
2635 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:302636}
2637
2638bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]3916c97e2010-02-25 03:20:502639 if (!current_program_ || current_program_->IsDeleted()) {
2640 // The program does not exist.
2641 // But GL says no ERROR.
2642 return false;
2643 }
2644 // Validate that all attribs current program needs are setup correctly.
2645 const ProgramManager::ProgramInfo::AttribInfoVector& infos =
2646 current_program_->GetAttribInfos();
2647 for (size_t ii = 0; ii < infos.size(); ++ii) {
2648 GLint location = infos[ii].location;
2649 if (location < 0) {
2650 return false;
2651 }
2652 DCHECK_LT(static_cast<GLuint>(location), group_->max_vertex_attribs());
2653 if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) {
[email protected]8eee29c2010-04-29 03:38:292654 SetGLError(GL_INVALID_OPERATION,
2655 "glDrawXXX: attempt to access out of range vertices");
[email protected]1d32bc82010-01-13 22:06:462656 return false;
2657 }
[email protected]07f54fcc2009-12-22 02:46:302658 }
[email protected]3916c97e2010-02-25 03:20:502659 return true;
[email protected]07f54fcc2009-12-22 02:46:302660};
2661
[email protected]f7a64ee2010-02-01 22:24:142662error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:192663 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:502664 if (!bound_element_array_buffer_ ||
2665 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:292666 SetGLError(GL_INVALID_OPERATION,
2667 "glDrawElements: No element array buffer bound");
2668 return error::kNoError;
2669 }
2670
2671 GLenum mode = c.mode;
2672 GLsizei count = c.count;
2673 GLenum type = c.type;
2674 int32 offset = c.index_offset;
2675 if (count < 0) {
2676 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
2677 return error::kNoError;
2678 }
2679 if (offset < 0) {
2680 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
2681 return error::kNoError;
2682 }
2683 if (!ValidateGLenumDrawMode(mode)) {
2684 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
2685 return error::kNoError;
2686 }
2687 if (!ValidateGLenumIndexType(type)) {
2688 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
2689 return error::kNoError;
2690 }
2691
2692 GLuint max_vertex_accessed;
2693 if (!bound_element_array_buffer_->GetMaxValueForRange(
2694 offset, count, type, &max_vertex_accessed)) {
2695 SetGLError(GL_INVALID_OPERATION,
2696 "glDrawElements: range out of bounds for buffer");
2697 return error::kNoError;
2698 }
2699
2700 if (IsDrawValid(max_vertex_accessed)) {
2701 bool has_non_renderable_textures;
2702 SetBlackTextureForNonRenderableTextures(
2703 &has_non_renderable_textures);
2704 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
2705 glDrawElements(mode, count, type, indices);
2706 if (has_non_renderable_textures) {
2707 RestoreStateForNonRenderableTextures();
[email protected]ba3176a2009-12-16 18:19:462708 }
[email protected]96449d2c2009-11-25 00:01:322709 }
[email protected]f7a64ee2010-02-01 22:24:142710 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322711}
2712
[email protected]29a9eb52010-04-13 09:04:232713GLuint GLES2DecoderImpl::DoGetMaxValueInBuffer(
2714 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
2715 GLuint max_vertex_accessed = 0;
2716 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:292717 if (!info) {
[email protected]ae51d192010-04-27 00:48:032718 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:292719 SetGLError(GL_INVALID_VALUE,
2720 "GetMaxValueInBuffer: unknown buffer");
2721 } else if (info->target() != GL_ELEMENT_ARRAY_BUFFER) {
2722 // TODO(gman): Should this be a GL error or a command buffer error?
2723 SetGLError(GL_INVALID_OPERATION,
2724 "GetMaxValueInBuffer: buffer not element array buffer");
[email protected]29a9eb52010-04-13 09:04:232725 } else {
2726 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:032727 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:292728 SetGLError(GL_INVALID_OPERATION,
2729 "GetMaxValueInBuffer: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:232730 }
2731 }
2732 return max_vertex_accessed;
2733}
2734
[email protected]96449d2c2009-11-25 00:01:322735// Calls glShaderSource for the various versions of the ShaderSource command.
2736// Assumes that data / data_size points to a piece of memory that is in range
2737// of whatever context it came from (shared memory, immediate memory, bucket
2738// memory.)
[email protected]45bf5152010-02-12 00:11:312739error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:032740 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:582741 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
2742 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:312743 if (!info) {
[email protected]45bf5152010-02-12 00:11:312744 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322745 }
[email protected]45bf5152010-02-12 00:11:312746 // Note: We don't actually call glShaderSource here. We wait until
2747 // the call to glCompileShader.
2748 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:142749 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322750}
2751
[email protected]f7a64ee2010-02-01 22:24:142752error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:192753 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:322754 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:312755 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:322756 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:462757 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142758 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:322759 }
[email protected]ae51d192010-04-27 00:48:032760 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:322761}
2762
[email protected]f7a64ee2010-02-01 22:24:142763error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:192764 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:322765 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:312766 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:302767 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462768 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142769 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:322770 }
[email protected]ae51d192010-04-27 00:48:032771 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:312772}
2773
[email protected]558847a2010-03-24 07:02:542774error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
2775 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:542776 Bucket* bucket = GetBucket(c.data_bucket_id);
2777 if (!bucket || bucket->size() == 0) {
2778 return error::kInvalidArguments;
2779 }
2780 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:032781 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:542782 bucket->size() - 1);
2783}
2784
[email protected]ae51d192010-04-27 00:48:032785void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]6b8cf1a2010-05-06 16:13:582786 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
2787 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:312788 if (!info) {
[email protected]45bf5152010-02-12 00:11:312789 return;
2790 }
[email protected]de17df392010-04-23 21:09:412791 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
2792 // glShaderSource and then glCompileShader.
2793 const char* shader_src = info->source().c_str();
2794#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
2795#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
2796 int dbg_options = 0;
[email protected]7cea56d92010-04-28 17:21:382797 EShLanguage language = info->shader_type() == GL_VERTEX_SHADER ?
2798 EShLangVertex : EShLangFragment;
[email protected]de17df392010-04-23 21:09:412799 TBuiltInResource resources;
2800 // TODO(alokp): Ask gman how to get appropriate values.
2801 resources.maxVertexAttribs = 8;
2802 resources.maxVertexUniformVectors = 128;
2803 resources.maxVaryingVectors = 8;
2804 resources.maxVertexTextureImageUnits = 0;
2805 resources.maxCombinedTextureImageUnits = 8;
2806 resources.maxTextureImageUnits = 8;
2807 resources.maxFragmentUniformVectors = 16;
2808 resources.maxDrawBuffers = 1;
2809 ShHandle compiler = ShConstructCompiler(language, dbg_options);
2810 if (!ShCompile(compiler, &shader_src, 1, EShOptNone, &resources,
2811 dbg_options)) {
2812 // TODO(alokp): Ask gman where to set compile-status and info-log.
2813 // May be add member variables to ShaderManager::ShaderInfo?
2814 const char* info_log = ShGetInfoLog(compiler);
2815 ShDestruct(compiler);
2816 return;
2817 }
2818 shader_src = ShGetObjectCode(compiler);
2819#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
2820#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
2821
[email protected]ae51d192010-04-27 00:48:032822 glShaderSource(info->service_id(), 1, &shader_src, NULL);
2823 glCompileShader(info->service_id());
[email protected]de17df392010-04-23 21:09:412824
2825#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
2826#ifdef GLES2_GPU_SERVICE_TRANSLATE_SHADER
2827 ShDestruct(compiler);
2828#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
2829#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
[email protected]45bf5152010-02-12 00:11:312830};
2831
[email protected]ddd968b82010-03-02 00:44:292832void GLES2DecoderImpl::DoGetShaderiv(
2833 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:582834 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
2835 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:292836 if (!info) {
[email protected]ddd968b82010-03-02 00:44:292837 return;
2838 }
2839 if (pname == GL_SHADER_SOURCE_LENGTH) {
2840 *params = info->source().size();
2841 } else {
[email protected]ae51d192010-04-27 00:48:032842 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:292843 }
2844}
2845
[email protected]ae51d192010-04-27 00:48:032846error::Error GLES2DecoderImpl::HandleGetShaderSource(
2847 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
2848 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:032849 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
2850 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:582851 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
2852 shader, "glGetShaderSource");
[email protected]8eee29c2010-04-29 03:38:292853 if (!info) {
2854 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:292855 return error::kNoError;
2856 }
[email protected]ae51d192010-04-27 00:48:032857 bucket->SetFromString(info->source());
2858 return error::kNoError;
2859}
2860
2861error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
2862 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
2863 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:582864 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
2865 Bucket* bucket = CreateBucket(bucket_id);
2866 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2867 program, "glGetProgramInfoLog");
[email protected]ae51d192010-04-27 00:48:032868 if (!info) {
[email protected]ae51d192010-04-27 00:48:032869 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:312870 }
[email protected]ae51d192010-04-27 00:48:032871 GLint len = 0;
2872 glGetProgramiv(info->service_id(), GL_INFO_LOG_LENGTH, &len);
[email protected]ae51d192010-04-27 00:48:032873 bucket->SetSize(len + 1);
2874 glGetProgramInfoLog(
2875 info->service_id(),
2876 len + 1, &len, bucket->GetDataAs<GLchar*>(0, len + 1));
2877 return error::kNoError;
2878}
2879
2880error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
2881 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
2882 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:582883 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
2884 Bucket* bucket = CreateBucket(bucket_id);
2885 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
2886 shader, "glGetShaderInfoLog");
[email protected]ae51d192010-04-27 00:48:032887 if (!info) {
[email protected]6b8cf1a2010-05-06 16:13:582888 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:032889 return error::kNoError;
2890 }
[email protected]ae51d192010-04-27 00:48:032891 GLint len = 0;
2892 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &len);
[email protected]ae51d192010-04-27 00:48:032893 bucket->SetSize(len + 1);
2894 glGetShaderInfoLog(
2895 info->service_id(),
2896 len + 1, &len, bucket->GetDataAs<GLchar*>(0, len + 1));
2897 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322898}
2899
[email protected]1958e0e2010-04-22 05:17:152900bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032901 return GetBufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:152902}
2903
2904bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032905 return GetFramebufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:152906}
2907
2908bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032909 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:152910}
2911
2912bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032913 return GetRenderbufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:152914}
2915
2916bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032917 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:152918}
2919
2920bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032921 return GetTextureInfo(client_id) != NULL;
2922}
2923
2924void GLES2DecoderImpl::DoAttachShader(
2925 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:582926 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
2927 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:032928 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:032929 return;
[email protected]1958e0e2010-04-22 05:17:152930 }
[email protected]6b8cf1a2010-05-06 16:13:582931 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
2932 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:032933 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:032934 return;
2935 }
2936 glAttachShader(program_info->service_id(), shader_info->service_id());
2937}
2938
2939void GLES2DecoderImpl::DoDetachShader(
2940 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:582941 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
2942 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:032943 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:032944 return;
2945 }
[email protected]6b8cf1a2010-05-06 16:13:582946 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
2947 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:032948 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:032949 return;
2950 }
2951 glDetachShader(program_info->service_id(), shader_info->service_id());
2952}
2953
2954void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:582955 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2956 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:032957 if (!info) {
[email protected]ae51d192010-04-27 00:48:032958 return;
2959 }
2960 glValidateProgram(info->service_id());
[email protected]1958e0e2010-04-22 05:17:152961}
2962
[email protected]f7a64ee2010-02-01 22:24:142963error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:192964 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:292965 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
2966 SetGLError(GL_INVALID_VALUE,
2967 "glVertexAttribPointer: no array buffer bound");
2968 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322969 }
[email protected]8eee29c2010-04-29 03:38:292970
2971 GLuint indx = c.indx;
2972 GLint size = c.size;
2973 GLenum type = c.type;
2974 GLboolean normalized = c.normalized;
2975 GLsizei stride = c.stride;
2976 GLsizei offset = c.offset;
2977 const void* ptr = reinterpret_cast<const void*>(offset);
2978 if (!ValidateGLenumVertexAttribType(type)) {
2979 SetGLError(GL_INVALID_ENUM,
2980 "glVertexAttribPointer: type GL_INVALID_ENUM");
2981 return error::kNoError;
2982 }
2983 if (!ValidateGLintVertexAttribSize(size)) {
2984 SetGLError(GL_INVALID_ENUM,
2985 "glVertexAttribPointer: size GL_INVALID_VALUE");
2986 return error::kNoError;
2987 }
2988 if (indx >= group_->max_vertex_attribs()) {
2989 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
2990 return error::kNoError;
2991 }
2992 if (stride < 0) {
2993 SetGLError(GL_INVALID_VALUE,
2994 "glVertexAttribPointer: stride < 0");
2995 return error::kNoError;
2996 }
2997 if (stride > 255) {
2998 SetGLError(GL_INVALID_VALUE,
2999 "glVertexAttribPointer: stride > 255");
3000 return error::kNoError;
3001 }
3002 if (offset < 0) {
3003 SetGLError(GL_INVALID_VALUE,
3004 "glVertexAttribPointer: offset < 0");
3005 return error::kNoError;
3006 }
3007 GLsizei component_size =
3008 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
3009 GLsizei real_stride = stride != 0 ? stride : component_size * size;
3010 if (offset % component_size > 0) {
3011 SetGLError(GL_INVALID_VALUE,
3012 "glVertexAttribPointer: stride not valid for type");
3013 return error::kNoError;
3014 }
3015 vertex_attrib_infos_[indx].SetInfo(
3016 bound_array_buffer_,
3017 size,
3018 type,
3019 real_stride,
3020 offset);
3021 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
[email protected]f7a64ee2010-02-01 22:24:143022 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323023}
3024
[email protected]f7a64ee2010-02-01 22:24:143025error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:193026 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:313027 GLint x = c.x;
3028 GLint y = c.y;
3029 GLsizei width = c.width;
3030 GLsizei height = c.height;
3031 GLenum format = c.format;
3032 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:563033 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:293034 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:563035 return error::kNoError;
3036 }
[email protected]a51788e2010-02-24 21:54:253037 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:183038 uint32 pixels_size;
3039 if (!GLES2Util::ComputeImageDataSize(
3040 width, height, format, type, pack_alignment_, &pixels_size)) {
3041 return error::kOutOfBounds;
3042 }
[email protected]612d2f82009-12-08 20:49:313043 void* pixels = GetSharedMemoryAs<void*>(
3044 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:253045 Result* result = GetSharedMemoryAs<Result*>(
3046 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3047 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:143048 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:463049 }
[email protected]a51788e2010-02-24 21:54:253050
[email protected]8eee29c2010-04-29 03:38:293051 if (!ValidateGLenumReadPixelFormat(format)) {
3052 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
3053 return error::kNoError;
3054 }
3055 if (!ValidateGLenumPixelType(type)) {
3056 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:123057 return error::kNoError;
3058 }
[email protected]57f223832010-03-19 01:57:563059 if (width == 0 || height == 0) {
3060 return error::kNoError;
3061 }
3062
3063 CopyRealGLErrorsToWrapper();
3064
3065 // Get the size of the current fbo or backbuffer.
[email protected]d37231fa2010-04-09 21:16:023066 gfx::Size max_size = GetBoundFrameBufferSize();
[email protected]57f223832010-03-19 01:57:563067
3068 GLint max_x;
3069 GLint max_y;
3070 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:293071 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:143072 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:313073 }
[email protected]57f223832010-03-19 01:57:563074
[email protected]6b8cf1a2010-05-06 16:13:583075 glFinish();
[email protected]d37231fa2010-04-09 21:16:023076 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:563077 // The user requested an out of range area. Get the results 1 line
3078 // at a time.
3079 uint32 temp_size;
3080 if (!GLES2Util::ComputeImageDataSize(
3081 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:293082 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563083 return error::kNoError;
3084 }
3085 GLsizei unpadded_row_size = temp_size;
3086 if (!GLES2Util::ComputeImageDataSize(
3087 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:293088 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563089 return error::kNoError;
3090 }
3091 GLsizei padded_row_size = temp_size - unpadded_row_size;
3092 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:293093 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563094 return error::kNoError;
3095 }
3096
3097 GLint dest_x_offset = std::max(-x, 0);
3098 uint32 dest_row_offset;
3099 if (!GLES2Util::ComputeImageDataSize(
3100 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:293101 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563102 return error::kNoError;
3103 }
3104
3105 // Copy each row into the larger dest rect.
3106 int8* dst = static_cast<int8*>(pixels);
3107 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:023108 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:563109 GLint read_width = read_end_x - read_x;
3110 for (GLint yy = 0; yy < height; ++yy) {
3111 GLint ry = y + yy;
3112
3113 // Clear the row.
3114 memset(dst, 0, unpadded_row_size);
3115
3116 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:023117 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:563118 glReadPixels(
3119 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
3120 }
3121 dst += padded_row_size;
3122 }
3123 } else {
3124 glReadPixels(x, y, width, height, format, type, pixels);
3125 }
[email protected]a51788e2010-02-24 21:54:253126 GLenum error = glGetError();
3127 if (error == GL_NO_ERROR) {
3128 *result = true;
3129 } else {
[email protected]8eee29c2010-04-29 03:38:293130 SetGLError(error, NULL);
[email protected]a51788e2010-02-24 21:54:253131 }
[email protected]f7a64ee2010-02-01 22:24:143132 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323133}
3134
[email protected]f7a64ee2010-02-01 22:24:143135error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:193136 uint32 immediate_data_size, const gles2::PixelStorei& c) {
3137 GLenum pname = c.pname;
3138 GLenum param = c.param;
[email protected]d2cf0a2d2010-02-25 21:36:123139 if (!ValidateGLenumPixelStore(pname)) {
[email protected]8eee29c2010-04-29 03:38:293140 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:123141 return error::kNoError;
3142 }
3143 if (!ValidateGLintPixelStoreAlignment(param)) {
[email protected]8eee29c2010-04-29 03:38:293144 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:143145 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193146 }
3147 glPixelStorei(pname, param);
3148 switch (pname) {
3149 case GL_PACK_ALIGNMENT:
3150 pack_alignment_ = param;
3151 break;
3152 case GL_UNPACK_ALIGNMENT:
3153 unpack_alignment_ = param;
3154 break;
3155 default:
3156 // Validation should have prevented us from getting here.
3157 DCHECK(false);
3158 break;
3159 }
[email protected]f7a64ee2010-02-01 22:24:143160 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193161}
3162
[email protected]558847a2010-03-24 07:02:543163error::Error GLES2DecoderImpl::GetAttribLocationHelper(
3164 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
3165 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:583166 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3167 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:033168 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:143169 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193170 }
[email protected]ae51d192010-04-27 00:48:033171 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:293172 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:253173 return error::kNoError;
3174 }
[email protected]b9849abf2009-11-25 19:13:193175 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:543176 location_shm_id, location_shm_offset, sizeof(GLint));
3177 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:143178 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193179 }
[email protected]558847a2010-03-24 07:02:543180 // Require the client to init this incase the context is lost and we are no
3181 // longer executing commands.
3182 if (*location != -1) {
3183 return error::kGenericError;
3184 }
[email protected]0bfd9882010-02-05 23:02:253185 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:143186 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193187}
3188
[email protected]558847a2010-03-24 07:02:543189error::Error GLES2DecoderImpl::HandleGetAttribLocation(
3190 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
3191 uint32 name_size = c.data_size;
3192 const char* name = GetSharedMemoryAs<const char*>(
3193 c.name_shm_id, c.name_shm_offset, name_size);
3194 if (!name) {
3195 return error::kOutOfBounds;
3196 }
3197 String name_str(name, name_size);
3198 return GetAttribLocationHelper(
3199 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3200}
3201
[email protected]f7a64ee2010-02-01 22:24:143202error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:193203 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:543204 uint32 name_size = c.data_size;
3205 const char* name = GetImmediateDataAs<const char*>(
3206 c, name_size, immediate_data_size);
3207 if (!name) {
3208 return error::kOutOfBounds;
3209 }
3210 String name_str(name, name_size);
3211 return GetAttribLocationHelper(
3212 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3213}
3214
3215error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
3216 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
3217 Bucket* bucket = GetBucket(c.name_bucket_id);
3218 if (!bucket) {
3219 return error::kInvalidArguments;
3220 }
3221 std::string name_str;
3222 bucket->GetAsString(&name_str);
3223 return GetAttribLocationHelper(
3224 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3225}
3226
3227error::Error GLES2DecoderImpl::GetUniformLocationHelper(
3228 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
3229 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:583230 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3231 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:033232 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:143233 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193234 }
[email protected]ae51d192010-04-27 00:48:033235 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:293236 SetGLError(GL_INVALID_OPERATION,
3237 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:253238 return error::kNoError;
3239 }
[email protected]b9849abf2009-11-25 19:13:193240 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:543241 location_shm_id, location_shm_offset, sizeof(GLint));
3242 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:143243 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193244 }
[email protected]558847a2010-03-24 07:02:543245 // Require the client to init this incase the context is lost an we are no
3246 // longer executing commands.
3247 if (*location != -1) {
3248 return error::kGenericError;
3249 }
3250 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:143251 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193252}
3253
[email protected]f7a64ee2010-02-01 22:24:143254error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:193255 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:193256 uint32 name_size = c.data_size;
3257 const char* name = GetSharedMemoryAs<const char*>(
3258 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:543259 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:143260 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193261 }
3262 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:543263 return GetUniformLocationHelper(
3264 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:193265}
3266
[email protected]f7a64ee2010-02-01 22:24:143267error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:193268 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:193269 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:303270 const char* name = GetImmediateDataAs<const char*>(
3271 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:543272 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:143273 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193274 }
3275 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:543276 return GetUniformLocationHelper(
3277 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3278}
3279
3280error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
3281 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
3282 Bucket* bucket = GetBucket(c.name_bucket_id);
3283 if (!bucket) {
3284 return error::kInvalidArguments;
3285 }
3286 std::string name_str;
3287 bucket->GetAsString(&name_str);
3288 return GetUniformLocationHelper(
3289 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:193290}
3291
[email protected]ddd968b82010-03-02 00:44:293292error::Error GLES2DecoderImpl::HandleGetString(
3293 uint32 immediate_data_size, const gles2::GetString& c) {
3294 GLenum name = static_cast<GLenum>(c.name);
3295 if (!ValidateGLenumStringType(name)) {
[email protected]8eee29c2010-04-29 03:38:293296 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:293297 return error::kNoError;
3298 }
[email protected]1958e0e2010-04-22 05:17:153299 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
3300 const char* str = NULL;
3301 switch (name) {
3302 case GL_VERSION:
3303 str = "OpenGL ES 2.0 Chromium";
3304 break;
3305 case GL_SHADING_LANGUAGE_VERSION:
3306 str = "OpenGL ES GLSL ES 1.0 Chromium";
3307 break;
3308 case GL_EXTENSIONS:
3309 str = "";
3310 break;
3311 default:
3312 str = gl_str;
3313 break;
3314 }
[email protected]ddd968b82010-03-02 00:44:293315 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:153316 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:293317 return error::kNoError;
3318}
3319
[email protected]0c86dbf2010-03-05 08:14:113320void GLES2DecoderImpl::DoBufferData(
3321 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]8eee29c2010-04-29 03:38:293322 if (!ValidateGLenumBufferTarget(target)) {
3323 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
3324 return;
3325 }
3326 if (!ValidateGLenumBufferUsage(usage)) {
3327 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:113328 return;
[email protected]3b6ec202010-03-05 05:16:233329 }
3330 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:293331 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:283332 return;
[email protected]3b6ec202010-03-05 05:16:233333 }
3334 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
3335 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293336 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:283337 return;
[email protected]3b6ec202010-03-05 05:16:233338 }
3339 // Clear the buffer to 0 if no initial data was passed in.
3340 scoped_array<int8> zero;
3341 if (!data) {
3342 zero.reset(new int8[size]);
3343 memset(zero.get(), 0, size);
3344 data = zero.get();
3345 }
3346 CopyRealGLErrorsToWrapper();
3347 glBufferData(target, size, data, usage);
3348 GLenum error = glGetError();
3349 if (error != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:293350 SetGLError(error, NULL);
[email protected]3b6ec202010-03-05 05:16:233351 } else {
[email protected]0c86dbf2010-03-05 08:14:113352 info->SetSize(size);
3353 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:233354 }
[email protected]0c86dbf2010-03-05 08:14:113355}
3356
3357error::Error GLES2DecoderImpl::HandleBufferData(
3358 uint32 immediate_data_size, const gles2::BufferData& c) {
3359 GLenum target = static_cast<GLenum>(c.target);
3360 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
3361 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
3362 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
3363 GLenum usage = static_cast<GLenum>(c.usage);
3364 const void* data = NULL;
3365 if (data_shm_id != 0 || data_shm_offset != 0) {
3366 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
3367 if (!data) {
3368 return error::kOutOfBounds;
3369 }
3370 }
3371 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:143372 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193373}
3374
[email protected]f7a64ee2010-02-01 22:24:143375error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:193376 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
3377 GLenum target = static_cast<GLenum>(c.target);
3378 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:303379 const void* data = GetImmediateDataAs<const void*>(
3380 c, size, immediate_data_size);
3381 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143382 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:303383 }
[email protected]b9849abf2009-11-25 19:13:193384 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:113385 DoBufferData(target, size, data, usage);
3386 return error::kNoError;
3387}
3388
3389void GLES2DecoderImpl::DoBufferSubData(
3390 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:503391 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:473392 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293393 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:283394 return;
[email protected]a93bb842010-02-16 23:03:473395 }
[email protected]0c86dbf2010-03-05 08:14:113396 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:293397 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]07f54fcc2009-12-22 02:46:303398 } else {
[email protected]0c86dbf2010-03-05 08:14:113399 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:303400 }
[email protected]b9849abf2009-11-25 19:13:193401}
3402
[email protected]a93bb842010-02-16 23:03:473403error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
3404 GLenum target,
3405 GLint level,
3406 GLenum internal_format,
3407 GLsizei width,
3408 GLsizei height,
3409 GLint border,
3410 GLsizei image_size,
3411 const void* data) {
[email protected]a93bb842010-02-16 23:03:473412 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]8eee29c2010-04-29 03:38:293413 if (!ValidateGLenumTextureTarget(target)) {
3414 SetGLError(GL_INVALID_ENUM,
3415 "glCompressedTexImage2D: target GL_INVALID_ENUM");
3416 return error::kNoError;
3417 }
3418 if (!ValidateGLenumCompressedTextureInternalFormat(internal_format)) {
3419 SetGLError(GL_INVALID_ENUM,
3420 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:473421 return error::kNoError;
3422 }
[email protected]3916c97e2010-02-25 03:20:503423 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:473424 border != 0) {
[email protected]8eee29c2010-04-29 03:38:293425 SetGLError(GL_INVALID_VALUE,
3426 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:473427 return error::kNoError;
3428 }
[email protected]3916c97e2010-02-25 03:20:503429 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:473430 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293431 SetGLError(GL_INVALID_VALUE,
3432 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:473433 return error::kNoError;
3434 }
3435 scoped_array<int8> zero;
3436 if (!data) {
3437 zero.reset(new int8[image_size]);
3438 memset(zero.get(), 0, image_size);
3439 data = zero.get();
3440 }
3441 info->SetLevelInfo(
3442 target, level, internal_format, width, height, 1, border, 0, 0);
3443 glCompressedTexImage2D(
3444 target, level, internal_format, width, height, border, image_size, data);
3445 return error::kNoError;
3446}
3447
[email protected]f7a64ee2010-02-01 22:24:143448error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:193449 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
3450 GLenum target = static_cast<GLenum>(c.target);
3451 GLint level = static_cast<GLint>(c.level);
3452 GLenum internal_format = static_cast<GLenum>(c.internalformat);
3453 GLsizei width = static_cast<GLsizei>(c.width);
3454 GLsizei height = static_cast<GLsizei>(c.height);
3455 GLint border = static_cast<GLint>(c.border);
3456 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
3457 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
3458 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
3459 const void* data = NULL;
3460 if (data_shm_id != 0 || data_shm_offset != 0) {
3461 data = GetSharedMemoryAs<const void*>(
3462 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:463463 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143464 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193465 }
3466 }
[email protected]a93bb842010-02-16 23:03:473467 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:193468 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:193469}
3470
[email protected]f7a64ee2010-02-01 22:24:143471error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:193472 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
3473 GLenum target = static_cast<GLenum>(c.target);
3474 GLint level = static_cast<GLint>(c.level);
3475 GLenum internal_format = static_cast<GLenum>(c.internalformat);
3476 GLsizei width = static_cast<GLsizei>(c.width);
3477 GLsizei height = static_cast<GLsizei>(c.height);
3478 GLint border = static_cast<GLint>(c.border);
3479 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:303480 const void* data = GetImmediateDataAs<const void*>(
3481 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:463482 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143483 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:463484 }
[email protected]a93bb842010-02-16 23:03:473485 return DoCompressedTexImage2D(
3486 target, level, internal_format, width, height, border, image_size, data);
3487}
3488
[email protected]a93bb842010-02-16 23:03:473489error::Error GLES2DecoderImpl::DoTexImage2D(
3490 GLenum target,
3491 GLint level,
3492 GLenum internal_format,
3493 GLsizei width,
3494 GLsizei height,
3495 GLint border,
3496 GLenum format,
3497 GLenum type,
3498 const void* pixels,
3499 uint32 pixels_size) {
[email protected]8eee29c2010-04-29 03:38:293500 if (!ValidateGLenumTextureTarget(target)) {
3501 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
3502 return error::kNoError;
3503 }
3504 if (!ValidateGLenumTextureFormat(internal_format)) {
3505 SetGLError(GL_INVALID_ENUM,
3506 "glTexImage2D: internal_format GL_INVALID_ENUM");
3507 return error::kNoError;
3508 }
3509 if (!ValidateGLenumTextureFormat(format)) {
3510 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
3511 return error::kNoError;
3512 }
3513 if (!ValidateGLenumPixelType(type)) {
3514 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:143515 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193516 }
[email protected]3916c97e2010-02-25 03:20:503517 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:473518 border != 0) {
[email protected]8eee29c2010-04-29 03:38:293519 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:473520 return error::kNoError;
3521 }
[email protected]3916c97e2010-02-25 03:20:503522 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:473523 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293524 SetGLError(GL_INVALID_OPERATION,
3525 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:473526 return error::kNoError;
3527 }
3528 scoped_array<int8> zero;
3529 if (!pixels) {
3530 zero.reset(new int8[pixels_size]);
3531 memset(zero.get(), 0, pixels_size);
3532 pixels = zero.get();
3533 }
3534 info->SetLevelInfo(
3535 target, level, internal_format, width, height, 1, border, format, type);
3536 glTexImage2D(
3537 target, level, internal_format, width, height, border, format, type,
3538 pixels);
[email protected]f7a64ee2010-02-01 22:24:143539 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193540}
3541
[email protected]f7a64ee2010-02-01 22:24:143542error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:193543 uint32 immediate_data_size, const gles2::TexImage2D& c) {
3544 GLenum target = static_cast<GLenum>(c.target);
3545 GLint level = static_cast<GLint>(c.level);
3546 GLint internal_format = static_cast<GLint>(c.internalformat);
3547 GLsizei width = static_cast<GLsizei>(c.width);
3548 GLsizei height = static_cast<GLsizei>(c.height);
3549 GLint border = static_cast<GLint>(c.border);
3550 GLenum format = static_cast<GLenum>(c.format);
3551 GLenum type = static_cast<GLenum>(c.type);
3552 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
3553 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:183554 uint32 pixels_size;
3555 if (!GLES2Util::ComputeImageDataSize(
3556 width, height, format, type, unpack_alignment_, &pixels_size)) {
3557 return error::kOutOfBounds;
3558 }
[email protected]b9849abf2009-11-25 19:13:193559 const void* pixels = NULL;
3560 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
3561 pixels = GetSharedMemoryAs<const void*>(
3562 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:463563 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:143564 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193565 }
3566 }
[email protected]a93bb842010-02-16 23:03:473567 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:193568 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:473569 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:193570}
3571
[email protected]f7a64ee2010-02-01 22:24:143572error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:193573 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
3574 GLenum target = static_cast<GLenum>(c.target);
3575 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:463576 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:193577 GLsizei width = static_cast<GLsizei>(c.width);
3578 GLsizei height = static_cast<GLsizei>(c.height);
3579 GLint border = static_cast<GLint>(c.border);
3580 GLenum format = static_cast<GLenum>(c.format);
3581 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:183582 uint32 size;
3583 if (!GLES2Util::ComputeImageDataSize(
3584 width, height, format, type, unpack_alignment_, &size)) {
3585 return error::kOutOfBounds;
3586 }
[email protected]07f54fcc2009-12-22 02:46:303587 const void* pixels = GetImmediateDataAs<const void*>(
3588 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:463589 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:143590 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:463591 }
[email protected]a93bb842010-02-16 23:03:473592 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:463593 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:473594 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:143595 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323596}
3597
[email protected]f7a64ee2010-02-01 22:24:143598error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:193599 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:363600 GLuint index = static_cast<GLuint>(c.index);
3601 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:253602 typedef gles2::GetVertexAttribPointerv::Result Result;
3603 Result* result = GetSharedMemoryAs<Result*>(
3604 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:363605 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:143606 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:363607 }
[email protected]07d0cc82010-02-17 04:51:403608 // Check that the client initialized the result.
3609 if (result->size != 0) {
3610 return error::kInvalidArguments;
3611 }
[email protected]8bf5a3e2010-01-29 04:21:363612 if (!ValidateGLenumVertexPointer(pname)) {
[email protected]8eee29c2010-04-29 03:38:293613 SetGLError(GL_INVALID_ENUM,
3614 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:143615 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:363616 }
[email protected]3916c97e2010-02-25 03:20:503617 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:293618 SetGLError(GL_INVALID_VALUE,
3619 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:143620 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:363621 }
[email protected]0bfd9882010-02-05 23:02:253622 result->SetNumResults(1);
3623 *result->GetData() = vertex_attrib_infos_[index].offset();
[email protected]f7a64ee2010-02-01 22:24:143624 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323625}
3626
[email protected]f7b85372010-02-03 01:11:373627bool GLES2DecoderImpl::GetUniformSetup(
3628 GLuint program, GLint location,
3629 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:253630 error::Error* error, GLuint* service_id, void** result_pointer) {
[email protected]f7b85372010-02-03 01:11:373631 *error = error::kNoError;
3632 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:253633 SizedResult<GLint>* result;
3634 result = GetSharedMemoryAs<SizedResult<GLint>*>(
3635 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
3636 if (!result) {
[email protected]f7b85372010-02-03 01:11:373637 *error = error::kOutOfBounds;
3638 return false;
3639 }
[email protected]0bfd9882010-02-05 23:02:253640 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:373641 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:253642 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:583643 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3644 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:373645 if (!info) {
[email protected]ae51d192010-04-27 00:48:033646 return false;
3647 }
3648 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:373649 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:293650 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:373651 return false;
3652 }
[email protected]ae51d192010-04-27 00:48:033653 *service_id = info->service_id();
[email protected]0bfd9882010-02-05 23:02:253654 GLenum type;
3655 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:373656 // No such location.
[email protected]8eee29c2010-04-29 03:38:293657 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:373658 return false;
3659 }
[email protected]3916c97e2010-02-25 03:20:503660 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:373661 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:293662 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:373663 return false;
3664 }
[email protected]0bfd9882010-02-05 23:02:253665 result = GetSharedMemoryAs<SizedResult<GLint>*>(
3666 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
3667 if (!result) {
[email protected]f7b85372010-02-03 01:11:373668 *error = error::kOutOfBounds;
3669 return false;
3670 }
[email protected]0bfd9882010-02-05 23:02:253671 result->size = size;
[email protected]f7b85372010-02-03 01:11:373672 return true;
3673}
3674
[email protected]f7a64ee2010-02-01 22:24:143675error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:193676 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:373677 GLuint program = c.program;
3678 GLint location = c.location;
3679 GLuint service_id;
3680 Error error;
[email protected]0bfd9882010-02-05 23:02:253681 void* result;
[email protected]f7b85372010-02-03 01:11:373682 if (GetUniformSetup(
3683 program, location, c.params_shm_id, c.params_shm_offset,
3684 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:253685 glGetUniformiv(
3686 service_id, location,
3687 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:373688 }
3689 return error;
[email protected]96449d2c2009-11-25 00:01:323690}
3691
[email protected]f7a64ee2010-02-01 22:24:143692error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:193693 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:373694 GLuint program = c.program;
3695 GLint location = c.location;
3696 GLuint service_id;
3697 Error error;
[email protected]0bfd9882010-02-05 23:02:253698 void* result;
3699 typedef gles2::GetUniformfv::Result Result;
[email protected]f7b85372010-02-03 01:11:373700 if (GetUniformSetup(
3701 program, location, c.params_shm_id, c.params_shm_offset,
3702 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:253703 glGetUniformfv(
3704 service_id,
3705 location,
3706 static_cast<gles2::GetUniformfv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:373707 }
3708 return error;
[email protected]96449d2c2009-11-25 00:01:323709}
3710
[email protected]f7a64ee2010-02-01 22:24:143711error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:193712 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:253713 GLenum shader_type = static_cast<GLenum>(c.shadertype);
3714 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
3715 typedef gles2::GetShaderPrecisionFormat::Result Result;
3716 Result* result = GetSharedMemoryAs<Result*>(
3717 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3718 if (!result) {
3719 return error::kOutOfBounds;
3720 }
[email protected]07d0cc82010-02-17 04:51:403721 // Check that the client initialized the result.
3722 if (result->success != 0) {
3723 return error::kInvalidArguments;
3724 }
[email protected]8eee29c2010-04-29 03:38:293725 if (!ValidateGLenumShaderType(shader_type)) {
3726 SetGLError(GL_INVALID_ENUM,
3727 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
3728 return error::kNoError;
3729 }
3730 if (!ValidateGLenumShaderPrecision(precision_type)) {
3731 SetGLError(GL_INVALID_ENUM,
3732 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
3733 return error::kNoError;
3734 }
3735
3736 result->success = 1; // true
3737 switch (precision_type) {
3738 case GL_LOW_INT:
3739 case GL_MEDIUM_INT:
3740 case GL_HIGH_INT:
3741 result->min_range = -31;
3742 result->max_range = 31;
3743 result->precision = 0;
3744 case GL_LOW_FLOAT:
3745 case GL_MEDIUM_FLOAT:
3746 case GL_HIGH_FLOAT:
3747 result->min_range = -62;
3748 result->max_range = 62;
3749 result->precision = -16;
3750 break;
3751 default:
3752 NOTREACHED();
3753 break;
[email protected]0bfd9882010-02-05 23:02:253754 }
[email protected]f7a64ee2010-02-01 22:24:143755 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323756}
3757
[email protected]f7a64ee2010-02-01 22:24:143758error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:193759 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:253760 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:583761 GLuint program = static_cast<GLuint>(c.program);
3762 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3763 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:033764 if (!info) {
[email protected]0bfd9882010-02-05 23:02:253765 return error::kNoError;
3766 }
3767 typedef gles2::GetAttachedShaders::Result Result;
3768 uint32 max_count = Result::ComputeMaxResults(result_size);
3769 Result* result = GetSharedMemoryAs<Result*>(
3770 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
3771 if (!result) {
3772 return error::kOutOfBounds;
3773 }
[email protected]07d0cc82010-02-17 04:51:403774 // Check that the client initialized the result.
3775 if (result->size != 0) {
3776 return error::kInvalidArguments;
3777 }
[email protected]0bfd9882010-02-05 23:02:253778 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:033779 glGetAttachedShaders(
3780 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:253781 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:033782 if (!shader_manager()->GetClientId(result->GetData()[ii],
3783 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:253784 NOTREACHED();
3785 return error::kGenericError;
3786 }
3787 }
3788 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:143789 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323790}
3791
[email protected]f7a64ee2010-02-01 22:24:143792error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:193793 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:253794 GLuint program = c.program;
3795 GLuint index = c.index;
3796 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:253797 typedef gles2::GetActiveUniform::Result Result;
3798 Result* result = GetSharedMemoryAs<Result*>(
3799 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3800 if (!result) {
3801 return error::kOutOfBounds;
3802 }
[email protected]07d0cc82010-02-17 04:51:403803 // Check that the client initialized the result.
3804 if (result->success != 0) {
3805 return error::kInvalidArguments;
3806 }
[email protected]6b8cf1a2010-05-06 16:13:583807 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3808 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:033809 if (!info) {
[email protected]0bfd9882010-02-05 23:02:253810 return error::kNoError;
3811 }
3812 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
3813 info->GetUniformInfo(index);
3814 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:293815 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:253816 return error::kNoError;
3817 }
3818 result->success = 1; // true.
3819 result->size = uniform_info->size;
3820 result->type = uniform_info->type;
3821 Bucket* bucket = CreateBucket(name_bucket_id);
3822 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:143823 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323824}
3825
[email protected]f7a64ee2010-02-01 22:24:143826error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:193827 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:253828 GLuint program = c.program;
3829 GLuint index = c.index;
3830 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:253831 typedef gles2::GetActiveAttrib::Result Result;
3832 Result* result = GetSharedMemoryAs<Result*>(
3833 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3834 if (!result) {
3835 return error::kOutOfBounds;
3836 }
[email protected]07d0cc82010-02-17 04:51:403837 // Check that the client initialized the result.
3838 if (result->success != 0) {
3839 return error::kInvalidArguments;
3840 }
[email protected]6b8cf1a2010-05-06 16:13:583841 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3842 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:033843 if (!info) {
[email protected]0bfd9882010-02-05 23:02:253844 return error::kNoError;
3845 }
3846 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
3847 info->GetAttribInfo(index);
3848 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:293849 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:253850 return error::kNoError;
3851 }
3852 result->success = 1; // true.
3853 result->size = attrib_info->size;
3854 result->type = attrib_info->type;
3855 Bucket* bucket = CreateBucket(name_bucket_id);
3856 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:143857 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323858}
3859
[email protected]b273e432010-04-12 17:23:583860error::Error GLES2DecoderImpl::HandleShaderBinary(
3861 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
3862#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:293863 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:583864 return error::kNoError;
3865#else
3866 GLsizei n = static_cast<GLsizei>(c.n);
3867 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:293868 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:583869 return error::kNoError;
3870 }
3871 GLsizei length = static_cast<GLsizei>(c.length);
3872 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:293873 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:583874 return error::kNoError;
3875 }
3876 uint32 data_size;
3877 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3878 return error::kOutOfBounds;
3879 }
3880 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
3881 c.shaders_shm_id, c.shaders_shm_offset, data_size);
3882 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
3883 const void* binary = GetSharedMemoryAs<const void*>(
3884 c.binary_shm_id, c.binary_shm_offset, length);
3885 if (shaders == NULL || binary == NULL) {
3886 return error::kOutOfBounds;
3887 }
3888 scoped_array<GLuint> service_ids(new GLuint[n]);
3889 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:033890 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
3891 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293892 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:583893 return error::kNoError;
3894 }
[email protected]ae51d192010-04-27 00:48:033895 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:583896 }
3897 // TODO(gman): call glShaderBinary
3898 return error::kNoError;
3899#endif
3900}
3901
[email protected]6217d392010-03-25 22:08:353902error::Error GLES2DecoderImpl::HandleSwapBuffers(
3903 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]6217d392010-03-25 22:08:353904 // If offscreen then don't actually SwapBuffers to the display. Just copy
3905 // the rendered frame to another frame buffer.
3906 if (offscreen_target_frame_buffer_.get()) {
3907 ScopedGLErrorSuppressor suppressor(this);
3908
3909 // First check to see if a deferred offscreen render buffer resize is
3910 // pending.
3911 if (!UpdateOffscreenFrameBufferSize())
3912 return error::kLostContext;
3913
3914 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]d37231fa2010-04-09 21:16:023915 offscreen_saved_color_texture_->Copy(
3916 offscreen_saved_color_texture_->size());
[email protected]6217d392010-03-25 22:08:353917 } else {
[email protected]d37231fa2010-04-09 21:16:023918#if !defined(UNIT_TEST)
3919 context_->SwapBuffers();
[email protected]6217d392010-03-25 22:08:353920#endif
3921 }
3922
[email protected]7d9ce4f2010-04-14 18:39:403923 // TODO(kbr): when the back buffer is multisampled, then at least on Mac
3924 // OS X (and probably on all platforms, for best semantics), we will need
3925 // to perform the resolve step and bind the offscreen_saved_color_texture_
3926 // as the color attachment before calling the swap buffers callback, which
3927 // expects a normal (non-multisampled) frame buffer for glCopyTexImage2D /
3928 // glReadPixels. After the callback runs, the multisampled frame buffer
3929 // needs to be bound again.
3930
[email protected]6217d392010-03-25 22:08:353931 if (swap_buffers_callback_.get()) {
3932 swap_buffers_callback_->Run();
3933 }
3934
3935 return error::kNoError;
3936}
3937
[email protected]96449d2c2009-11-25 00:01:323938// Include the auto-generated part of this file. We split this because it means
3939// we can easily edit the non-auto generated parts right here in this file
3940// instead of having to edit some template or the code generator.
3941#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
3942
3943} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:253944} // namespace gpu