blob: 155c90899c3a239a16bbf0352270a337d0ffdbfd [file] [log] [blame]
[email protected]4874aae2011-03-18 01:19:561// Copyright (c) 2011 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]f39f4b3f2010-05-12 17:04:0810#include <list>
[email protected]96449d2c2009-11-25 00:01:3211#include <map>
[email protected]f39f4b3f2010-05-12 17:04:0812#include <string>
13#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0614
[email protected]1e6f58d2011-03-24 00:00:4015#include "base/atomicops.h"
[email protected]00eb49a2010-08-12 20:46:5716#include "base/at_exit.h"
[email protected]2041cf342010-02-19 03:15:5917#include "base/callback.h"
[email protected]3b63f8f42011-03-28 01:54:1518#include "base/memory/scoped_ptr.h"
19#include "base/memory/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0220#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3221#define GLES2_GPU_SERVICE 1
22#include "gpu/command_buffer/common/gles2_cmd_format.h"
23#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1024#include "gpu/command_buffer/common/id_allocator.h"
[email protected]366ae242011-05-10 02:23:5825#include "gpu/command_buffer/common/trace_event.h"
[email protected]3916c97e2010-02-25 03:20:5026#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3227#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5028#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1129#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5830#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3231#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4632#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4733#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5834#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4735#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4536#include "gpu/command_buffer/service/shader_translator.h"
[email protected]fbe20372011-06-01 01:46:3837#include "gpu/command_buffer/service/surface_manager.h"
[email protected]a93bb842010-02-16 23:03:4738#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4339#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]4e8a5b122010-05-08 22:00:1040#include "gpu/GLES2/gles2_command_buffer.h"
[email protected]5ae0b282011-03-28 19:24:4941#include "ui/gfx/gl/gl_context.h"
42#include "ui/gfx/gl/gl_implementation.h"
[email protected]f62a5ab2011-05-23 20:34:1543#include "ui/gfx/gl/gl_surface.h"
[email protected]de17df392010-04-23 21:09:4144
[email protected]6217d392010-03-25 22:08:3545#if !defined(GL_DEPTH24_STENCIL8)
46#define GL_DEPTH24_STENCIL8 0x88F0
47#endif
48
[email protected]a7a27ace2009-12-12 00:11:2549namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3250namespace gles2 {
51
[email protected]6217d392010-03-25 22:08:3552class GLES2DecoderImpl;
53
[email protected]07f54fcc2009-12-22 02:46:3054// Check that certain assumptions the code makes are true. There are places in
55// the code where shared memory is passed direclty to GL. Example, glUniformiv,
56// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
57// a few others) are 32bits. If they are not 32bits the code will have to change
58// to call those GL functions with service side memory and then copy the results
59// to shared memory, converting the sizes.
60COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
61 GLint_not_same_size_as_uint32);
62COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
63 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3764COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
65 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3066
[email protected]43f28f832010-02-03 02:28:4867// TODO(kbr): the use of this anonymous namespace core dumps the
68// linker on Mac OS X 10.6 when the symbol ordering file is used
69// namespace {
[email protected]96449d2c2009-11-25 00:01:3270
71// Returns the address of the first byte after a struct.
72template <typename T>
73const void* AddressAfterStruct(const T& pod) {
74 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
75}
76
[email protected]07f54fcc2009-12-22 02:46:3077// Returns the address of the frst byte after the struct or NULL if size >
78// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3279template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3080RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
81 uint32 size,
82 uint32 immediate_data_size) {
83 return (size <= immediate_data_size) ?
84 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
85 NULL;
[email protected]96449d2c2009-11-25 00:01:3286}
87
[email protected]07f54fcc2009-12-22 02:46:3088// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1889bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3290 GLuint count,
91 size_t size,
[email protected]a76b0052010-03-05 00:33:1892 unsigned int elements_per_unit,
93 uint32* dst) {
94 uint32 value;
95 if (!SafeMultiplyUint32(count, size, &value)) {
96 return false;
97 }
98 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
99 return false;
100 }
101 *dst = value;
102 return true;
[email protected]96449d2c2009-11-25 00:01:32103}
104
105// A struct to hold info about each command.
106struct CommandInfo {
107 int arg_flags; // How to handle the arguments for this command
108 int arg_count; // How many arguments are expected for this command.
109};
110
111// A table of CommandInfo for all the commands.
112const CommandInfo g_command_info[] = {
113 #define GLES2_CMD_OP(name) { \
114 name::kArgFlags, \
115 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
116
117 GLES2_COMMAND_LIST(GLES2_CMD_OP)
118
119 #undef GLES2_CMD_OP
120};
121
[email protected]34ff8b0c2010-10-01 20:06:02122static bool IsAngle() {
123#if defined(OS_WIN)
124 return gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
125#else
126 return false;
127#endif
128}
129
[email protected]297ca1c2011-06-20 23:08:46130static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30131 GLenum target,
132 GLint level,
133 GLenum internal_format,
134 GLsizei width,
135 GLsizei height,
136 GLint border,
137 GLenum format,
138 GLenum type,
139 const void* pixels) {
140 GLenum gl_internal_format = internal_format;
141 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
142 if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
143 gl_internal_format = GL_RGBA;
144 } else if (type == GL_FLOAT) {
145 if (format == GL_RGBA) {
146 gl_internal_format = GL_RGBA32F_ARB;
147 } else if (format == GL_RGB) {
148 gl_internal_format = GL_RGB32F_ARB;
149 }
150 } else if (type == GL_HALF_FLOAT_OES) {
151 if (format == GL_RGBA) {
152 gl_internal_format = GL_RGBA16F_ARB;
153 } else if (format == GL_RGB) {
154 gl_internal_format = GL_RGB16F_ARB;
155 }
156 }
157 }
158 glTexImage2D(
159 target, level, gl_internal_format, width, height, border, format, type,
160 pixels);
161}
162
[email protected]297ca1c2011-06-20 23:08:46163// Wrapper for glEnable/glDisable that doesn't suck.
164static void EnableDisable(GLenum pname, bool enable) {
165 if (enable) {
166 glEnable(pname);
167 } else {
168 glDisable(pname);
169 }
170}
171
[email protected]6217d392010-03-25 22:08:35172// This class prevents any GL errors that occur when it is in scope from
173// being reported to the client.
174class ScopedGLErrorSuppressor {
175 public:
176 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
177 ~ScopedGLErrorSuppressor();
178 private:
179 GLES2DecoderImpl* decoder_;
180 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
181};
182
183// Temporarily changes a decoder's bound 2D texture and restore it when this
184// object goes out of scope. Also temporarily switches to using active texture
185// unit zero in case the client has changed that to something invalid.
186class ScopedTexture2DBinder {
187 public:
188 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
189 ~ScopedTexture2DBinder();
190
191 private:
192 GLES2DecoderImpl* decoder_;
193 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
194};
195
196// Temporarily changes a decoder's bound render buffer and restore it when this
197// object goes out of scope.
198class ScopedRenderBufferBinder {
199 public:
200 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
201 ~ScopedRenderBufferBinder();
202
203 private:
204 GLES2DecoderImpl* decoder_;
205 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
206};
207
208// Temporarily changes a decoder's bound frame buffer and restore it when this
209// object goes out of scope.
210class ScopedFrameBufferBinder {
211 public:
212 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
213 ~ScopedFrameBufferBinder();
214
215 private:
216 GLES2DecoderImpl* decoder_;
217 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
218};
219
[email protected]34ff8b0c2010-10-01 20:06:02220// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52221// the multisampled offscreen render buffer if that buffer is multisampled, and,
222// if it is bound or enforce_internal_framebuffer is true.
[email protected]34ff8b0c2010-10-01 20:06:02223class ScopedResolvedFrameBufferBinder {
224 public:
[email protected]c0701082011-04-20 00:34:52225 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
226 bool enforce_internal_framebuffer);
[email protected]34ff8b0c2010-10-01 20:06:02227 ~ScopedResolvedFrameBufferBinder();
228
229 private:
230 GLES2DecoderImpl* decoder_;
231 bool resolve_and_bind_;
232 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
233};
234
[email protected]6217d392010-03-25 22:08:35235// Encapsulates an OpenGL texture.
236class Texture {
237 public:
238 explicit Texture(GLES2DecoderImpl* decoder);
239 ~Texture();
240
241 // Create a new render texture.
242 void Create();
243
244 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02245 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35246
247 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58248 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35249
250 // Destroy the render texture. This must be explicitly called before
251 // destroying this object.
252 void Destroy();
253
[email protected]97872062010-11-03 19:07:05254 // Invalidate the texture. This can be used when a context is lost and it is
255 // not possible to make it current in order to free the resource.
256 void Invalidate();
257
[email protected]6217d392010-03-25 22:08:35258 GLuint id() const {
259 return id_;
260 }
261
[email protected]d37231fa2010-04-09 21:16:02262 gfx::Size size() const {
263 return size_;
264 }
265
[email protected]6217d392010-03-25 22:08:35266 private:
267 GLES2DecoderImpl* decoder_;
268 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02269 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35270 DISALLOW_COPY_AND_ASSIGN(Texture);
271};
272
273// Encapsulates an OpenGL render buffer of any format.
274class RenderBuffer {
275 public:
276 explicit RenderBuffer(GLES2DecoderImpl* decoder);
277 ~RenderBuffer();
278
279 // Create a new render buffer.
280 void Create();
281
282 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02283 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35284
285 // Destroy the render buffer. This must be explicitly called before destroying
286 // this object.
287 void Destroy();
288
[email protected]97872062010-11-03 19:07:05289 // Invalidate the render buffer. This can be used when a context is lost and
290 // it is not possible to make it current in order to free the resource.
291 void Invalidate();
292
[email protected]6217d392010-03-25 22:08:35293 GLuint id() const {
294 return id_;
295 }
296
297 private:
298 GLES2DecoderImpl* decoder_;
299 GLuint id_;
300 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
301};
302
303// Encapsulates an OpenGL frame buffer.
304class FrameBuffer {
305 public:
306 explicit FrameBuffer(GLES2DecoderImpl* decoder);
307 ~FrameBuffer();
308
309 // Create a new frame buffer.
310 void Create();
311
312 // Attach a color render buffer to a frame buffer.
313 void AttachRenderTexture(Texture* texture);
314
[email protected]b9363b22010-06-09 22:06:15315 // Attach a render buffer to a frame buffer. Note that this unbinds any
316 // currently bound frame buffer.
317 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35318
319 // Clear the given attached buffers.
320 void Clear(GLbitfield buffers);
321
322 // Destroy the frame buffer. This must be explicitly called before destroying
323 // this object.
324 void Destroy();
325
[email protected]97872062010-11-03 19:07:05326 // Invalidate the frame buffer. This can be used when a context is lost and it
327 // is not possible to make it current in order to free the resource.
328 void Invalidate();
329
[email protected]6217d392010-03-25 22:08:35330 // See glCheckFramebufferStatusEXT.
331 GLenum CheckStatus();
332
333 GLuint id() const {
334 return id_;
335 }
336
337 private:
338 GLES2DecoderImpl* decoder_;
339 GLuint id_;
340 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
341};
[email protected]34ff8b0c2010-10-01 20:06:02342
343class ContextCreationAttribParser {
344 public:
345 ContextCreationAttribParser();
346 bool Parse(const std::vector<int32>& attribs);
347
348 // -1 if invalid or unspecified.
349 int32 alpha_size_;
350 int32 blue_size_;
351 int32 green_size_;
352 int32 red_size_;
353 int32 depth_size_;
354 int32 stencil_size_;
355 int32 samples_;
356 int32 sample_buffers_;
357};
358
359ContextCreationAttribParser::ContextCreationAttribParser()
360 : alpha_size_(-1),
361 blue_size_(-1),
362 green_size_(-1),
363 red_size_(-1),
364 depth_size_(-1),
365 stencil_size_(-1),
366 samples_(-1),
367 sample_buffers_(-1) {
368}
369
370bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
371 // From <EGL/egl.h>.
372 const int32 EGL_ALPHA_SIZE = 0x3021;
373 const int32 EGL_BLUE_SIZE = 0x3022;
374 const int32 EGL_GREEN_SIZE = 0x3023;
375 const int32 EGL_RED_SIZE = 0x3024;
376 const int32 EGL_DEPTH_SIZE = 0x3025;
377 const int32 EGL_STENCIL_SIZE = 0x3026;
378 const int32 EGL_SAMPLES = 0x3031;
379 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
380 const int32 EGL_NONE = 0x3038;
381
382 for (size_t i = 0; i < attribs.size(); i += 2) {
383 const int32 attrib = attribs[i];
384 if (i + 1 >= attribs.size()) {
385 if (attrib == EGL_NONE)
386 return true;
387
388 DLOG(ERROR) << "Missing value after context creation attribute: "
389 << attrib;
390 return false;
391 }
392
393 const int32 value = attribs[i+1];
394 switch (attrib) {
395 case EGL_ALPHA_SIZE:
396 alpha_size_ = value;
397 break;
398 case EGL_BLUE_SIZE:
399 blue_size_ = value;
400 break;
401 case EGL_GREEN_SIZE:
402 green_size_ = value;
403 break;
404 case EGL_RED_SIZE:
405 red_size_ = value;
406 break;
407 case EGL_DEPTH_SIZE:
408 depth_size_ = value;
409 break;
410 case EGL_STENCIL_SIZE:
411 stencil_size_ = value;
412 break;
413 case EGL_SAMPLES:
414 samples_ = value;
415 break;
416 case EGL_SAMPLE_BUFFERS:
417 sample_buffers_ = value;
418 break;
419 case EGL_NONE:
420 // Terminate list, even if more attributes.
421 return true;
422 default:
423 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
424 return false;
425 }
426 }
427
428 return true;
429}
430
[email protected]43f28f832010-02-03 02:28:48431// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32432
[email protected]ddb1e5a2010-12-13 20:10:45433bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
434 uint32* service_texture_id) {
435 return false;
436}
437
[email protected]a3ded6d2010-10-19 06:44:39438GLES2Decoder::GLES2Decoder()
439 : debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32440}
441
[email protected]3916c97e2010-02-25 03:20:50442GLES2Decoder::~GLES2Decoder() {
443}
444
[email protected]f39f4b3f2010-05-12 17:04:08445// This class implements GLES2Decoder so we don't have to expose all the GLES2
446// cmd stuff to outside this class.
447class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
448 public GLES2Decoder {
449 public:
[email protected]fbe20372011-06-01 01:46:38450 explicit GLES2DecoderImpl(SurfaceManager* surface_manager,
451 ContextGroup* group);
[email protected]f39f4b3f2010-05-12 17:04:08452
[email protected]96449d2c2009-11-25 00:01:32453 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14454 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50455 unsigned int arg_count,
456 const void* args);
[email protected]96449d2c2009-11-25 00:01:32457
458 // Overridden from AsyncAPIInterface.
459 virtual const char* GetCommandName(unsigned int command_id) const;
460
461 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38462 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
463 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35464 const gfx::Size& size,
[email protected]c410da802011-03-14 19:17:41465 const DisallowedExtensions& disallowed_extensions,
[email protected]a3ded6d2010-10-19 06:44:39466 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24467 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32468 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24469 virtual bool SetParent(GLES2Decoder* parent_decoder,
470 uint32 parent_texture_id);
[email protected]6217d392010-03-25 22:08:35471 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]c71caa82010-06-02 23:25:45472 virtual bool UpdateOffscreenFrameBufferSize();
[email protected]eb54a562010-01-20 21:55:18473 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55474 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30475 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15476 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39477 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48478
[email protected]7ff86b92010-11-25 17:50:00479 virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
[email protected]43f28f832010-02-03 02:28:48480 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
[email protected]80c49752011-04-18 23:55:10481 virtual void SetLatchCallback(const base::Callback<void(bool)>& callback);;
[email protected]1318e922010-09-17 22:03:16482 virtual bool GetServiceTextureId(uint32 client_texture_id,
483 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48484
[email protected]8e3e0662010-08-23 18:46:30485 // Restores the current state to the user's settings.
486 void RestoreCurrentFramebufferBindings();
487 void RestoreCurrentRenderbufferBindings();
488 void RestoreCurrentTexture2DBindings();
489
[email protected]297ca1c2011-06-20 23:08:46490 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
491 void ApplyDirtyState();
492
493 // These check the state of the currently bound framebuffer or the
494 // backbuffer if no framebuffer is bound.
495 bool BoundFramebufferHasColorAttachmentWithAlpha();
496 bool BoundFramebufferHasDepthAttachment();
497 bool BoundFramebufferHasStencilAttachment();
498
[email protected]96449d2c2009-11-25 00:01:32499 private:
[email protected]6217d392010-03-25 22:08:35500 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02501 friend class ScopedResolvedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35502 friend class RenderBuffer;
503 friend class FrameBuffer;
504
[email protected]3916c97e2010-02-25 03:20:50505 // State associated with each texture unit.
506 struct TextureUnit {
507 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
508
509 // The last target that was bound to this texture unit.
510 GLenum bind_target;
511
512 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
513 TextureManager::TextureInfo::Ref bound_texture_2d;
514
515 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
516 // glBindTexture
517 TextureManager::TextureInfo::Ref bound_texture_cube_map;
518 };
519
[email protected]c2f8c8402010-12-06 18:07:24520 // Initialize or re-initialize the shader translator.
521 bool InitializeShaderTranslator();
522
[email protected]302ce6d2011-07-07 23:28:11523 void UpdateCapabilities();
524
[email protected]ae51d192010-04-27 00:48:03525 // Helpers for the glGen and glDelete functions.
526 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
527 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
528 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
529 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
530 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
531 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
532 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
533 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47534
[email protected]3916c97e2010-02-25 03:20:50535 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50536 BufferManager* buffer_manager() {
537 return group_->buffer_manager();
538 }
539
[email protected]a25fa872010-03-25 02:57:58540 RenderbufferManager* renderbuffer_manager() {
541 return group_->renderbuffer_manager();
542 }
543
544 FramebufferManager* framebuffer_manager() {
545 return group_->framebuffer_manager();
546 }
547
[email protected]3916c97e2010-02-25 03:20:50548 ProgramManager* program_manager() {
549 return group_->program_manager();
550 }
551
552 ShaderManager* shader_manager() {
553 return group_->shader_manager();
554 }
555
556 TextureManager* texture_manager() {
557 return group_->texture_manager();
558 }
559
[email protected]34ff8b0c2010-10-01 20:06:02560 bool IsOffscreenBufferMultisampled() const {
561 return offscreen_target_samples_ > 1;
562 }
563
[email protected]a93bb842010-02-16 23:03:47564 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03565 TextureManager::TextureInfo* CreateTextureInfo(
566 GLuint client_id, GLuint service_id) {
[email protected]915a59a12010-09-30 21:29:11567 return texture_manager()->CreateTextureInfo(
568 feature_info_, client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47569 }
570
571 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03572 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50573 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03574 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50575 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47576 }
577
578 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03579 void RemoveTextureInfo(GLuint client_id) {
[email protected]915a59a12010-09-30 21:29:11580 texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]3916c97e2010-02-25 03:20:50581 }
[email protected]a93bb842010-02-16 23:03:47582
[email protected]d37231fa2010-04-09 21:16:02583 // Get the size (in pixels) of the currently bound frame buffer (either FBO
584 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30585 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02586
[email protected]9edc6b22010-12-23 02:00:26587 // Get the format of the currently bound frame buffer (either FBO or regular
588 // back buffer)
589 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46590 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26591
[email protected]a93bb842010-02-16 23:03:47592 // Wrapper for CompressedTexImage2D commands.
593 error::Error DoCompressedTexImage2D(
594 GLenum target,
595 GLint level,
596 GLenum internal_format,
597 GLsizei width,
598 GLsizei height,
599 GLint border,
600 GLsizei image_size,
601 const void* data);
602
[email protected]cadde4a2010-07-31 17:10:43603 // Wrapper for CompressedTexSubImage2D.
604 void DoCompressedTexSubImage2D(
605 GLenum target,
606 GLint level,
607 GLint xoffset,
608 GLint yoffset,
609 GLsizei width,
610 GLsizei height,
611 GLenum format,
612 GLsizei imageSize,
613 const void * data);
614
615 // Wrapper for CopyTexImage2D.
616 void DoCopyTexImage2D(
617 GLenum target,
618 GLint level,
619 GLenum internal_format,
620 GLint x,
621 GLint y,
622 GLsizei width,
623 GLsizei height,
624 GLint border);
625
626 // Wrapper for CopyTexSubImage2D.
627 void DoCopyTexSubImage2D(
628 GLenum target,
629 GLint level,
630 GLint xoffset,
631 GLint yoffset,
632 GLint x,
633 GLint y,
634 GLsizei width,
635 GLsizei height);
636
[email protected]a93bb842010-02-16 23:03:47637 // Wrapper for TexImage2D commands.
638 error::Error DoTexImage2D(
639 GLenum target,
640 GLint level,
641 GLenum internal_format,
642 GLsizei width,
643 GLsizei height,
644 GLint border,
645 GLenum format,
646 GLenum type,
647 const void* pixels,
648 uint32 pixels_size);
649
[email protected]cadde4a2010-07-31 17:10:43650 // Wrapper for TexSubImage2D.
651 void DoTexSubImage2D(
652 GLenum target,
653 GLint level,
654 GLint xoffset,
655 GLint yoffset,
656 GLsizei width,
657 GLsizei height,
658 GLenum format,
659 GLenum type,
660 const void * data);
661
[email protected]a93bb842010-02-16 23:03:47662 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57663 ProgramManager::ProgramInfo* CreateProgramInfo(
664 GLuint client_id, GLuint service_id) {
665 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47666 }
667
[email protected]07f54fcc2009-12-22 02:46:30668 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03669 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14670 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46671 }
[email protected]07f54fcc2009-12-22 02:46:30672
[email protected]6b8cf1a2010-05-06 16:13:58673 // Gets the program info for the given program. If it's not a program
674 // generates a GL error. Returns NULL if not program.
675 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
676 GLuint client_id, const char* function_name) {
677 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
678 if (!info) {
679 if (GetShaderInfo(client_id)) {
680 SetGLError(GL_INVALID_OPERATION,
681 (std::string(function_name) +
682 ": shader passed for program").c_str());
683 } else {
684 SetGLError(GL_INVALID_VALUE,
685 (std::string(function_name) + ": unknown program").c_str());
686 }
687 }
688 return info;
689 }
690
691
[email protected]45bf5152010-02-12 00:11:31692 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57693 ShaderManager::ShaderInfo* CreateShaderInfo(
694 GLuint client_id,
695 GLuint service_id,
696 GLenum shader_type) {
697 return shader_manager()->CreateShaderInfo(
698 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31699 }
700
701 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03702 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14703 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31704 }
705
[email protected]6b8cf1a2010-05-06 16:13:58706 // Gets the shader info for the given shader. If it's not a shader generates a
707 // GL error. Returns NULL if not shader.
708 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
709 GLuint client_id, const char* function_name) {
710 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
711 if (!info) {
712 if (GetProgramInfo(client_id)) {
713 SetGLError(
714 GL_INVALID_OPERATION,
715 (std::string(function_name) +
716 ": program passed for shader").c_str());
717 } else {
718 SetGLError(GL_INVALID_VALUE,
719 (std::string(function_name) + ": unknown shader").c_str());
720 }
721 }
722 return info;
723 }
724
[email protected]a93bb842010-02-16 23:03:47725 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03726 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
727 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47728 }
729
[email protected]07f54fcc2009-12-22 02:46:30730 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03731 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
732 BufferManager::BufferInfo* info =
733 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50734 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46735 }
[email protected]07f54fcc2009-12-22 02:46:30736
[email protected]a93bb842010-02-16 23:03:47737 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
738 // on glDeleteBuffers so we can make sure the user does not try to render
739 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03740 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47741
[email protected]a25fa872010-03-25 02:57:58742 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03743 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
744 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58745 }
746
747 // Gets the framebuffer info for the given framebuffer.
748 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03749 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58750 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03751 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58752 return (info && !info->IsDeleted()) ? info : NULL;
753 }
754
755 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03756 void RemoveFramebufferInfo(GLuint client_id) {
757 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58758 }
759
760 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03761 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
762 return renderbuffer_manager()->CreateRenderbufferInfo(
763 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58764 }
765
766 // Gets the renderbuffer info for the given renderbuffer.
767 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03768 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58769 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03770 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58771 return (info && !info->IsDeleted()) ? info : NULL;
772 }
773
774 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03775 void RemoveRenderbufferInfo(GLuint client_id) {
776 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58777 }
778
[email protected]558847a2010-03-24 07:02:54779 error::Error GetAttribLocationHelper(
780 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
781 const std::string& name_str);
782
783 error::Error GetUniformLocationHelper(
784 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
785 const std::string& name_str);
786
[email protected]3916c97e2010-02-25 03:20:50787 // Helper for glShaderSource.
788 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03789 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30790
[email protected]3a2e7c7b2010-08-06 01:12:28791 // Clears any uncleared render buffers attached to the given frame buffer.
[email protected]8e3e0662010-08-23 18:46:30792 void ClearUnclearedRenderbuffers(
793 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28794
[email protected]c007aa02010-09-02 22:22:40795 // Restore all GL state that affects clearing.
796 void RestoreClearState();
797
[email protected]3a2e7c7b2010-08-06 01:12:28798 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46799 // Returns: true if glEnable/glDisable should actually be called.
800 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28801
[email protected]3a03a8f2011-03-19 00:51:27802 // Check that the current frame buffer is complete. Generates error if not.
803 bool CheckFramebufferComplete(const char* func_name);
804
[email protected]939e7362010-05-13 20:49:10805 // Checks if the current program exists and is valid. If not generates the
806 // appropriate GL error. Returns true if the current program is in a usable
807 // state.
808 bool CheckCurrentProgram(const char* function_name);
809
810 // Checks if the current program exists and is valid and that location is not
811 // -1. If the current program is not valid generates the appropriate GL
812 // error. Returns true if the current program is in a usable state and
813 // location is not -1.
814 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
815
816 // Gets the type of a uniform for a location in the current program. Sets GL
817 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36818 // program is valid and the location exists. Adjusts count so it
819 // does not overflow the uniform.
820 bool PrepForSetUniformByLocation(
821 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10822
[email protected]b273e432010-04-12 17:23:58823 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
824 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
825
[email protected]96449d2c2009-11-25 00:01:32826 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03827 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32828
829 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03830 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32831
[email protected]3916c97e2010-02-25 03:20:50832 // Wrapper for glActiveTexture
833 void DoActiveTexture(GLenum texture_unit);
834
[email protected]ae51d192010-04-27 00:48:03835 // Wrapper for glAttachShader
836 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
837
[email protected]96449d2c2009-11-25 00:01:32838 // Wrapper for glBindBuffer since we need to track the current targets.
839 void DoBindBuffer(GLenum target, GLuint buffer);
840
[email protected]86093972010-03-11 00:13:56841 // Wrapper for glBindFramebuffer since we need to track the current targets.
842 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
843
844 // Wrapper for glBindRenderbuffer since we need to track the current targets.
845 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
846
[email protected]a93bb842010-02-16 23:03:47847 // Wrapper for glBindTexture since we need to track the current targets.
848 void DoBindTexture(GLenum target, GLuint texture);
849
[email protected]8e3e0662010-08-23 18:46:30850 // Wrapper for glBlitFramebufferEXT.
851 void DoBlitFramebufferEXT(
852 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
853 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
854 GLbitfield mask, GLenum filter);
855
[email protected]36cef8ce2010-03-16 07:34:45856 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11857 void DoBufferData(
858 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
859
[email protected]36cef8ce2010-03-16 07:34:45860 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11861 void DoBufferSubData(
862 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
863
[email protected]36cef8ce2010-03-16 07:34:45864 // Wrapper for glCheckFramebufferStatus
865 GLenum DoCheckFramebufferStatus(GLenum target);
866
[email protected]3a03a8f2011-03-19 00:51:27867 // Wrapper for glClear
868 void DoClear(GLbitfield mask);
869
[email protected]3a2e7c7b2010-08-06 01:12:28870 // Wrappers for clear and mask settings functions.
871 void DoClearColor(
872 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
873 void DoClearDepthf(GLclampf depth);
874 void DoClearStencil(GLint s);
875 void DoColorMask(
876 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
877 void DoDepthMask(GLboolean depth);
878 void DoStencilMask(GLuint mask);
879 void DoStencilMaskSeparate(GLenum face, GLuint mask);
880
[email protected]45bf5152010-02-12 00:11:31881 // Wrapper for glCompileShader.
882 void DoCompileShader(GLuint shader);
883
[email protected]269200b12010-11-18 22:53:06884 // Helper for DeleteSharedIdsCHROMIUM commands.
885 void DoDeleteSharedIdsCHROMIUM(
886 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10887
[email protected]ae51d192010-04-27 00:48:03888 // Wrapper for glDetachShader
889 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
890
[email protected]07f54fcc2009-12-22 02:46:30891 // Wrapper for glDrawArrays.
892 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
893
[email protected]3a2e7c7b2010-08-06 01:12:28894 // Wrapper for glDisable
895 void DoDisable(GLenum cap);
896
[email protected]07f54fcc2009-12-22 02:46:30897 // Wrapper for glDisableVertexAttribArray.
898 void DoDisableVertexAttribArray(GLuint index);
899
[email protected]3a2e7c7b2010-08-06 01:12:28900 // Wrapper for glEnable
901 void DoEnable(GLenum cap);
902
[email protected]07f54fcc2009-12-22 02:46:30903 // Wrapper for glEnableVertexAttribArray.
904 void DoEnableVertexAttribArray(GLuint index);
905
[email protected]36cef8ce2010-03-16 07:34:45906 // Wrapper for glFramebufferRenderbufffer.
907 void DoFramebufferRenderbuffer(
908 GLenum target, GLenum attachment, GLenum renderbuffertarget,
909 GLuint renderbuffer);
910
911 // Wrapper for glFramebufferTexture2D.
912 void DoFramebufferTexture2D(
913 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
914 GLint level);
915
[email protected]a93bb842010-02-16 23:03:47916 // Wrapper for glGenerateMipmap
917 void DoGenerateMipmap(GLenum target);
918
[email protected]269200b12010-11-18 22:53:06919 // Helper for GenSharedIdsCHROMIUM commands.
920 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:10921 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
922
[email protected]b273e432010-04-12 17:23:58923 // Wrapper for DoGetBooleanv.
924 void DoGetBooleanv(GLenum pname, GLboolean* params);
925
926 // Wrapper for DoGetFloatv.
927 void DoGetFloatv(GLenum pname, GLfloat* params);
928
[email protected]36cef8ce2010-03-16 07:34:45929 // Wrapper for glGetFramebufferAttachmentParameteriv.
930 void DoGetFramebufferAttachmentParameteriv(
931 GLenum target, GLenum attachment, GLenum pname, GLint* params);
932
[email protected]a0c3e972010-04-21 00:49:13933 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:58934 void DoGetIntegerv(GLenum pname, GLint* params);
935
[email protected]29a9eb52010-04-13 09:04:23936 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:06937 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:23938 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
939
[email protected]a0c3e972010-04-21 00:49:13940 // Wrapper for glGetProgramiv.
941 void DoGetProgramiv(
942 GLuint program_id, GLenum pname, GLint* params);
943
[email protected]36cef8ce2010-03-16 07:34:45944 // Wrapper for glRenderbufferParameteriv.
945 void DoGetRenderbufferParameteriv(
946 GLenum target, GLenum pname, GLint* params);
947
[email protected]ddd968b82010-03-02 00:44:29948 // Wrapper for glGetShaderiv
949 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
950
[email protected]b1122982010-05-17 23:04:24951 // Wrappers for glGetVertexAttrib.
952 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
953 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
954
[email protected]1958e0e2010-04-22 05:17:15955 // Wrappers for glIsXXX functions.
956 bool DoIsBuffer(GLuint client_id);
957 bool DoIsFramebuffer(GLuint client_id);
958 bool DoIsProgram(GLuint client_id);
959 bool DoIsRenderbuffer(GLuint client_id);
960 bool DoIsShader(GLuint client_id);
961 bool DoIsTexture(GLuint client_id);
962
[email protected]07f54fcc2009-12-22 02:46:30963 // Wrapper for glLinkProgram
964 void DoLinkProgram(GLuint program);
965
[email protected]269200b12010-11-18 22:53:06966 // Helper for RegisterSharedIdsCHROMIUM.
967 void DoRegisterSharedIdsCHROMIUM(
968 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10969
[email protected]36cef8ce2010-03-16 07:34:45970 // Wrapper for glRenderbufferStorage.
971 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:03972 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:45973
[email protected]8e3e0662010-08-23 18:46:30974 // Wrapper for glRenderbufferStorageMultisampleEXT.
975 void DoRenderbufferStorageMultisample(
976 GLenum target, GLsizei samples, GLenum internalformat,
977 GLsizei width, GLsizei height);
978
[email protected]b273e432010-04-12 17:23:58979 // Wrapper for glReleaseShaderCompiler.
980 void DoReleaseShaderCompiler() { }
981
[email protected]3916c97e2010-02-25 03:20:50982 // Wrappers for glTexParameter functions.
983 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
984 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
985 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
986 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
987
988 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
989 // spec only these 2 functions can be used to set sampler uniforms.
990 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:10991 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:36992 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
993 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
994 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:10995
996 // Wrappers for glUniformfv because some drivers don't correctly accept
997 // bool uniforms.
998 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
999 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1000 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1001 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501002
[email protected]43c2f1f2011-03-25 18:35:361003 void DoUniformMatrix2fv(
1004 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1005 void DoUniformMatrix3fv(
1006 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1007 void DoUniformMatrix4fv(
1008 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1009
[email protected]b1122982010-05-17 23:04:241010 // Wrappers for glVertexAttrib??
1011 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1012 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1013 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1014 void DoVertexAttrib4f(
1015 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1016 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1017 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1018 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1019 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1020
[email protected]07f54fcc2009-12-22 02:46:301021 // Wrapper for glUseProgram
1022 void DoUseProgram(GLuint program);
1023
[email protected]ae51d192010-04-27 00:48:031024 // Wrapper for glValidateProgram.
1025 void DoValidateProgram(GLuint program_client_id);
1026
[email protected]297ca1c2011-06-20 23:08:461027 void DoCopyTextureToParentTextureCHROMIUM(
1028 GLuint client_texture_id, GLuint parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:561029
[email protected]43ecf372010-11-16 19:19:391030 void DoResizeCHROMIUM(GLuint width, GLuint height);
1031
[email protected]fbe20372011-06-01 01:46:381032 void DoSetSurfaceCHROMIUM(GLint surface_id);
1033
[email protected]4e8a5b122010-05-08 22:00:101034 // Gets the number of values that will be returned by glGetXXX. Returns
1035 // false if pname is unknown.
1036 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1037
[email protected]96449d2c2009-11-25 00:01:321038 // Gets the GLError through our wrapper.
1039 GLenum GetGLError();
1040
[email protected]1002c2d2011-06-28 22:39:041041 // Gets the GLError and stores it in our wrapper. Effectively
1042 // this lets us peek at the error without losing it.
1043 GLenum PeekGLError();
1044
[email protected]96449d2c2009-11-25 00:01:321045 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:291046 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:321047
[email protected]07f54fcc2009-12-22 02:46:301048 // Copies the real GL errors to the wrapper. This is so we can
1049 // make sure there are no native GL errors before calling some GL function
1050 // so that on return we know any error generated was for that specific
1051 // command.
1052 void CopyRealGLErrorsToWrapper();
1053
[email protected]6217d392010-03-25 22:08:351054 // Clear all real GL errors. This is to prevent the client from seeing any
1055 // errors caused by GL calls that it was not responsible for issuing.
1056 void ClearRealGLErrors();
1057
[email protected]07f54fcc2009-12-22 02:46:301058 // Checks if the current program and vertex attributes are valid for drawing.
1059 bool IsDrawValid(GLuint max_vertex_accessed);
1060
[email protected]b1122982010-05-17 23:04:241061 // Returns true if attrib0 was simulated.
1062 bool SimulateAttrib0(GLuint max_vertex_accessed);
1063 void RestoreStateForSimulatedAttrib0();
1064
[email protected]ef526492010-06-02 23:12:251065 // Returns true if textures were set.
1066 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501067 void RestoreStateForNonRenderableTextures();
1068
[email protected]8fbedc02010-11-18 18:43:401069 // Returns true if GL_FIXED attribs were simulated.
1070 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1071 void RestoreStateForSimulatedFixedAttribs();
1072
[email protected]07f54fcc2009-12-22 02:46:301073 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501074 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301075 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501076 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1077 bound_array_buffer_ : bound_element_array_buffer_;
1078 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301079 }
1080
[email protected]a93bb842010-02-16 23:03:471081 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501082 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1083 TextureUnit& unit = texture_units_[active_texture_unit_];
1084 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471085 switch (target) {
1086 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501087 info = unit.bound_texture_2d;
1088 break;
[email protected]a93bb842010-02-16 23:03:471089 case GL_TEXTURE_CUBE_MAP:
1090 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1091 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1092 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1093 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1094 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1095 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501096 info = unit.bound_texture_cube_map;
1097 break;
[email protected]1aef98132010-02-23 18:00:071098 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1099 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1100 // because |texture_| is used by the FBO rendering mechanism for readback
1101 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471102 default:
1103 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501104 return NULL;
[email protected]a93bb842010-02-16 23:03:471105 }
[email protected]3916c97e2010-02-25 03:20:501106 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471107 }
1108
[email protected]8e3e0662010-08-23 18:46:301109 // Gets the framebuffer info for a particular target.
1110 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1111 GLenum target) {
1112 FramebufferManager::FramebufferInfo* info = NULL;
1113 switch (target) {
1114 case GL_FRAMEBUFFER:
1115 case GL_DRAW_FRAMEBUFFER:
1116 info = bound_draw_framebuffer_;
1117 break;
1118 case GL_READ_FRAMEBUFFER:
1119 info = bound_read_framebuffer_;
1120 break;
1121 default:
1122 NOTREACHED();
1123 break;
1124 }
1125 return (info && !info->IsDeleted()) ? info : NULL;
1126 }
1127
[email protected]f7b85372010-02-03 01:11:371128 // Validates the program and location for a glGetUniform call and returns
1129 // a SizeResult setup to receive the result. Returns true if glGetUniform
1130 // should be called.
1131 bool GetUniformSetup(
1132 GLuint program, GLint location,
1133 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101134 error::Error* error, GLuint* service_id, void** result,
1135 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371136
[email protected]96449d2c2009-11-25 00:01:321137 // Generate a member function prototype for each command in an automated and
1138 // typesafe way.
1139 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141140 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191141 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321142 const gles2::name& args); \
1143
1144 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1145
1146 #undef GLES2_CMD_OP
1147
[email protected]fbe20372011-06-01 01:46:381148 // Maps surface IDs to GLSurface.
1149 gpu::SurfaceManager* surface_manager_;
1150
[email protected]2f2d7042010-04-14 21:45:581151 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381152 scoped_refptr<gfx::GLSurface> surface_;
1153 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021154
[email protected]a3ded6d2010-10-19 06:44:391155 // The ContextGroup for this decoder uses to track resources.
1156 ContextGroup::Ref group_;
1157
[email protected]6217d392010-03-25 22:08:351158 // A parent decoder can access this decoders saved offscreen frame buffer.
1159 // The parent pointer is reset if the parent is destroyed.
1160 base::WeakPtr<GLES2DecoderImpl> parent_;
1161
1162 // Width and height to which an offscreen frame buffer should be resized on
1163 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021164 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351165
[email protected]34ff8b0c2010-10-01 20:06:021166 // Current width and height of the offscreen frame buffer.
1167 gfx::Size offscreen_size_;
1168
[email protected]96449d2c2009-11-25 00:01:321169 // Current GL error bits.
1170 uint32 error_bits_;
1171
[email protected]96449d2c2009-11-25 00:01:321172 // Util to help with GL.
1173 GLES2Util util_;
1174
1175 // pack alignment as last set by glPixelStorei
1176 GLint pack_alignment_;
1177
1178 // unpack alignment as last set by glPixelStorei
1179 GLint unpack_alignment_;
1180
1181 // The currently bound array buffer. If this is 0 it is illegal to call
1182 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501183 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321184
1185 // The currently bound element array buffer. If this is 0 it is illegal
1186 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501187 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301188
[email protected]f39f4b3f2010-05-12 17:04:081189 // Class that manages vertex attribs.
1190 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301191
[email protected]b1122982010-05-17 23:04:241192 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1193 GLuint attrib_0_buffer_id_;
1194
1195 // The value currently in attrib_0.
1196 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1197
[email protected]fc753442011-02-04 19:49:491198 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1199 bool attrib_0_buffer_matches_value_;
1200
[email protected]b1122982010-05-17 23:04:241201 // The size of attrib 0.
1202 GLsizei attrib_0_size_;
1203
[email protected]8fbedc02010-11-18 18:43:401204 // The buffer used to simulate GL_FIXED attribs.
1205 GLuint fixed_attrib_buffer_id_;
1206
1207 // The size of fiixed attrib buffer.
1208 GLsizei fixed_attrib_buffer_size_;
1209
[email protected]3916c97e2010-02-25 03:20:501210 // Current active texture by 0 - n index.
1211 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1212 // be 2.
1213 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301214
[email protected]3916c97e2010-02-25 03:20:501215 // Which textures are bound to texture units through glActiveTexture.
1216 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471217
[email protected]3a2e7c7b2010-08-06 01:12:281218 // state saved for clearing so we can clear render buffers and then
1219 // restore to these values.
1220 GLclampf clear_red_;
1221 GLclampf clear_green_;
1222 GLclampf clear_blue_;
1223 GLclampf clear_alpha_;
1224 GLboolean mask_red_;
1225 GLboolean mask_green_;
1226 GLboolean mask_blue_;
1227 GLboolean mask_alpha_;
1228 GLint clear_stencil_;
1229 GLuint mask_stencil_front_;
1230 GLuint mask_stencil_back_;
1231 GLclampf clear_depth_;
1232 GLboolean mask_depth_;
1233 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461234 bool enable_depth_test_;
1235 bool enable_stencil_test_;
1236 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281237
[email protected]1d32bc82010-01-13 22:06:461238 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501239 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301240
[email protected]8e3e0662010-08-23 18:46:301241 // The currently bound framebuffers
1242 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1243 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561244
1245 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081246 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561247
[email protected]b9363b22010-06-09 22:06:151248 // The offscreen frame buffer that the client renders to. With EGL, the
1249 // depth and stencil buffers are separate. With regular GL there is a single
1250 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1251 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351252 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1253 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021254 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151255 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1256 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021257 GLenum offscreen_target_color_format_;
1258 GLenum offscreen_target_depth_format_;
1259 GLenum offscreen_target_stencil_format_;
1260 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351261
[email protected]a3a93e7b2010-08-28 00:48:561262 GLuint copy_texture_to_parent_texture_fb_;
1263
[email protected]34ff8b0c2010-10-01 20:06:021264 // The copy that is saved when SwapBuffers is called. It is also
1265 // used as the destination for multi-sample resolves.
1266 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351267 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]97872062010-11-03 19:07:051268 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351269
[email protected]7ff86b92010-11-25 17:50:001270 scoped_ptr<Callback1<gfx::Size>::Type> resize_callback_;
[email protected]43f28f832010-02-03 02:28:481271 scoped_ptr<Callback0::Type> swap_buffers_callback_;
[email protected]80c49752011-04-18 23:55:101272 base::Callback<void(bool)> latch_callback_;
[email protected]43f28f832010-02-03 02:28:481273
[email protected]32fe9aa2011-01-21 23:47:131274 // The format of the back buffer_
1275 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461276 bool back_buffer_has_depth_;
1277 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131278
[email protected]473c01ccb2011-06-07 01:33:301279 bool teximage2d_faster_than_texsubimage2d_;
1280 bool bufferdata_faster_than_buffersubdata_;
1281
[email protected]8eee29c2010-04-29 03:38:291282 // The last error message set.
1283 std::string last_error_;
1284
[email protected]a3a93e7b2010-08-28 00:48:561285 // The current decoder error.
1286 error::Error current_decoder_error_;
1287
[email protected]b1d2dcb2010-05-17 19:24:181288 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451289 scoped_ptr<ShaderTranslator> vertex_translator_;
1290 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181291
[email protected]c410da802011-03-14 19:17:411292 DisallowedExtensions disallowed_extensions_;
1293
[email protected]915a59a12010-09-30 21:29:111294 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051295 const Validators* validators_;
[email protected]915a59a12010-09-30 21:29:111296 FeatureInfo* feature_info_;
[email protected]9438b012010-06-15 22:55:051297
[email protected]b493ee622011-04-13 23:52:001298 // This indicates all the following texSubImage2D calls that are part of the
1299 // failed texImage2D call should be ignored.
1300 bool tex_image_2d_failed_;
1301
[email protected]65225772011-05-12 21:10:241302 int frame_number_;
1303
[email protected]96449d2c2009-11-25 00:01:321304 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1305};
1306
[email protected]6217d392010-03-25 22:08:351307ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1308 : decoder_(decoder) {
1309 decoder_->CopyRealGLErrorsToWrapper();
1310}
1311
1312ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1313 decoder_->ClearRealGLErrors();
1314}
1315
1316ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1317 GLuint id)
1318 : decoder_(decoder) {
1319 ScopedGLErrorSuppressor suppressor(decoder_);
1320
1321 // TODO(apatrick): Check if there are any other states that need to be reset
1322 // before binding a new texture.
1323 glActiveTexture(GL_TEXTURE0);
1324 glBindTexture(GL_TEXTURE_2D, id);
1325}
1326
1327ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1328 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301329 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351330}
1331
1332ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1333 GLuint id)
1334 : decoder_(decoder) {
1335 ScopedGLErrorSuppressor suppressor(decoder_);
1336 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1337}
1338
1339ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1340 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301341 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351342}
1343
1344ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1345 GLuint id)
1346 : decoder_(decoder) {
1347 ScopedGLErrorSuppressor suppressor(decoder_);
1348 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1349}
1350
1351ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1352 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301353 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351354}
1355
[email protected]34ff8b0c2010-10-01 20:06:021356ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]c0701082011-04-20 00:34:521357 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer)
1358 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021359 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1360 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521361 (!decoder_->bound_read_framebuffer_.get() ||
1362 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021363 if (!resolve_and_bind_)
1364 return;
1365
1366 ScopedGLErrorSuppressor suppressor(decoder_);
1367 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1368 decoder_->offscreen_target_frame_buffer_->id());
1369 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT,
1370 decoder_->offscreen_saved_frame_buffer_->id());
1371 const int width = decoder_->offscreen_size_.width();
1372 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181373 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021374 if (IsAngle()) {
1375 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1376 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1377 } else {
1378 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1379 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1380 }
1381 glBindFramebufferEXT(GL_FRAMEBUFFER,
1382 decoder_->offscreen_saved_frame_buffer_->id());
1383}
1384
1385ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1386 if (!resolve_and_bind_)
1387 return;
1388
1389 ScopedGLErrorSuppressor suppressor(decoder_);
1390 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181391 if (decoder_->enable_scissor_test_) {
1392 glEnable(GL_SCISSOR_TEST);
1393 }
[email protected]34ff8b0c2010-10-01 20:06:021394}
1395
[email protected]6217d392010-03-25 22:08:351396Texture::Texture(GLES2DecoderImpl* decoder)
1397 : decoder_(decoder),
[email protected]3a4d0c52011-06-29 23:11:581398 id_(0) {
[email protected]6217d392010-03-25 22:08:351399}
1400
1401Texture::~Texture() {
1402 // This does not destroy the render texture because that would require that
1403 // the associated GL context was current. Just check that it was explicitly
1404 // destroyed.
1405 DCHECK_EQ(id_, 0u);
1406}
1407
1408void Texture::Create() {
1409 ScopedGLErrorSuppressor suppressor(decoder_);
1410 Destroy();
1411 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581412 ScopedTexture2DBinder binder(decoder_, id_);
1413 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1414 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1415 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1416 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351417}
1418
[email protected]34ff8b0c2010-10-01 20:06:021419bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351420 DCHECK_NE(id_, 0u);
1421 ScopedGLErrorSuppressor suppressor(decoder_);
1422 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351423
1424 glTexImage2D(GL_TEXTURE_2D,
1425 0, // mip level
[email protected]34ff8b0c2010-10-01 20:06:021426 format,
[email protected]6217d392010-03-25 22:08:351427 size.width(),
1428 size.height(),
1429 0, // border
[email protected]34ff8b0c2010-10-01 20:06:021430 format,
[email protected]6217d392010-03-25 22:08:351431 GL_UNSIGNED_BYTE,
1432 NULL);
1433
[email protected]d37231fa2010-04-09 21:16:021434 size_ = size;
1435
[email protected]6217d392010-03-25 22:08:351436 return glGetError() == GL_NO_ERROR;
1437}
1438
[email protected]3a4d0c52011-06-29 23:11:581439void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351440 DCHECK_NE(id_, 0u);
1441 ScopedGLErrorSuppressor suppressor(decoder_);
1442 ScopedTexture2DBinder binder(decoder_, id_);
1443 glCopyTexImage2D(GL_TEXTURE_2D,
1444 0, // level
[email protected]3a4d0c52011-06-29 23:11:581445 format,
[email protected]6217d392010-03-25 22:08:351446 0, 0,
1447 size.width(),
1448 size.height(),
1449 0); // border
1450}
1451
1452void Texture::Destroy() {
1453 if (id_ != 0) {
1454 ScopedGLErrorSuppressor suppressor(decoder_);
1455 glDeleteTextures(1, &id_);
1456 id_ = 0;
1457 }
1458}
1459
[email protected]97872062010-11-03 19:07:051460void Texture::Invalidate() {
1461 id_ = 0;
1462}
1463
[email protected]6217d392010-03-25 22:08:351464RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1465 : decoder_(decoder),
1466 id_(0) {
1467}
1468
1469RenderBuffer::~RenderBuffer() {
1470 // This does not destroy the render buffer because that would require that
1471 // the associated GL context was current. Just check that it was explicitly
1472 // destroyed.
1473 DCHECK_EQ(id_, 0u);
1474}
1475
1476void RenderBuffer::Create() {
1477 ScopedGLErrorSuppressor suppressor(decoder_);
1478 Destroy();
1479 glGenRenderbuffersEXT(1, &id_);
1480}
1481
[email protected]34ff8b0c2010-10-01 20:06:021482bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1483 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351484 ScopedGLErrorSuppressor suppressor(decoder_);
1485 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021486 if (samples <= 1) {
1487 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1488 format,
1489 size.width(),
1490 size.height());
1491 } else {
1492 if (IsAngle()) {
1493 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1494 samples,
1495 format,
1496 size.width(),
1497 size.height());
1498 } else {
1499 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1500 samples,
1501 format,
1502 size.width(),
1503 size.height());
1504 }
1505 }
[email protected]6217d392010-03-25 22:08:351506 return glGetError() == GL_NO_ERROR;
1507}
1508
1509void RenderBuffer::Destroy() {
1510 if (id_ != 0) {
1511 ScopedGLErrorSuppressor suppressor(decoder_);
1512 glDeleteRenderbuffersEXT(1, &id_);
1513 id_ = 0;
1514 }
1515}
1516
[email protected]97872062010-11-03 19:07:051517void RenderBuffer::Invalidate() {
1518 id_ = 0;
1519}
1520
[email protected]6217d392010-03-25 22:08:351521FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1522 : decoder_(decoder),
1523 id_(0) {
1524}
1525
1526FrameBuffer::~FrameBuffer() {
1527 // This does not destroy the frame buffer because that would require that
1528 // the associated GL context was current. Just check that it was explicitly
1529 // destroyed.
1530 DCHECK_EQ(id_, 0u);
1531}
1532
1533void FrameBuffer::Create() {
1534 ScopedGLErrorSuppressor suppressor(decoder_);
1535 Destroy();
1536 glGenFramebuffersEXT(1, &id_);
1537}
1538
1539void FrameBuffer::AttachRenderTexture(Texture* texture) {
1540 DCHECK_NE(id_, 0u);
1541 ScopedGLErrorSuppressor suppressor(decoder_);
1542 ScopedFrameBufferBinder binder(decoder_, id_);
1543 GLuint attach_id = texture ? texture->id() : 0;
1544 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1545 GL_COLOR_ATTACHMENT0,
1546 GL_TEXTURE_2D,
1547 attach_id,
1548 0);
1549}
1550
[email protected]b9363b22010-06-09 22:06:151551void FrameBuffer::AttachRenderBuffer(GLenum target,
1552 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351553 DCHECK_NE(id_, 0u);
1554 ScopedGLErrorSuppressor suppressor(decoder_);
1555 ScopedFrameBufferBinder binder(decoder_, id_);
1556 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1557 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151558 target,
[email protected]6217d392010-03-25 22:08:351559 GL_RENDERBUFFER,
1560 attach_id);
1561}
1562
1563void FrameBuffer::Clear(GLbitfield buffers) {
1564 ScopedGLErrorSuppressor suppressor(decoder_);
1565 ScopedFrameBufferBinder binder(decoder_, id_);
1566 glClear(buffers);
1567}
1568
1569void FrameBuffer::Destroy() {
1570 if (id_ != 0) {
1571 ScopedGLErrorSuppressor suppressor(decoder_);
1572 glDeleteFramebuffersEXT(1, &id_);
1573 id_ = 0;
1574 }
1575}
1576
[email protected]97872062010-11-03 19:07:051577void FrameBuffer::Invalidate() {
1578 id_ = 0;
1579}
1580
[email protected]6217d392010-03-25 22:08:351581GLenum FrameBuffer::CheckStatus() {
1582 DCHECK_NE(id_, 0u);
1583 ScopedGLErrorSuppressor suppressor(decoder_);
1584 ScopedFrameBufferBinder binder(decoder_, id_);
1585 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1586}
1587
[email protected]fbe20372011-06-01 01:46:381588GLES2Decoder* GLES2Decoder::Create(SurfaceManager* surface_manager,
1589 ContextGroup* group) {
1590 return new GLES2DecoderImpl(surface_manager, group);
[email protected]96449d2c2009-11-25 00:01:321591}
1592
[email protected]fbe20372011-06-01 01:46:381593GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
1594 ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391595 : GLES2Decoder(),
[email protected]fbe20372011-06-01 01:46:381596 surface_manager_(surface_manager),
[email protected]a3ded6d2010-10-19 06:44:391597 group_(ContextGroup::Ref(group ? group : new ContextGroup())),
[email protected]96449d2c2009-11-25 00:01:321598 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321599 pack_alignment_(4),
1600 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241601 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491602 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241603 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401604 fixed_attrib_buffer_id_(0),
1605 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501606 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281607 clear_red_(0),
1608 clear_green_(0),
1609 clear_blue_(0),
1610 clear_alpha_(0),
1611 mask_red_(true),
1612 mask_green_(true),
1613 mask_blue_(true),
1614 mask_alpha_(true),
1615 clear_stencil_(0),
1616 mask_stencil_front_(-1),
1617 mask_stencil_back_(-1),
1618 clear_depth_(1.0f),
1619 mask_depth_(true),
1620 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461621 enable_depth_test_(false),
1622 enable_stencil_test_(false),
1623 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021624 offscreen_target_color_format_(0),
1625 offscreen_target_depth_format_(0),
1626 offscreen_target_stencil_format_(0),
1627 offscreen_target_samples_(0),
[email protected]5ea88812011-03-28 10:45:391628 copy_texture_to_parent_texture_fb_(0),
[email protected]97872062010-11-03 19:07:051629 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:131630 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461631 back_buffer_has_depth_(false),
1632 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301633 teximage2d_faster_than_texsubimage2d_(true),
1634 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561635 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051636 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111637 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001638 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241639 tex_image_2d_failed_(false),
1640 frame_number_(0) {
[email protected]b1122982010-05-17 23:04:241641 attrib_0_value_.v[0] = 0.0f;
1642 attrib_0_value_.v[1] = 0.0f;
1643 attrib_0_value_.v[2] = 0.0f;
1644 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151645
[email protected]c2f8c8402010-12-06 18:07:241646 // The shader translator is used for WebGL even when running on EGL
1647 // because additional restrictions are needed (like only enabling
1648 // GL_OES_standard_derivatives on demand). It is used for the unit
1649 // tests because
1650 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1651 // empty string to CompileShader and this is not a valid shader.
1652 // TODO(apatrick): fix this test.
1653 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1654 !feature_info_->feature_flags().chromium_webglsl) ||
[email protected]b9363b22010-06-09 22:06:151655 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1656 use_shader_translator_ = false;
1657 }
[email protected]473c01ccb2011-06-07 01:33:301658
1659 // TODO(gman): Consider setting these based on GPU and/or driver.
1660 if (IsAngle()) {
1661 teximage2d_faster_than_texsubimage2d_ = false;
1662 bufferdata_faster_than_buffersubdata_ = false;
1663 }
[email protected]96449d2c2009-11-25 00:01:321664}
1665
[email protected]c410da802011-03-14 19:17:411666bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381667 const scoped_refptr<gfx::GLSurface>& surface,
1668 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411669 const gfx::Size& size,
1670 const DisallowedExtensions& disallowed_extensions,
1671 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241672 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541673 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301674 DCHECK(!context_.get());
1675
[email protected]fbe20372011-06-01 01:46:381676 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1677 // context is retired, the decoder should not take an initial surface as
1678 // an argument to this function.
1679 // Maybe create a short lived offscreen GLSurface for the purpose of
1680 // initializing the decoder's GLContext.
1681 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151682
[email protected]66791e382010-07-14 20:48:301683 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381684 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021685
[email protected]246a70452010-03-05 21:53:501686 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011687 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1688 << "MakeCurrent failed.";
[email protected]246a70452010-03-05 21:53:501689 Destroy();
1690 return false;
[email protected]eb54a562010-01-20 21:55:181691 }
1692
[email protected]c410da802011-03-14 19:17:411693 if (!group_->Initialize(disallowed_extensions, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221694 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391695 << "failed to initialize.";
1696 Destroy();
[email protected]ae1741092010-11-17 19:16:031697 return false;
[email protected]a3ded6d2010-10-19 06:44:391698 }
1699
[email protected]246a70452010-03-05 21:53:501700 CHECK_GL_ERROR();
[email protected]c410da802011-03-14 19:17:411701 disallowed_extensions_ = disallowed_extensions;
[email protected]246a70452010-03-05 21:53:501702
[email protected]f39f4b3f2010-05-12 17:04:081703 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321704
[email protected]302ce6d2011-07-07 23:28:111705 util_.set_num_compressed_texture_formats(
1706 validators_->compressed_texture_format.GetValues().size());
1707
[email protected]1071e572011-02-09 20:00:121708 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1709 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1710 // OpenGL ES 2.0 does not have this issue.
1711 glEnableVertexAttribArray(0);
1712 }
[email protected]b1122982010-05-17 23:04:241713 glGenBuffersARB(1, &attrib_0_buffer_id_);
1714 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1715 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1716 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401717 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081718
[email protected]246a70452010-03-05 21:53:501719 texture_units_.reset(
1720 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151721 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491722 glActiveTexture(GL_TEXTURE0 + tt);
1723 // Do cube map first because we want the last bind to be 2D.
1724 TextureManager::TextureInfo* info =
[email protected]1958e0e2010-04-22 05:17:151725 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491726 texture_units_[tt].bound_texture_cube_map = info;
1727 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1728 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1729 texture_units_[tt].bound_texture_2d = info;
1730 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151731 }
[email protected]00f893d2010-08-24 18:55:491732 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501733 CHECK_GL_ERROR();
1734
[email protected]297ca1c2011-06-20 23:08:461735 ContextCreationAttribParser attrib_parser;
1736 if (!attrib_parser.Parse(attribs))
1737 return false;
[email protected]41c56362011-06-14 16:47:431738
[email protected]297ca1c2011-06-20 23:08:461739 // These are NOT if the back buffer has these proprorties. They are
1740 // if we want the command buffer to enforce them regardless of what
1741 // the real backbuffer is assuming the real back buffer gives us more than
1742 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
1743 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
1744 // can't do anything about that.
1745
1746 GLint v = 0;
1747 glGetIntegerv(GL_ALPHA_BITS, &v);
1748 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
1749 // user requested RGB then RGB. If the user did not specify a preference than
1750 // use whatever we were given. Same for DEPTH and STENCIL.
1751 back_buffer_color_format_ =
1752 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
1753 glGetIntegerv(GL_DEPTH_BITS, &v);
1754 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
1755 glGetIntegerv(GL_STENCIL_BITS, &v);
1756 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
1757
1758 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:021759 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:541760 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:021761 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
1762 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:431763 // max_sample_count must be initialized to a sane value. If
1764 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
1765 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:021766 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
1767 offscreen_target_samples_ = std::min(attrib_parser.samples_,
1768 max_sample_count);
1769 } else {
1770 offscreen_target_samples_ = 1;
1771 }
1772
1773 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1774 const bool rgb8_supported =
1775 context_->HasExtension("GL_OES_rgb8_rgba8");
1776 // The only available default render buffer formats in GLES2 have very
1777 // little precision. Don't enable multisampling unless 8-bit render
1778 // buffer formats are available--instead fall back to 8-bit textures.
1779 if (rgb8_supported && offscreen_target_samples_ > 1) {
1780 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1781 GL_RGBA8 : GL_RGB8;
1782 } else {
1783 offscreen_target_samples_ = 1;
1784 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1785 GL_RGBA : GL_RGB;
1786 }
1787
1788 // ANGLE only supports packed depth/stencil formats, so use it if it is
1789 // available.
1790 const bool depth24_stencil8_supported =
1791 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271792 VLOG(1) << "GL_OES_packed_depth_stencil "
1793 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:001794 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1795 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021796 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1797 offscreen_target_stencil_format_ = 0;
1798 } else {
1799 // It may be the case that this depth/stencil combination is not
1800 // supported, but this will be checked later by CheckFramebufferStatus.
1801 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1802 GL_DEPTH_COMPONENT16 : 0;
1803 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1804 GL_STENCIL_INDEX8 : 0;
1805 }
1806 } else {
1807 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1808 GL_RGBA : GL_RGB;
1809
1810 // If depth is requested at all, use the packed depth stencil format if
1811 // it's available, as some desktop GL drivers don't support any non-packed
1812 // formats for depth attachments.
1813 const bool depth24_stencil8_supported =
1814 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271815 VLOG(1) << "GL_EXT_packed_depth_stencil "
1816 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:021817
[email protected]71ee3642010-10-14 18:08:001818 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1819 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021820 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1821 offscreen_target_stencil_format_ = 0;
1822 } else {
1823 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1824 GL_DEPTH_COMPONENT : 0;
1825 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1826 GL_STENCIL_INDEX : 0;
1827 }
1828 }
1829
[email protected]97872062010-11-03 19:07:051830 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
1831 GL_RGBA : GL_RGB;
1832
[email protected]6217d392010-03-25 22:08:351833 // Create the target frame buffer. This is the one that the client renders
1834 // directly to.
1835 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1836 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021837 // Due to GLES2 format limitations, either the color texture (for
1838 // non-multisampling) or the color render buffer (for multisampling) will be
1839 // attached to the offscreen frame buffer. The render buffer has more
1840 // limited formats available to it, but the texture can't do multisampling.
1841 if (IsOffscreenBufferMultisampled()) {
1842 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
1843 offscreen_target_color_render_buffer_->Create();
1844 } else {
1845 offscreen_target_color_texture_.reset(new Texture(this));
1846 offscreen_target_color_texture_->Create();
1847 }
1848 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151849 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021850 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151851 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:351852
1853 // Create the saved offscreen texture. The target frame buffer is copied
1854 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021855 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
1856 offscreen_saved_frame_buffer_->Create();
1857 //
[email protected]6217d392010-03-25 22:08:351858 offscreen_saved_color_texture_.reset(new Texture(this));
1859 offscreen_saved_color_texture_->Create();
1860
[email protected]6217d392010-03-25 22:08:351861 // Allocate the render buffers at their initial size and check the status
1862 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021863 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351864 if (!UpdateOffscreenFrameBufferSize()) {
[email protected]d0498742010-09-20 20:27:011865 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:351866 Destroy();
1867 return false;
1868 }
1869
1870 // Bind to the new default frame buffer (the offscreen target frame buffer).
1871 // This should now be associated with ID zero.
1872 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]a3a93e7b2010-08-28 00:48:561873
1874 glGenFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:351875 }
1876
[email protected]76a0ee102010-04-07 21:03:041877 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1878 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1879 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:371880 // mailing list archives. It also implicitly enables the desktop GL
1881 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
1882 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:151883 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1884 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:371885 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:151886 }
[email protected]de17df392010-04-23 21:09:411887
[email protected]c2f8c8402010-12-06 18:07:241888 if (!InitializeShaderTranslator()) {
1889 return false;
[email protected]de17df392010-04-23 21:09:411890 }
[email protected]76a0ee102010-04-07 21:03:041891
[email protected]246a70452010-03-05 21:53:501892 return true;
[email protected]96449d2c2009-11-25 00:01:321893}
1894
[email protected]302ce6d2011-07-07 23:28:111895void GLES2DecoderImpl::UpdateCapabilities() {
1896 util_.set_num_compressed_texture_formats(
1897 validators_->compressed_texture_format.GetValues().size());
1898 util_.set_num_shader_binary_formats(
1899 validators_->shader_binary_format.GetValues().size());
1900}
1901
[email protected]c2f8c8402010-12-06 18:07:241902bool GLES2DecoderImpl::InitializeShaderTranslator() {
1903 // Re-check the state of use_shader_translator_ each time this is called.
1904 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1905 feature_info_->feature_flags().chromium_webglsl &&
1906 !use_shader_translator_) {
1907 use_shader_translator_ = true;
1908 }
1909 if (!use_shader_translator_) {
1910 return true;
1911 }
1912 ShBuiltInResources resources;
1913 ShInitBuiltInResources(&resources);
1914 resources.MaxVertexAttribs = group_->max_vertex_attribs();
1915 resources.MaxVertexUniformVectors =
1916 group_->max_vertex_uniform_vectors();
1917 resources.MaxVaryingVectors = group_->max_varying_vectors();
1918 resources.MaxVertexTextureImageUnits =
1919 group_->max_vertex_texture_image_units();
1920 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
1921 resources.MaxTextureImageUnits = group_->max_texture_image_units();
1922 resources.MaxFragmentUniformVectors =
1923 group_->max_fragment_uniform_vectors();
1924 resources.MaxDrawBuffers = 1;
1925 resources.OES_standard_derivatives =
1926 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
1927 vertex_translator_.reset(new ShaderTranslator);
1928 ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ?
1929 SH_WEBGL_SPEC : SH_GLES2_SPEC;
1930 bool is_glsl_es =
1931 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
1932 if (!vertex_translator_->Init(
1933 SH_VERTEX_SHADER, shader_spec, &resources, is_glsl_es)) {
1934 LOG(ERROR) << "Could not initialize vertex shader translator.";
1935 Destroy();
1936 return false;
1937 }
1938 fragment_translator_.reset(new ShaderTranslator);
1939 if (!fragment_translator_->Init(
1940 SH_FRAGMENT_SHADER, shader_spec, &resources, is_glsl_es)) {
1941 LOG(ERROR) << "Could not initialize fragment shader translator.";
1942 Destroy();
1943 return false;
1944 }
1945 return true;
1946}
1947
[email protected]ae51d192010-04-27 00:48:031948bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471949 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031950 if (GetBufferInfo(client_ids[ii])) {
1951 return false;
1952 }
1953 }
1954 scoped_array<GLuint> service_ids(new GLuint[n]);
1955 glGenBuffersARB(n, service_ids.get());
1956 for (GLsizei ii = 0; ii < n; ++ii) {
1957 CreateBufferInfo(client_ids[ii], service_ids[ii]);
1958 }
1959 return true;
1960}
1961
1962bool GLES2DecoderImpl::GenFramebuffersHelper(
1963 GLsizei n, const GLuint* client_ids) {
1964 for (GLsizei ii = 0; ii < n; ++ii) {
1965 if (GetFramebufferInfo(client_ids[ii])) {
1966 return false;
1967 }
1968 }
1969 scoped_array<GLuint> service_ids(new GLuint[n]);
1970 glGenFramebuffersEXT(n, service_ids.get());
1971 for (GLsizei ii = 0; ii < n; ++ii) {
1972 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
1973 }
1974 return true;
1975}
1976
1977bool GLES2DecoderImpl::GenRenderbuffersHelper(
1978 GLsizei n, const GLuint* client_ids) {
1979 for (GLsizei ii = 0; ii < n; ++ii) {
1980 if (GetRenderbufferInfo(client_ids[ii])) {
1981 return false;
1982 }
1983 }
1984 scoped_array<GLuint> service_ids(new GLuint[n]);
1985 glGenRenderbuffersEXT(n, service_ids.get());
1986 for (GLsizei ii = 0; ii < n; ++ii) {
1987 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
1988 }
1989 return true;
1990}
1991
1992bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
1993 for (GLsizei ii = 0; ii < n; ++ii) {
1994 if (GetTextureInfo(client_ids[ii])) {
1995 return false;
1996 }
1997 }
1998 scoped_array<GLuint> service_ids(new GLuint[n]);
1999 glGenTextures(n, service_ids.get());
2000 for (GLsizei ii = 0; ii < n; ++ii) {
2001 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2002 }
2003 return true;
2004}
2005
2006void GLES2DecoderImpl::DeleteBuffersHelper(
2007 GLsizei n, const GLuint* client_ids) {
2008 for (GLsizei ii = 0; ii < n; ++ii) {
2009 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
2010 if (info) {
2011 GLuint service_id = info->service_id();
2012 glDeleteBuffersARB(1, &service_id);
2013 RemoveBufferInfo(client_ids[ii]);
2014 }
[email protected]a93bb842010-02-16 23:03:472015 }
[email protected]07f54fcc2009-12-22 02:46:302016}
2017
[email protected]ae51d192010-04-27 00:48:032018void GLES2DecoderImpl::DeleteFramebuffersHelper(
2019 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582020 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032021 FramebufferManager::FramebufferInfo* info =
2022 GetFramebufferInfo(client_ids[ii]);
2023 if (info) {
[email protected]297ca1c2011-06-20 23:08:462024 if (info == bound_draw_framebuffer_) {
2025 bound_draw_framebuffer_ = NULL;
2026 state_dirty_ = true;
2027 }
[email protected]ae51d192010-04-27 00:48:032028 GLuint service_id = info->service_id();
2029 glDeleteFramebuffersEXT(1, &service_id);
2030 RemoveFramebufferInfo(client_ids[ii]);
2031 }
[email protected]a25fa872010-03-25 02:57:582032 }
[email protected]07f54fcc2009-12-22 02:46:302033}
2034
[email protected]ae51d192010-04-27 00:48:032035void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2036 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582037 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032038 RenderbufferManager::RenderbufferInfo* info =
2039 GetRenderbufferInfo(client_ids[ii]);
2040 if (info) {
[email protected]297ca1c2011-06-20 23:08:462041 state_dirty_ = true;
[email protected]ae51d192010-04-27 00:48:032042 GLuint service_id = info->service_id();
2043 glDeleteRenderbuffersEXT(1, &service_id);
2044 RemoveRenderbufferInfo(client_ids[ii]);
2045 }
[email protected]a25fa872010-03-25 02:57:582046 }
[email protected]07f54fcc2009-12-22 02:46:302047}
2048
[email protected]ae51d192010-04-27 00:48:032049void GLES2DecoderImpl::DeleteTexturesHelper(
2050 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472051 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032052 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
2053 if (info) {
[email protected]297ca1c2011-06-20 23:08:462054 if (info->IsAttachedToFramebuffer()) {
2055 state_dirty_ = true;
2056 }
[email protected]ae51d192010-04-27 00:48:032057 GLuint service_id = info->service_id();
2058 glDeleteTextures(1, &service_id);
2059 RemoveTextureInfo(client_ids[ii]);
2060 }
[email protected]a93bb842010-02-16 23:03:472061 }
[email protected]07f54fcc2009-12-22 02:46:302062}
2063
[email protected]43f28f832010-02-03 02:28:482064// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322065
[email protected]eb54a562010-01-20 21:55:182066bool GLES2DecoderImpl::MakeCurrent() {
[email protected]f62a5ab2011-05-23 20:34:152067 return context_.get() ? context_->MakeCurrent(surface_.get()) : false;
[email protected]eb54a562010-01-20 21:55:182068}
2069
[email protected]8e3e0662010-08-23 18:46:302070void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2071 glBindRenderbufferEXT(
2072 GL_RENDERBUFFER,
2073 bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
2074}
2075
2076static void RebindCurrentFramebuffer(
2077 GLenum target,
2078 FramebufferManager::FramebufferInfo* info,
2079 FrameBuffer* offscreen_frame_buffer) {
2080 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462081
[email protected]8e3e0662010-08-23 18:46:302082 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2083 framebuffer_id = offscreen_frame_buffer->id();
2084 }
[email protected]297ca1c2011-06-20 23:08:462085
[email protected]8e3e0662010-08-23 18:46:302086 glBindFramebufferEXT(target, framebuffer_id);
2087}
2088
2089void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462090 state_dirty_ = true;
2091
[email protected]a3ded6d2010-10-19 06:44:392092 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302093 RebindCurrentFramebuffer(
2094 GL_FRAMEBUFFER,
2095 bound_draw_framebuffer_.get(),
2096 offscreen_target_frame_buffer_.get());
2097 } else {
2098 RebindCurrentFramebuffer(
2099 GL_READ_FRAMEBUFFER_EXT,
2100 bound_read_framebuffer_.get(),
2101 offscreen_target_frame_buffer_.get());
2102 RebindCurrentFramebuffer(
2103 GL_DRAW_FRAMEBUFFER_EXT,
2104 bound_draw_framebuffer_.get(),
2105 offscreen_target_frame_buffer_.get());
2106 }
2107}
2108
2109void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2110 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2111 GLuint last_id;
2112 if (info.bound_texture_2d) {
2113 last_id = info.bound_texture_2d->service_id();
2114 } else {
2115 last_id = 0;
2116 }
2117
2118 glBindTexture(GL_TEXTURE_2D, last_id);
2119 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2120}
2121
[email protected]3a03a8f2011-03-19 00:51:272122bool GLES2DecoderImpl::CheckFramebufferComplete(const char* func_name) {
2123 if (bound_draw_framebuffer_ && bound_draw_framebuffer_->IsNotComplete()) {
[email protected]be45d7c2011-04-15 18:03:352124 SetGLError(GL_INVALID_FRAMEBUFFER_OPERATION,
[email protected]3a03a8f2011-03-19 00:51:272125 (std::string(func_name) + " framebuffer incomplete").c_str());
2126 return false;
2127 }
2128 return true;
2129}
2130
[email protected]8e3e0662010-08-23 18:46:302131gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2132 if (bound_read_framebuffer_ != 0) {
[email protected]9edc6b22010-12-23 02:00:262133 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2134 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2135 if (attachment) {
2136 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502137 }
[email protected]9edc6b22010-12-23 02:00:262138 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022139 } else if (offscreen_target_frame_buffer_.get()) {
2140 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352141 } else {
[email protected]f62a5ab2011-05-23 20:34:152142 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022143 }
[email protected]246a70452010-03-05 21:53:502144}
2145
[email protected]9edc6b22010-12-23 02:00:262146GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
2147 if (bound_read_framebuffer_ != 0) {
[email protected]297ca1c2011-06-20 23:08:462148 return bound_read_framebuffer_->GetColorAttachmentFormat();
2149 } else if (offscreen_target_frame_buffer_.get()) {
2150 return offscreen_target_color_format_;
2151 } else {
2152 return back_buffer_color_format_;
2153 }
2154}
2155
2156GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
2157 if (bound_draw_framebuffer_ != 0) {
2158 return bound_draw_framebuffer_->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262159 } else if (offscreen_target_frame_buffer_.get()) {
2160 return offscreen_target_color_format_;
2161 } else {
[email protected]32fe9aa2011-01-21 23:47:132162 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262163 }
2164}
2165
[email protected]6217d392010-03-25 22:08:352166bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]34ff8b0c2010-10-01 20:06:022167 if (offscreen_size_ == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:352168 return true;
2169
[email protected]34ff8b0c2010-10-01 20:06:022170 offscreen_size_ = pending_offscreen_size_;
[email protected]a470d612011-02-25 04:15:002171 int w = offscreen_size_.width();
2172 int h = offscreen_size_.height();
2173 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2174 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2175 << "to allocate storage due to excessive dimensions.";
2176 return false;
2177 }
[email protected]34ff8b0c2010-10-01 20:06:022178
[email protected]6217d392010-03-25 22:08:352179 // Reallocate the offscreen target buffers.
[email protected]34ff8b0c2010-10-01 20:06:022180 DCHECK(offscreen_target_color_format_);
2181 if (IsOffscreenBufferMultisampled()) {
2182 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2183 pending_offscreen_size_, offscreen_target_color_format_,
2184 offscreen_target_samples_)) {
2185 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2186 << "to allocate storage for offscreen target color buffer.";
2187 return false;
2188 }
2189 } else {
2190 if (!offscreen_target_color_texture_->AllocateStorage(
2191 pending_offscreen_size_, offscreen_target_color_format_)) {
2192 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2193 << "to allocate storage for offscreen target color texture.";
2194 return false;
2195 }
2196 }
2197 if (offscreen_target_depth_format_ &&
2198 !offscreen_target_depth_render_buffer_->AllocateStorage(
2199 pending_offscreen_size_, offscreen_target_depth_format_,
2200 offscreen_target_samples_)) {
[email protected]d0498742010-09-20 20:27:012201 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
[email protected]34ff8b0c2010-10-01 20:06:022202 << "to allocate storage for offscreen target depth buffer.";
2203 return false;
2204 }
2205 if (offscreen_target_stencil_format_ &&
2206 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2207 pending_offscreen_size_, offscreen_target_stencil_format_,
2208 offscreen_target_samples_)) {
2209 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2210 << "to allocate storage for offscreen target stencil buffer.";
[email protected]6217d392010-03-25 22:08:352211 return false;
2212 }
2213
[email protected]2f2d7042010-04-14 21:45:582214 // Attach the offscreen target buffers to the target frame buffer.
[email protected]34ff8b0c2010-10-01 20:06:022215 if (IsOffscreenBufferMultisampled()) {
[email protected]b9363b22010-06-09 22:06:152216 offscreen_target_frame_buffer_->AttachRenderBuffer(
[email protected]34ff8b0c2010-10-01 20:06:022217 GL_COLOR_ATTACHMENT0,
2218 offscreen_target_color_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152219 } else {
[email protected]34ff8b0c2010-10-01 20:06:022220 offscreen_target_frame_buffer_->AttachRenderTexture(
2221 offscreen_target_color_texture_.get());
2222 }
2223 if (offscreen_target_depth_format_) {
2224 offscreen_target_frame_buffer_->AttachRenderBuffer(
2225 GL_DEPTH_ATTACHMENT,
2226 offscreen_target_depth_render_buffer_.get());
2227 }
2228 const bool packed_depth_stencil =
2229 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2230 if (packed_depth_stencil) {
[email protected]b9363b22010-06-09 22:06:152231 offscreen_target_frame_buffer_->AttachRenderBuffer(
2232 GL_STENCIL_ATTACHMENT,
2233 offscreen_target_depth_render_buffer_.get());
[email protected]34ff8b0c2010-10-01 20:06:022234 } else if (offscreen_target_stencil_format_) {
2235 offscreen_target_frame_buffer_->AttachRenderBuffer(
2236 GL_STENCIL_ATTACHMENT,
2237 offscreen_target_stencil_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152238 }
[email protected]34ff8b0c2010-10-01 20:06:022239
[email protected]6217d392010-03-25 22:08:352240 if (offscreen_target_frame_buffer_->CheckStatus() !=
2241 GL_FRAMEBUFFER_COMPLETE) {
[email protected]d0498742010-09-20 20:27:012242 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2243 << "because offscreen FBO was incomplete.";
[email protected]6217d392010-03-25 22:08:352244 return false;
2245 }
2246
[email protected]c007aa02010-09-02 22:22:402247 // Clear the target frame buffer.
2248 {
2249 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]297ca1c2011-06-20 23:08:462250 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2251 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
[email protected]c007aa02010-09-02 22:22:402252 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2253 glClearStencil(0);
[email protected]297ca1c2011-06-20 23:08:462254 glStencilMaskSeparate(GL_FRONT, -1);
2255 glStencilMaskSeparate(GL_BACK, -1);
[email protected]c007aa02010-09-02 22:22:402256 glClearDepth(0);
2257 glDepthMask(GL_TRUE);
2258 glDisable(GL_SCISSOR_TEST);
[email protected]2f2d7042010-04-14 21:45:582259 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402260 RestoreClearState();
[email protected]2f2d7042010-04-14 21:45:582261 }
[email protected]2f2d7042010-04-14 21:45:582262
[email protected]34ff8b0c2010-10-01 20:06:022263 if (parent_ || IsOffscreenBufferMultisampled()) {
[email protected]97872062010-11-03 19:07:052264 DCHECK(offscreen_saved_color_format_);
2265 offscreen_saved_color_texture_->AllocateStorage(
2266 pending_offscreen_size_, offscreen_saved_color_format_);
[email protected]d37231fa2010-04-09 21:16:022267
[email protected]34ff8b0c2010-10-01 20:06:022268 offscreen_saved_frame_buffer_->AttachRenderTexture(
2269 offscreen_saved_color_texture_.get());
2270 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2271 GL_FRAMEBUFFER_COMPLETE) {
2272 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2273 << "because offscreen saved FBO was incomplete.";
2274 return false;
2275 }
2276 }
2277
2278 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582279 // Update the info about the offscreen saved color texture in the parent.
2280 // The reference to the parent is a weak pointer and will become null if the
2281 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352282 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142283 GLuint client_id;
[email protected]262d7aa2010-12-03 22:07:292284 TextureManager* parent_texture_manager = parent_->texture_manager();
2285 CHECK(parent_texture_manager->GetClientId(service_id, &client_id));
[email protected]8d25d042010-06-16 19:48:142286 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352287 DCHECK(info);
2288
[email protected]262d7aa2010-12-03 22:07:292289 parent_texture_manager->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:112290 feature_info_,
[email protected]ef526492010-06-02 23:12:252291 info,
2292 GL_TEXTURE_2D,
2293 0, // level
2294 GL_RGBA,
2295 pending_offscreen_size_.width(),
2296 pending_offscreen_size_.height(),
2297 1, // depth
2298 0, // border
2299 GL_RGBA,
2300 GL_UNSIGNED_BYTE);
[email protected]262d7aa2010-12-03 22:07:292301 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042302 feature_info_,
2303 info,
2304 GL_TEXTURE_MAG_FILTER,
2305 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292306 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042307 feature_info_,
2308 info,
2309 GL_TEXTURE_MIN_FILTER,
2310 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292311 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042312 feature_info_,
2313 info,
2314 GL_TEXTURE_WRAP_S,
2315 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292316 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042317 feature_info_,
2318 info,
2319 GL_TEXTURE_WRAP_T,
2320 GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:352321
[email protected]c007aa02010-09-02 22:22:402322 // Clear the offscreen color texture.
2323 {
[email protected]34ff8b0c2010-10-01 20:06:022324 ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:402325 glClearColor(0, 0, 0, 0);
2326 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2327 glDisable(GL_SCISSOR_TEST);
[email protected]0c8c9d22010-06-25 17:36:392328 glClear(GL_COLOR_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402329 RestoreClearState();
[email protected]0c8c9d22010-06-25 17:36:392330 }
[email protected]0c8c9d22010-06-25 17:36:392331 }
[email protected]e566b955d2010-06-22 19:26:512332
[email protected]6217d392010-03-25 22:08:352333 return true;
2334}
2335
[email protected]7ff86b92010-11-25 17:50:002336void GLES2DecoderImpl::SetResizeCallback(Callback1<gfx::Size>::Type* callback) {
2337 resize_callback_.reset(callback);
2338}
2339
[email protected]43f28f832010-02-03 02:28:482340void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
2341 swap_buffers_callback_.reset(callback);
2342}
2343
[email protected]80c49752011-04-18 23:55:102344void GLES2DecoderImpl::SetLatchCallback(
2345 const base::Callback<void(bool)>& callback) {
2346 latch_callback_ = callback;
2347}
2348
[email protected]1318e922010-09-17 22:03:162349bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2350 uint32* service_texture_id) {
2351 TextureManager::TextureInfo* texture =
2352 texture_manager()->GetTextureInfo(client_texture_id);
2353 if (texture) {
2354 *service_texture_id = texture->service_id();
2355 return true;
2356 }
2357 return false;
2358}
2359
[email protected]96449d2c2009-11-25 00:01:322360void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392361 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052362
2363 if (group_.get())
2364 group_->set_have_context(have_context);
2365
[email protected]3c644d82011-06-20 19:58:242366 SetParent(NULL, 0);
2367
[email protected]eadc96792010-10-27 19:39:392368 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142369 if (current_program_) {
2370 program_manager()->UnuseProgram(shader_manager(), current_program_);
2371 current_program_ = NULL;
2372 }
2373
[email protected]b1122982010-05-17 23:04:242374 if (attrib_0_buffer_id_) {
2375 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2376 }
[email protected]8fbedc02010-11-18 18:43:402377 if (fixed_attrib_buffer_id_) {
2378 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2379 }
[email protected]b1122982010-05-17 23:04:242380
[email protected]3c644d82011-06-20 19:58:242381 if (copy_texture_to_parent_texture_fb_)
[email protected]a3a93e7b2010-08-28 00:48:562382 glDeleteFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:352383
[email protected]97872062010-11-03 19:07:052384 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542385 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052386 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542387 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052388 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022389 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052390 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152391 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052392 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152393 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052394 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022395 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052396 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542397 offscreen_saved_color_texture_->Destroy();
[email protected]66791e382010-07-14 20:48:302398
[email protected]eadc96792010-10-27 19:39:392399 // must release the ContextGroup before destroying the context as its
2400 // destructor uses GL.
2401 group_ = NULL;
[email protected]97872062010-11-03 19:07:052402 } else {
2403 if (offscreen_target_frame_buffer_.get())
2404 offscreen_target_frame_buffer_->Invalidate();
2405 if (offscreen_target_color_texture_.get())
2406 offscreen_target_color_texture_->Invalidate();
2407 if (offscreen_target_color_render_buffer_.get())
2408 offscreen_target_color_render_buffer_->Invalidate();
2409 if (offscreen_target_depth_render_buffer_.get())
2410 offscreen_target_depth_render_buffer_->Invalidate();
2411 if (offscreen_target_stencil_render_buffer_.get())
2412 offscreen_target_stencil_render_buffer_->Invalidate();
2413 if (offscreen_saved_frame_buffer_.get())
2414 offscreen_saved_frame_buffer_->Invalidate();
2415 if (offscreen_saved_color_texture_.get())
2416 offscreen_saved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022417 }
[email protected]97872062010-11-03 19:07:052418
[email protected]fe871662011-06-16 20:43:052419 if (context_.get()) {
2420 context_->ReleaseCurrent(NULL);
[email protected]0fc35742011-04-13 17:57:542421 context_->Destroy();
[email protected]fe871662011-06-16 20:43:052422 }
[email protected]fbe20372011-06-01 01:46:382423 context_ = NULL;
[email protected]0fc35742011-04-13 17:57:542424
[email protected]97872062010-11-03 19:07:052425 offscreen_target_frame_buffer_.reset();
2426 offscreen_target_color_texture_.reset();
2427 offscreen_target_color_render_buffer_.reset();
2428 offscreen_target_depth_render_buffer_.reset();
2429 offscreen_target_stencil_render_buffer_.reset();
2430 offscreen_saved_frame_buffer_.reset();
2431 offscreen_saved_color_texture_.reset();
[email protected]96449d2c2009-11-25 00:01:322432}
2433
[email protected]3c644d82011-06-20 19:58:242434bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2435 uint32 new_parent_texture_id) {
2436 // Remove the saved frame buffer mapping from the parent decoder. The
2437 // parent pointer is a weak pointer so it will be null if the parent has
2438 // already been destroyed.
2439 if (parent_) {
2440 // First check the texture has been mapped into the parent. This might not
2441 // be the case if initialization failed midway through.
2442 GLuint service_id = offscreen_saved_color_texture_->id();
2443 GLuint client_id = 0;
2444 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
2445 parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
2446 }
2447 }
2448
2449 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2450 new_parent);
2451 if (new_parent_impl) {
2452 // Map the ID of the saved offscreen texture into the parent so that
2453 // it can reference it.
2454 GLuint service_id = offscreen_saved_color_texture_->id();
2455 TextureManager::TextureInfo* info =
2456 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
2457 info->SetNotOwned();
2458 new_parent_impl->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
2459
2460 parent_ = new_parent_impl->AsWeakPtr();
2461 } else {
2462 parent_.reset();
2463 }
2464
2465 return true;
2466}
2467
[email protected]6217d392010-03-25 22:08:352468void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2469 // We can't resize the render buffers immediately because there might be a
2470 // partial frame rendered into them and we don't want the tail end of that
2471 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:022472 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352473}
2474
[email protected]269200b12010-11-18 22:53:062475void GLES2DecoderImpl::DoCopyTextureToParentTextureCHROMIUM(
[email protected]c007aa02010-09-02 22:22:402476 GLuint client_texture_id,
2477 GLuint parent_client_texture_id) {
[email protected]a3a93e7b2010-08-28 00:48:562478 if (parent_) {
[email protected]c007aa02010-09-02 22:22:402479 TextureManager::TextureInfo* texture = texture_manager()->GetTextureInfo(
2480 client_texture_id);
2481 TextureManager::TextureInfo* parent_texture =
2482 parent_->texture_manager()->GetTextureInfo(parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:562483 if (!texture || !parent_texture) {
2484 current_decoder_error_ = error::kInvalidArguments;
2485 return;
2486 }
2487 ScopedFrameBufferBinder fb_binder(this, copy_texture_to_parent_texture_fb_);
2488 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2489 GL_COLOR_ATTACHMENT0,
2490 GL_TEXTURE_2D,
2491 texture->service_id(),
2492 0);
2493 ScopedTexture2DBinder tex_binder(this, parent_texture->service_id());
2494 GLsizei width, height;
2495 parent_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
2496 glCopyTexImage2D(GL_TEXTURE_2D,
2497 0, // level
2498 GL_RGBA,
[email protected]c007aa02010-09-02 22:22:402499 0, 0, // x, y
[email protected]a3a93e7b2010-08-28 00:48:562500 width,
2501 height,
2502 0); // border
2503 }
2504}
2505
[email protected]43ecf372010-11-16 19:19:392506void GLES2DecoderImpl::DoResizeCHROMIUM(GLuint width, GLuint height) {
[email protected]23f771162011-06-02 18:37:512507#if defined(OS_POSIX) && !defined(OS_MACOSX)
[email protected]7ff86b92010-11-25 17:50:002508 // Make sure that we are done drawing to the back buffer before resizing.
2509 glFinish();
2510#endif
2511 if (resize_callback_.get()) {
2512 gfx::Size size(width, height);
2513 resize_callback_->Run(size);
2514 }
[email protected]43ecf372010-11-16 19:19:392515}
2516
[email protected]fbe20372011-06-01 01:46:382517void GLES2DecoderImpl::DoSetSurfaceCHROMIUM(GLint surface_id) {
2518 gfx::GLSurface* surface = surface_manager_->LookupSurface(surface_id);
2519 if (!surface)
2520 return;
2521
2522 surface_ = surface;
2523}
2524
[email protected]96449d2c2009-11-25 00:01:322525const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2526 if (command_id > kStartPoint && command_id < kNumCommands) {
2527 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2528 }
2529 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2530}
2531
2532// Decode command with its arguments, and call the corresponding GL function.
2533// Note: args is a pointer to the command buffer. As such, it could be changed
2534// by a (malicious) client at any time, so if validation has to happen, it
2535// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142536error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322537 unsigned int command,
2538 unsigned int arg_count,
2539 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142540 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192541 if (debug()) {
2542 // TODO(gman): Change output to something useful for NaCl.
[email protected]8e1b98a2011-06-14 23:39:532543 DLOG(INFO) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192544 }
[email protected]96449d2c2009-11-25 00:01:322545 unsigned int command_index = command - kStartPoint - 1;
2546 if (command_index < arraysize(g_command_info)) {
2547 const CommandInfo& info = g_command_info[command_index];
2548 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2549 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2550 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192551 uint32 immediate_data_size =
2552 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322553 switch (command) {
2554 #define GLES2_CMD_OP(name) \
2555 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192556 result = Handle ## name( \
2557 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322558 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192559 break; \
[email protected]96449d2c2009-11-25 00:01:322560
2561 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322562 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382563 }
2564 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302565 GLenum error;
2566 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382567 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292568 SetGLError(error, NULL);
[email protected]8e1b98a2011-06-14 23:39:532569 DLOG(INFO) << "[" << this << "]"
2570 << "GL ERROR: " << error << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192571 }
[email protected]96449d2c2009-11-25 00:01:322572 }
2573 } else {
[email protected]f7a64ee2010-02-01 22:24:142574 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322575 }
[email protected]b9849abf2009-11-25 19:13:192576 } else {
2577 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322578 }
[email protected]a3a93e7b2010-08-28 00:48:562579 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
2580 result = current_decoder_error_;
2581 current_decoder_error_ = error::kNoError;
2582 }
[email protected]b9849abf2009-11-25 19:13:192583 return result;
[email protected]96449d2c2009-11-25 00:01:322584}
2585
[email protected]ae51d192010-04-27 00:48:032586void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2587 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502588}
2589
[email protected]ae51d192010-04-27 00:48:032590bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2591 if (GetProgramInfo(client_id)) {
2592 return false;
2593 }
[email protected]96449d2c2009-11-25 00:01:322594 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032595 if (service_id != 0) {
2596 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322597 }
[email protected]ae51d192010-04-27 00:48:032598 return true;
[email protected]96449d2c2009-11-25 00:01:322599}
2600
[email protected]ae51d192010-04-27 00:48:032601bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2602 if (GetShaderInfo(client_id)) {
2603 return false;
[email protected]96449d2c2009-11-25 00:01:322604 }
[email protected]ae51d192010-04-27 00:48:032605 GLuint service_id = glCreateShader(type);
2606 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382607 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032608 }
2609 return true;
[email protected]96449d2c2009-11-25 00:01:322610}
2611
[email protected]3916c97e2010-02-25 03:20:502612void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452613 GLuint texture_index = texture_unit - GL_TEXTURE0;
2614 if (texture_index > group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292615 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502616 return;
2617 }
[email protected]36cef8ce2010-03-16 07:34:452618 active_texture_unit_ = texture_index;
2619 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502620}
2621
[email protected]051b1372010-04-12 02:42:082622void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502623 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082624 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032625 if (client_id != 0) {
2626 info = GetBufferInfo(client_id);
2627 if (!info) {
2628 // It's a new id so make a buffer info for it.
2629 glGenBuffersARB(1, &service_id);
2630 CreateBufferInfo(client_id, service_id);
2631 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102632 IdAllocator* id_allocator =
2633 group_->GetIdAllocator(id_namespaces::kBuffers);
2634 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032635 }
[email protected]051b1372010-04-12 02:42:082636 }
[email protected]ae51d192010-04-27 00:48:032637 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102638 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292639 SetGLError(GL_INVALID_OPERATION,
2640 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472641 return;
2642 }
[email protected]ae51d192010-04-27 00:48:032643 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472644 }
[email protected]96449d2c2009-11-25 00:01:322645 switch (target) {
2646 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502647 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322648 break;
2649 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502650 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322651 break;
2652 default:
[email protected]a93bb842010-02-16 23:03:472653 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322654 break;
2655 }
[email protected]051b1372010-04-12 02:42:082656 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322657}
2658
[email protected]297ca1c2011-06-20 23:08:462659bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
2660 return (GLES2Util::GetChannelsForFormat(
2661 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
2662}
2663
2664bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
2665 if (bound_draw_framebuffer_) {
2666 return bound_draw_framebuffer_->HasDepthAttachment();
2667 }
2668 if (offscreen_target_frame_buffer_.get()) {
2669 return offscreen_target_depth_format_ != 0;
2670 }
2671 return back_buffer_has_depth_;
2672}
2673
2674bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
2675 if (bound_draw_framebuffer_) {
2676 return bound_draw_framebuffer_->HasStencilAttachment();
2677 }
2678 if (offscreen_target_frame_buffer_.get()) {
2679 return offscreen_target_stencil_format_ != 0 ||
2680 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2681 }
2682 return back_buffer_has_stencil_;
2683}
2684
2685void GLES2DecoderImpl::ApplyDirtyState() {
2686 if (state_dirty_) {
2687 glColorMask(
2688 mask_red_, mask_green_, mask_blue_,
2689 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
2690 bool have_depth = BoundFramebufferHasDepthAttachment();
2691 glDepthMask(mask_depth_ && have_depth);
2692 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
2693 bool have_stencil = BoundFramebufferHasStencilAttachment();
2694 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
2695 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
2696 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
2697 state_dirty_ = false;
2698 }
2699}
2700
[email protected]051b1372010-04-12 02:42:082701void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2702 FramebufferManager::FramebufferInfo* info = NULL;
2703 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032704 if (client_id != 0) {
2705 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082706 if (!info) {
[email protected]ae51d192010-04-27 00:48:032707 // It's a new id so make a framebuffer info for it.
2708 glGenFramebuffersEXT(1, &service_id);
2709 CreateFramebufferInfo(client_id, service_id);
2710 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102711 IdAllocator* id_allocator =
2712 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2713 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032714 } else {
2715 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082716 }
[email protected]06c8b082011-01-05 18:00:362717 info->MarkAsValid();
[email protected]eff9a222010-12-21 21:48:562718 } else {
[email protected]f62a5ab2011-05-23 20:34:152719 service_id = 0;
[email protected]051b1372010-04-12 02:42:082720 }
[email protected]8e3e0662010-08-23 18:46:302721
2722 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
2723 bound_draw_framebuffer_ = info;
2724 }
2725 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
2726 bound_read_framebuffer_ = info;
2727 }
[email protected]6217d392010-03-25 22:08:352728
[email protected]297ca1c2011-06-20 23:08:462729 state_dirty_ = true;
2730
[email protected]6217d392010-03-25 22:08:352731 // When rendering to an offscreen frame buffer, instead of unbinding from
2732 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]297ca1c2011-06-20 23:08:462733 if (info == NULL && offscreen_target_frame_buffer_.get()) {
[email protected]051b1372010-04-12 02:42:082734 service_id = offscreen_target_frame_buffer_->id();
[email protected]297ca1c2011-06-20 23:08:462735 }
[email protected]6217d392010-03-25 22:08:352736
[email protected]051b1372010-04-12 02:42:082737 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562738}
2739
[email protected]051b1372010-04-12 02:42:082740void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2741 RenderbufferManager::RenderbufferInfo* info = NULL;
2742 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032743 if (client_id != 0) {
2744 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082745 if (!info) {
[email protected]ae51d192010-04-27 00:48:032746 // It's a new id so make a renderbuffer info for it.
2747 glGenRenderbuffersEXT(1, &service_id);
2748 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102749 info = GetRenderbufferInfo(client_id);
2750 IdAllocator* id_allocator =
2751 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2752 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032753 } else {
2754 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082755 }
[email protected]06c8b082011-01-05 18:00:362756 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:082757 }
2758 bound_renderbuffer_ = info;
2759 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562760}
2761
[email protected]051b1372010-04-12 02:42:082762void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032763 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082764 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032765 if (client_id != 0) {
2766 info = GetTextureInfo(client_id);
2767 if (!info) {
2768 // It's a new id so make a texture info for it.
2769 glGenTextures(1, &service_id);
2770 CreateTextureInfo(client_id, service_id);
2771 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:102772 IdAllocator* id_allocator =
2773 group_->GetIdAllocator(id_namespaces::kTextures);
2774 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032775 }
2776 } else {
2777 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082778 }
[email protected]ae51d192010-04-27 00:48:032779
[email protected]1958e0e2010-04-22 05:17:152780 // Check the texture exists
2781 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032782 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292783 SetGLError(GL_INVALID_OPERATION,
2784 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152785 return;
2786 }
2787 if (info->target() == 0) {
2788 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472789 }
[email protected]ae51d192010-04-27 00:48:032790 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502791 TextureUnit& unit = texture_units_[active_texture_unit_];
2792 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472793 switch (target) {
2794 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502795 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472796 break;
2797 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502798 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472799 break;
2800 default:
2801 NOTREACHED(); // Validation should prevent us getting here.
2802 break;
2803 }
2804}
2805
[email protected]07f54fcc2009-12-22 02:46:302806void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082807 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:122808 if (index != 0 ||
2809 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:242810 glDisableVertexAttribArray(index);
2811 }
[email protected]07f54fcc2009-12-22 02:46:302812 } else {
[email protected]8eee29c2010-04-29 03:38:292813 SetGLError(GL_INVALID_VALUE,
2814 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302815 }
2816}
2817
2818void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082819 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302820 glEnableVertexAttribArray(index);
2821 } else {
[email protected]8eee29c2010-04-29 03:38:292822 SetGLError(GL_INVALID_VALUE,
2823 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302824 }
2825}
2826
[email protected]a93bb842010-02-16 23:03:472827void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502828 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]915a59a12010-09-30 21:29:112829 if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) {
[email protected]8eee29c2010-04-29 03:38:292830 SetGLError(GL_INVALID_OPERATION,
2831 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472832 return;
2833 }
[email protected]59f3ca02011-03-26 22:24:192834 // Workaround for Mac driver bug. In the large scheme of things setting
2835 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
2836 // hit so there's probably no need to make this conditional.
2837 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
[email protected]a93bb842010-02-16 23:03:472838 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:192839 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:472840}
2841
[email protected]b273e432010-04-12 17:23:582842bool GLES2DecoderImpl::GetHelper(
2843 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582844 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152845 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2846 switch (pname) {
[email protected]b273e432010-04-12 17:23:582847 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2848 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102849 if (params) {
[email protected]5094b0f2010-11-09 19:45:242850 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:102851 }
[email protected]b273e432010-04-12 17:23:582852 return true;
2853 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2854 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102855 if (params) {
[email protected]5094b0f2010-11-09 19:45:242856 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:102857 }
[email protected]b273e432010-04-12 17:23:582858 return true;
2859 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2860 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102861 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482862 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102863 }
[email protected]b273e432010-04-12 17:23:582864 return true;
2865 case GL_MAX_VARYING_VECTORS:
2866 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102867 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482868 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102869 }
[email protected]b273e432010-04-12 17:23:582870 return true;
2871 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2872 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102873 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482874 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102875 }
[email protected]b273e432010-04-12 17:23:582876 return true;
[email protected]5094b0f2010-11-09 19:45:242877 case GL_MAX_VIEWPORT_DIMS:
2878 if (offscreen_target_frame_buffer_.get()) {
2879 *num_written = 2;
2880 if (params) {
2881 params[0] = renderbuffer_manager()->max_renderbuffer_size();
2882 params[1] = renderbuffer_manager()->max_renderbuffer_size();
2883 }
2884 return true;
2885 }
[email protected]b9363b22010-06-09 22:06:152886 }
2887 }
2888 switch (pname) {
[email protected]297ca1c2011-06-20 23:08:462889 case GL_COLOR_WRITEMASK:
2890 *num_written = 4;
2891 if (params) {
2892 params[0] = mask_red_;
2893 params[1] = mask_green_;
2894 params[2] = mask_blue_;
2895 params[3] = mask_alpha_;
2896 }
2897 return true;
2898 case GL_DEPTH_WRITEMASK:
2899 *num_written = 1;
2900 if (params) {
2901 params[0] = mask_depth_;
2902 }
2903 return true;
2904 case GL_STENCIL_BACK_WRITEMASK:
2905 *num_written = 1;
2906 if (params) {
2907 params[0] = mask_stencil_back_;
2908 }
2909 return true;
2910 case GL_STENCIL_WRITEMASK:
2911 *num_written = 1;
2912 if (params) {
2913 params[0] = mask_stencil_front_;
2914 }
2915 return true;
2916 case GL_DEPTH_TEST:
2917 *num_written = 1;
2918 if (params) {
2919 params[0] = enable_depth_test_;
2920 }
2921 return true;
2922 case GL_STENCIL_TEST:
2923 *num_written = 1;
2924 if (params) {
2925 params[0] = enable_stencil_test_;
2926 }
2927 return true;
2928 case GL_ALPHA_BITS:
2929 *num_written = 1;
2930 if (params) {
2931 GLint v = 0;
2932 glGetIntegerv(GL_ALPHA_BITS, &v);
2933 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
2934 }
2935 return true;
2936 case GL_DEPTH_BITS:
2937 *num_written = 1;
2938 if (params) {
2939 GLint v = 0;
2940 glGetIntegerv(GL_DEPTH_BITS, &v);
2941 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
2942 }
2943 return true;
2944 case GL_STENCIL_BITS:
2945 *num_written = 1;
2946 if (params) {
2947 GLint v = 0;
2948 glGetIntegerv(GL_STENCIL_BITS, &v);
2949 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
2950 }
2951 return true;
[email protected]656dcaad2010-05-07 17:18:372952 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:112953 *num_written = validators_->compressed_texture_format.GetValues().size();
2954 if (params) {
2955 for (GLint ii = 0; ii < *num_written; ++ii) {
2956 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
2957 }
2958 }
[email protected]656dcaad2010-05-07 17:18:372959 return true;
[email protected]b273e432010-04-12 17:23:582960 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
2961 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102962 if (params) {
[email protected]302ce6d2011-07-07 23:28:112963 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:102964 }
[email protected]b273e432010-04-12 17:23:582965 return true;
2966 case GL_NUM_SHADER_BINARY_FORMATS:
2967 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102968 if (params) {
[email protected]302ce6d2011-07-07 23:28:112969 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:102970 }
[email protected]b273e432010-04-12 17:23:582971 return true;
2972 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:112973 *num_written = validators_->shader_binary_format.GetValues().size();
2974 if (params) {
2975 for (GLint ii = 0; ii < *num_written; ++ii) {
2976 params[ii] = validators_->shader_binary_format.GetValues()[ii];
2977 }
2978 }
2979 return true;
[email protected]b273e432010-04-12 17:23:582980 case GL_SHADER_COMPILER:
2981 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102982 if (params) {
2983 *params = GL_TRUE;
2984 }
[email protected]b273e432010-04-12 17:23:582985 return true;
[email protected]6b8cf1a2010-05-06 16:13:582986 case GL_ARRAY_BUFFER_BINDING:
2987 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102988 if (params) {
2989 if (bound_array_buffer_) {
2990 GLuint client_id = 0;
2991 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
2992 &client_id);
2993 *params = client_id;
2994 } else {
2995 *params = 0;
2996 }
[email protected]6b8cf1a2010-05-06 16:13:582997 }
2998 return true;
2999 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3000 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103001 if (params) {
3002 if (bound_element_array_buffer_) {
3003 GLuint client_id = 0;
3004 buffer_manager()->GetClientId(
3005 bound_element_array_buffer_->service_id(),
3006 &client_id);
3007 *params = client_id;
3008 } else {
3009 *params = 0;
3010 }
[email protected]6b8cf1a2010-05-06 16:13:583011 }
3012 return true;
3013 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303014 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583015 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103016 if (params) {
[email protected]8e3e0662010-08-23 18:46:303017 if (bound_draw_framebuffer_) {
[email protected]4e8a5b122010-05-08 22:00:103018 GLuint client_id = 0;
3019 framebuffer_manager()->GetClientId(
[email protected]8e3e0662010-08-23 18:46:303020 bound_draw_framebuffer_->service_id(), &client_id);
3021 *params = client_id;
3022 } else {
3023 *params = 0;
3024 }
3025 }
3026 return true;
3027 case GL_READ_FRAMEBUFFER_BINDING:
3028 *num_written = 1;
3029 if (params) {
3030 if (bound_read_framebuffer_) {
3031 GLuint client_id = 0;
3032 framebuffer_manager()->GetClientId(
3033 bound_read_framebuffer_->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103034 *params = client_id;
3035 } else {
3036 *params = 0;
3037 }
[email protected]6b8cf1a2010-05-06 16:13:583038 }
3039 return true;
3040 case GL_RENDERBUFFER_BINDING:
3041 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103042 if (params) {
3043 if (bound_renderbuffer_) {
3044 GLuint client_id = 0;
3045 renderbuffer_manager()->GetClientId(
3046 bound_renderbuffer_->service_id(), &client_id);
3047 *params = client_id;
3048 } else {
3049 *params = 0;
3050 }
[email protected]6b8cf1a2010-05-06 16:13:583051 }
3052 return true;
3053 case GL_CURRENT_PROGRAM:
3054 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103055 if (params) {
3056 if (current_program_) {
3057 GLuint client_id = 0;
3058 program_manager()->GetClientId(
3059 current_program_->service_id(), &client_id);
3060 *params = client_id;
3061 } else {
3062 *params = 0;
3063 }
[email protected]6b8cf1a2010-05-06 16:13:583064 }
3065 return true;
[email protected]4e8a5b122010-05-08 22:00:103066 case GL_TEXTURE_BINDING_2D:
3067 *num_written = 1;
3068 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583069 TextureUnit& unit = texture_units_[active_texture_unit_];
3070 if (unit.bound_texture_2d) {
3071 GLuint client_id = 0;
3072 texture_manager()->GetClientId(
3073 unit.bound_texture_2d->service_id(), &client_id);
3074 *params = client_id;
3075 } else {
3076 *params = 0;
3077 }
[email protected]6b8cf1a2010-05-06 16:13:583078 }
[email protected]4e8a5b122010-05-08 22:00:103079 return true;
3080 case GL_TEXTURE_BINDING_CUBE_MAP:
3081 *num_written = 1;
3082 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583083 TextureUnit& unit = texture_units_[active_texture_unit_];
3084 if (unit.bound_texture_cube_map) {
3085 GLuint client_id = 0;
3086 texture_manager()->GetClientId(
3087 unit.bound_texture_cube_map->service_id(), &client_id);
3088 *params = client_id;
3089 } else {
3090 *params = 0;
3091 }
[email protected]6b8cf1a2010-05-06 16:13:583092 }
[email protected]4e8a5b122010-05-08 22:00:103093 return true;
[email protected]b273e432010-04-12 17:23:583094 default:
[email protected]4e8a5b122010-05-08 22:00:103095 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533096 return false;
[email protected]b273e432010-04-12 17:23:583097 }
3098}
3099
[email protected]4e8a5b122010-05-08 22:00:103100bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3101 GLenum pname, GLsizei* num_values) {
3102 return GetHelper(pname, NULL, num_values);
3103}
3104
[email protected]b273e432010-04-12 17:23:583105void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3106 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103107 GLsizei num_written = 0;
3108 if (GetHelper(pname, NULL, &num_written)) {
3109 scoped_array<GLint> values(new GLint[num_written]);
3110 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583111 for (GLsizei ii = 0; ii < num_written; ++ii) {
3112 params[ii] = static_cast<GLboolean>(values[ii]);
3113 }
3114 } else {
3115 glGetBooleanv(pname, params);
3116 }
3117}
3118
3119void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3120 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103121 GLsizei num_written = 0;
3122 if (GetHelper(pname, NULL, &num_written)) {
3123 scoped_array<GLint> values(new GLint[num_written]);
3124 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583125 for (GLsizei ii = 0; ii < num_written; ++ii) {
3126 params[ii] = static_cast<GLfloat>(values[ii]);
3127 }
3128 } else {
3129 glGetFloatv(pname, params);
3130 }
3131}
3132
3133void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3134 DCHECK(params);
3135 GLsizei num_written;
3136 if (!GetHelper(pname, params, &num_written)) {
3137 glGetIntegerv(pname, params);
3138 }
3139}
3140
[email protected]a0c3e972010-04-21 00:49:133141void GLES2DecoderImpl::DoGetProgramiv(
3142 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583143 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3144 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133145 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133146 return;
3147 }
3148 info->GetProgramiv(pname, params);
3149}
3150
[email protected]558847a2010-03-24 07:02:543151error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3152 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:583153 GLuint program = static_cast<GLuint>(c.program);
3154 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3155 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033156 if (!info) {
[email protected]558847a2010-03-24 07:02:543157 return error::kNoError;
3158 }
3159 GLuint index = static_cast<GLuint>(c.index);
3160 uint32 name_size = c.data_size;
3161 const char* name = GetSharedMemoryAs<const char*>(
3162 c.name_shm_id, c.name_shm_offset, name_size);
3163 if (name == NULL) {
3164 return error::kOutOfBounds;
3165 }
3166 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033167 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543168 return error::kNoError;
3169}
3170
3171error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3172 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583173 GLuint program = static_cast<GLuint>(c.program);
3174 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3175 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033176 if (!info) {
[email protected]558847a2010-03-24 07:02:543177 return error::kNoError;
3178 }
3179 GLuint index = static_cast<GLuint>(c.index);
3180 uint32 name_size = c.data_size;
3181 const char* name = GetImmediateDataAs<const char*>(
3182 c, name_size, immediate_data_size);
3183 if (name == NULL) {
3184 return error::kOutOfBounds;
3185 }
3186 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033187 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543188 return error::kNoError;
3189}
3190
3191error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3192 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583193 GLuint program = static_cast<GLuint>(c.program);
3194 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3195 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033196 if (!info) {
[email protected]558847a2010-03-24 07:02:543197 return error::kNoError;
3198 }
3199 GLuint index = static_cast<GLuint>(c.index);
3200 Bucket* bucket = GetBucket(c.name_bucket_id);
3201 if (!bucket || bucket->size() == 0) {
3202 return error::kInvalidArguments;
3203 }
3204 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183205 if (!bucket->GetAsString(&name_str)) {
3206 return error::kInvalidArguments;
3207 }
[email protected]ae51d192010-04-27 00:48:033208 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543209 return error::kNoError;
3210}
3211
[email protected]f7a64ee2010-02-01 22:24:143212error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463213 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033214 GLuint client_id = c.shader;
3215 if (client_id) {
3216 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3217 if (info) {
[email protected]ca488e12010-12-13 20:06:143218 if (!info->IsDeleted()) {
3219 glDeleteShader(info->service_id());
3220 shader_manager()->MarkAsDeleted(info);
3221 }
[email protected]ae51d192010-04-27 00:48:033222 } else {
[email protected]8eee29c2010-04-29 03:38:293223 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033224 }
[email protected]96449d2c2009-11-25 00:01:323225 }
[email protected]f7a64ee2010-02-01 22:24:143226 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323227}
3228
[email protected]f7a64ee2010-02-01 22:24:143229error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463230 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033231 GLuint client_id = c.program;
3232 if (client_id) {
3233 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3234 if (info) {
[email protected]ca488e12010-12-13 20:06:143235 if (!info->IsDeleted()) {
3236 glDeleteProgram(info->service_id());
3237 program_manager()->MarkAsDeleted(shader_manager(), info);
3238 }
[email protected]ae51d192010-04-27 00:48:033239 } else {
[email protected]8eee29c2010-04-29 03:38:293240 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033241 }
[email protected]96449d2c2009-11-25 00:01:323242 }
[email protected]f7a64ee2010-02-01 22:24:143243 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323244}
3245
[email protected]269200b12010-11-18 22:53:063246void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103247 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3248 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3249 for (GLsizei ii = 0; ii < n; ++ii) {
3250 id_allocator->FreeID(ids[ii]);
3251 }
3252}
3253
[email protected]269200b12010-11-18 22:53:063254error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3255 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103256 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3257 GLsizei n = static_cast<GLsizei>(c.n);
3258 uint32 data_size;
3259 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3260 return error::kOutOfBounds;
3261 }
3262 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3263 c.ids_shm_id, c.ids_shm_offset, data_size);
3264 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063265 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103266 return error::kNoError;
3267 }
3268 if (ids == NULL) {
3269 return error::kOutOfBounds;
3270 }
[email protected]269200b12010-11-18 22:53:063271 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103272 return error::kNoError;
3273}
3274
[email protected]269200b12010-11-18 22:53:063275void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103276 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
3277 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3278 if (id_offset == 0) {
3279 for (GLsizei ii = 0; ii < n; ++ii) {
3280 ids[ii] = id_allocator->AllocateID();
3281 }
3282 } else {
3283 for (GLsizei ii = 0; ii < n; ++ii) {
3284 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3285 id_offset = ids[ii] + 1;
3286 }
3287 }
3288}
3289
[email protected]269200b12010-11-18 22:53:063290error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3291 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103292 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3293 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3294 GLsizei n = static_cast<GLsizei>(c.n);
3295 uint32 data_size;
3296 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3297 return error::kOutOfBounds;
3298 }
3299 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3300 c.ids_shm_id, c.ids_shm_offset, data_size);
3301 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063302 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103303 return error::kNoError;
3304 }
3305 if (ids == NULL) {
3306 return error::kOutOfBounds;
3307 }
[email protected]269200b12010-11-18 22:53:063308 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103309 return error::kNoError;
3310}
3311
[email protected]269200b12010-11-18 22:53:063312void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103313 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3314 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3315 for (GLsizei ii = 0; ii < n; ++ii) {
3316 if (!id_allocator->MarkAsUsed(ids[ii])) {
3317 for (GLsizei jj = 0; jj < ii; ++jj) {
3318 id_allocator->FreeID(ids[jj]);
3319 }
3320 SetGLError(
3321 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063322 "RegisterSharedIdsCHROMIUM: attempt to register "
3323 "id that already exists");
[email protected]066849e32010-05-03 19:14:103324 return;
3325 }
3326 }
3327}
3328
[email protected]269200b12010-11-18 22:53:063329error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3330 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103331 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3332 GLsizei n = static_cast<GLsizei>(c.n);
3333 uint32 data_size;
3334 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3335 return error::kOutOfBounds;
3336 }
3337 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3338 c.ids_shm_id, c.ids_shm_offset, data_size);
3339 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063340 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103341 return error::kNoError;
3342 }
3343 if (ids == NULL) {
3344 return error::kOutOfBounds;
3345 }
[email protected]269200b12010-11-18 22:53:063346 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103347 return error::kNoError;
3348}
3349
[email protected]3a03a8f2011-03-19 00:51:273350void GLES2DecoderImpl::DoClear(GLbitfield mask) {
3351 if (CheckFramebufferComplete("glClear")) {
[email protected]297ca1c2011-06-20 23:08:463352 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:273353 glClear(mask);
3354 }
3355}
3356
[email protected]07f54fcc2009-12-22 02:46:303357void GLES2DecoderImpl::DoDrawArrays(
3358 GLenum mode, GLint first, GLsizei count) {
[email protected]3a03a8f2011-03-19 00:51:273359 if (!CheckFramebufferComplete("glDrawArrays")) {
3360 return;
3361 }
[email protected]d81e8c52010-06-07 17:58:323362 // We have to check this here because the prototype for glDrawArrays
3363 // is GLint not GLsizei.
3364 if (first < 0) {
[email protected]7601c3f2010-12-22 00:41:203365 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
[email protected]d81e8c52010-06-07 17:58:323366 return;
3367 }
[email protected]6c788fb72010-08-26 02:16:313368
3369 if (count == 0) {
3370 return;
3371 }
3372
[email protected]8fbedc02010-11-18 18:43:403373 GLuint max_vertex_accessed = first + count - 1;
3374 if (IsDrawValid(max_vertex_accessed)) {
3375 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
3376 bool simulated_fixed_attribs = false;
3377 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
3378 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:463379 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:403380 glDrawArrays(mode, first, count);
3381 if (textures_set) {
3382 RestoreStateForNonRenderableTextures();
3383 }
3384 if (simulated_fixed_attribs) {
3385 RestoreStateForSimulatedFixedAttribs();
3386 }
[email protected]3916c97e2010-02-25 03:20:503387 }
[email protected]b1122982010-05-17 23:04:243388 if (simulated_attrib_0) {
3389 RestoreStateForSimulatedAttrib0();
3390 }
[email protected]07f54fcc2009-12-22 02:46:303391 }
3392}
3393
[email protected]36cef8ce2010-03-16 07:34:453394void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3395 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033396 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303397 FramebufferManager::FramebufferInfo* framebuffer_info =
3398 GetFramebufferInfoForTarget(target);
3399 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293400 SetGLError(GL_INVALID_OPERATION,
3401 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453402 return;
3403 }
[email protected]ae51d192010-04-27 00:48:033404 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283405 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033406 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283407 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033408 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293409 SetGLError(GL_INVALID_OPERATION,
3410 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033411 return;
3412 }
3413 service_id = info->service_id();
3414 }
[email protected]9edc6b22010-12-23 02:00:263415 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033416 glFramebufferRenderbufferEXT(
3417 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:043418 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263419 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303420 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]9edc6b22010-12-23 02:00:263421 if (service_id == 0 ||
3422 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3423 if (info) {
3424 ClearUnclearedRenderbuffers(target, framebuffer_info);
3425 }
[email protected]3a2e7c7b2010-08-06 01:12:283426 }
3427 }
[email protected]297ca1c2011-06-20 23:08:463428 if (framebuffer_info == bound_draw_framebuffer_) {
3429 state_dirty_ = true;
3430 }
[email protected]3a2e7c7b2010-08-06 01:12:283431}
3432
[email protected]297ca1c2011-06-20 23:08:463433bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:283434 switch (cap) {
3435 case GL_SCISSOR_TEST:
3436 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:463437 return true;
3438 case GL_DEPTH_TEST: {
3439 if (enable_depth_test_ != enabled) {
3440 enable_depth_test_ = enabled;
3441 state_dirty_ = true;
3442 }
3443 return false;
3444 }
3445 case GL_STENCIL_TEST:
3446 if (enable_stencil_test_ != enabled) {
3447 enable_stencil_test_ = enabled;
3448 state_dirty_ = true;
3449 }
3450 return false;
[email protected]3a2e7c7b2010-08-06 01:12:283451 default:
[email protected]297ca1c2011-06-20 23:08:463452 return true;
[email protected]3a2e7c7b2010-08-06 01:12:283453 }
3454}
3455
3456void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463457 if (SetCapabilityState(cap, false)) {
3458 glDisable(cap);
3459 }
[email protected]3a2e7c7b2010-08-06 01:12:283460}
3461
3462void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463463 if (SetCapabilityState(cap, true)) {
3464 glEnable(cap);
3465 }
[email protected]3a2e7c7b2010-08-06 01:12:283466}
3467
3468void GLES2DecoderImpl::DoClearColor(
3469 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
3470 clear_red_ = red;
3471 clear_green_ = green;
3472 clear_blue_ = blue;
3473 clear_alpha_ = alpha;
3474 glClearColor(red, green, blue, alpha);
3475}
3476
3477void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
3478 clear_depth_ = depth;
3479 glClearDepth(depth);
3480}
3481
3482void GLES2DecoderImpl::DoClearStencil(GLint s) {
3483 clear_stencil_ = s;
3484 glClearStencil(s);
3485}
3486
3487void GLES2DecoderImpl::DoColorMask(
3488 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
3489 mask_red_ = red;
3490 mask_green_ = green;
3491 mask_blue_ = blue;
3492 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:463493 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283494}
3495
3496void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
3497 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:463498 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283499}
3500
3501void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
3502 mask_stencil_front_ = mask;
3503 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:463504 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283505}
3506
3507void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:463508 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283509 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:463510 }
3511 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283512 mask_stencil_back_ = mask;
3513 }
[email protected]297ca1c2011-06-20 23:08:463514 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283515}
3516
3517// NOTE: There's an assumption here that Texture attachments
3518// are cleared because they are textures so we only need to clear
3519// the renderbuffers.
3520void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
[email protected]8e3e0662010-08-23 18:46:303521 GLenum target, FramebufferManager::FramebufferInfo* info) {
3522 if (target == GL_READ_FRAMEBUFFER_EXT) {
3523 // TODO(gman): bind this to the DRAW point, clear then bind back to READ
3524 }
[email protected]3a2e7c7b2010-08-06 01:12:283525 GLbitfield clear_bits = 0;
3526 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:463527 glClearColor(
3528 0, 0, 0,
3529 (GLES2Util::GetChannelsForFormat(
3530 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0 : 1);
[email protected]3a2e7c7b2010-08-06 01:12:283531 glColorMask(true, true, true, true);
3532 clear_bits |= GL_COLOR_BUFFER_BIT;
3533 }
3534
3535 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
3536 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3537 glClearStencil(0);
3538 glStencilMask(-1);
3539 clear_bits |= GL_STENCIL_BUFFER_BIT;
3540 }
3541
3542 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
3543 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3544 glClearDepth(1.0f);
3545 glDepthMask(true);
3546 clear_bits |= GL_DEPTH_BUFFER_BIT;
3547 }
3548
3549 glDisable(GL_SCISSOR_TEST);
3550 glClear(clear_bits);
3551
3552 info->MarkAttachedRenderbuffersAsCleared();
3553
[email protected]c007aa02010-09-02 22:22:403554 RestoreClearState();
3555
3556 if (target == GL_READ_FRAMEBUFFER_EXT) {
3557 // TODO(gman): rebind draw.
3558 }
3559}
3560
3561void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:463562 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283563 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:283564 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:283565 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:283566 if (enable_scissor_test_) {
3567 glEnable(GL_SCISSOR_TEST);
3568 }
[email protected]36cef8ce2010-03-16 07:34:453569}
3570
3571GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]8e3e0662010-08-23 18:46:303572 FramebufferManager::FramebufferInfo* info =
3573 GetFramebufferInfoForTarget(target);
3574 if (!info) {
[email protected]36cef8ce2010-03-16 07:34:453575 return GL_FRAMEBUFFER_COMPLETE;
3576 }
3577 return glCheckFramebufferStatusEXT(target);
3578}
3579
3580void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033581 GLenum target, GLenum attachment, GLenum textarget,
3582 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303583 FramebufferManager::FramebufferInfo* framebuffer_info =
3584 GetFramebufferInfoForTarget(target);
3585 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293586 SetGLError(GL_INVALID_OPERATION,
3587 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453588 return;
3589 }
[email protected]ae51d192010-04-27 00:48:033590 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283591 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033592 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283593 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033594 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293595 SetGLError(GL_INVALID_OPERATION,
3596 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033597 return;
3598 }
3599 service_id = info->service_id();
3600 }
[email protected]9edc6b22010-12-23 02:00:263601 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033602 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:043603 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263604 if (error == GL_NO_ERROR) {
3605 framebuffer_info->AttachTexture(attachment, info, textarget, level);
3606 if (service_id != 0 &&
3607 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3608 ClearUnclearedRenderbuffers(target, framebuffer_info);
3609 }
[email protected]3a2e7c7b2010-08-06 01:12:283610 }
[email protected]297ca1c2011-06-20 23:08:463611 if (framebuffer_info == bound_draw_framebuffer_) {
3612 state_dirty_ = true;
3613 }
[email protected]36cef8ce2010-03-16 07:34:453614}
3615
3616void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3617 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303618 FramebufferManager::FramebufferInfo* framebuffer_info =
3619 GetFramebufferInfoForTarget(target);
3620 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293621 SetGLError(GL_INVALID_OPERATION,
3622 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453623 return;
3624 }
3625 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573626 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3627 GLint type = 0;
3628 GLuint client_id = 0;
3629 glGetFramebufferAttachmentParameterivEXT(
3630 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3631 switch (type) {
3632 case GL_RENDERBUFFER: {
3633 renderbuffer_manager()->GetClientId(*params, &client_id);
3634 break;
3635 }
3636 case GL_TEXTURE: {
3637 texture_manager()->GetClientId(*params, &client_id);
3638 break;
3639 }
3640 default:
3641 break;
3642 }
3643 *params = client_id;
3644 }
[email protected]36cef8ce2010-03-16 07:34:453645}
3646
3647void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
3648 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:083649 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293650 SetGLError(GL_INVALID_OPERATION,
3651 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453652 return;
3653 }
[email protected]3a03a8f2011-03-19 00:51:273654 switch (pname) {
3655 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]b71f52c2010-06-18 22:20:203656 *params = bound_renderbuffer_->internal_format();
[email protected]3a03a8f2011-03-19 00:51:273657 break;
3658 case GL_RENDERBUFFER_WIDTH:
3659 *params = bound_renderbuffer_->width();
3660 break;
3661 case GL_RENDERBUFFER_HEIGHT:
3662 *params = bound_renderbuffer_->height();
3663 break;
3664 default:
3665 glGetRenderbufferParameterivEXT(target, pname, params);
3666 break;
[email protected]b71f52c2010-06-18 22:20:203667 }
[email protected]36cef8ce2010-03-16 07:34:453668}
3669
[email protected]8e3e0662010-08-23 18:46:303670void GLES2DecoderImpl::DoBlitFramebufferEXT(
3671 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3672 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3673 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:393674 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303675 SetGLError(GL_INVALID_OPERATION,
3676 "glBlitFramebufferEXT: function not available");
3677 }
[email protected]5094b0f2010-11-09 19:45:243678 if (IsAngle()) {
3679 glBlitFramebufferANGLE(
3680 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3681 } else {
3682 glBlitFramebufferEXT(
3683 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3684 }
[email protected]8e3e0662010-08-23 18:46:303685}
3686
3687void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
3688 GLenum target, GLsizei samples, GLenum internalformat,
3689 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:393690 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303691 SetGLError(GL_INVALID_OPERATION,
3692 "glRenderbufferStorageMultisampleEXT: function not available");
3693 return;
3694 }
[email protected]8e3e0662010-08-23 18:46:303695
[email protected]9edc6b22010-12-23 02:00:263696 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:303697 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263698 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:303699 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263700 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:303701 break;
3702 case GL_RGBA4:
3703 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263704 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:303705 break;
3706 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263707 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:303708 break;
3709 }
3710 }
3711
[email protected]9edc6b22010-12-23 02:00:263712 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:083713 if (IsAngle()) {
3714 glRenderbufferStorageMultisampleANGLE(
3715 target, samples, impl_format, width, height);
3716 } else {
3717 glRenderbufferStorageMultisampleEXT(
3718 target, samples, impl_format, width, height);
3719 }
[email protected]1002c2d2011-06-28 22:39:043720 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263721 if (error == GL_NO_ERROR) {
3722 bound_renderbuffer_->SetInfo(samples, internalformat, width, height);
3723 }
[email protected]8e3e0662010-08-23 18:46:303724}
3725
[email protected]36cef8ce2010-03-16 07:34:453726void GLES2DecoderImpl::DoRenderbufferStorage(
3727 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:083728 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293729 SetGLError(GL_INVALID_OPERATION,
3730 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453731 return;
3732 }
[email protected]876f6fee2010-08-02 23:10:323733
[email protected]9edc6b22010-12-23 02:00:263734 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:323735 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263736 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:323737 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263738 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:323739 break;
3740 case GL_RGBA4:
3741 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263742 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:323743 break;
3744 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263745 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:323746 break;
3747 }
[email protected]b71f52c2010-06-18 22:20:203748 }
[email protected]876f6fee2010-08-02 23:10:323749
[email protected]9edc6b22010-12-23 02:00:263750 CopyRealGLErrorsToWrapper();
3751 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:043752 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263753 if (error == GL_NO_ERROR) {
3754 bound_renderbuffer_->SetInfo(0, internalformat, width, height);
3755 }
[email protected]36cef8ce2010-03-16 07:34:453756}
3757
[email protected]07f54fcc2009-12-22 02:46:303758void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:223759 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:583760 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3761 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:473762 if (!info) {
[email protected]a93bb842010-02-16 23:03:473763 return;
3764 }
[email protected]05afda12011-01-20 00:17:343765
[email protected]d685a682011-04-29 16:19:573766 info->Link();
[email protected]07f54fcc2009-12-22 02:46:303767};
3768
[email protected]3916c97e2010-02-25 03:20:503769void GLES2DecoderImpl::DoTexParameterf(
3770 GLenum target, GLenum pname, GLfloat param) {
3771 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:303772 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293773 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243774 return;
[email protected]07f54fcc2009-12-22 02:46:303775 }
[email protected]cbb22e42011-05-12 23:36:243776
3777 if (!texture_manager()->SetParameter(
3778 feature_info_, info, pname, static_cast<GLint>(param))) {
3779 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
3780 return;
3781 }
3782 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:303783}
3784
[email protected]3916c97e2010-02-25 03:20:503785void GLES2DecoderImpl::DoTexParameteri(
3786 GLenum target, GLenum pname, GLint param) {
3787 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3788 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293789 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243790 return;
[email protected]3916c97e2010-02-25 03:20:503791 }
[email protected]cbb22e42011-05-12 23:36:243792
3793 if (!texture_manager()->SetParameter(feature_info_, info, pname, param)) {
3794 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
3795 return;
3796 }
3797 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:503798}
3799
3800void GLES2DecoderImpl::DoTexParameterfv(
3801 GLenum target, GLenum pname, const GLfloat* params) {
3802 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3803 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293804 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243805 return;
[email protected]3916c97e2010-02-25 03:20:503806 }
[email protected]cbb22e42011-05-12 23:36:243807
3808 if (!texture_manager()->SetParameter(
3809 feature_info_, info, pname, static_cast<GLint>(params[0]))) {
3810 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
3811 return;
3812 }
3813 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503814}
3815
3816void GLES2DecoderImpl::DoTexParameteriv(
3817 GLenum target, GLenum pname, const GLint* params) {
3818 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3819 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293820 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243821 return;
[email protected]3916c97e2010-02-25 03:20:503822 }
[email protected]cbb22e42011-05-12 23:36:243823
3824 if (!texture_manager()->SetParameter(feature_info_, info, pname, *params)) {
3825 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
3826 return;
3827 }
3828 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503829}
3830
[email protected]939e7362010-05-13 20:49:103831bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:143832 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:103833 // The program does not exist.
3834 SetGLError(GL_INVALID_OPERATION,
3835 (std::string(function_name) + ": no program in use").c_str());
3836 return false;
3837 }
[email protected]ca488e12010-12-13 20:06:143838 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:103839 SetGLError(GL_INVALID_OPERATION,
3840 (std::string(function_name) + ": program not linked").c_str());
3841 return false;
3842 }
3843 return true;
3844}
3845
3846bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
3847 GLint location, const char* function_name) {
3848 if (!CheckCurrentProgram(function_name)) {
3849 return false;
3850 }
3851 return location != -1;
3852}
3853
[email protected]43c2f1f2011-03-25 18:35:363854bool GLES2DecoderImpl::PrepForSetUniformByLocation(
3855 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
3856 DCHECK(type);
3857 DCHECK(count);
[email protected]939e7362010-05-13 20:49:103858 if (!CheckCurrentProgramForUniform(location, function_name)) {
3859 return false;
3860 }
[email protected]43c2f1f2011-03-25 18:35:363861 GLint array_index = -1;
3862 const ProgramManager::ProgramInfo::UniformInfo* info =
3863 current_program_->GetUniformInfoByLocation(location, &array_index);
3864 if (!info) {
[email protected]939e7362010-05-13 20:49:103865 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:363866 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:103867 return false;
3868 }
[email protected]43c2f1f2011-03-25 18:35:363869 if (*count > 1 && !info->is_array) {
3870 SetGLError(
3871 GL_INVALID_OPERATION,
3872 (std::string(function_name) + ": count > 1 for non-array").c_str());
3873 return false;
3874 }
3875 *count = std::min(info->size - array_index, *count);
3876 if (*count <= 0) {
3877 return false;
3878 }
3879 *type = info->type;
[email protected]939e7362010-05-13 20:49:103880 return true;
3881}
3882
[email protected]939e7362010-05-13 20:49:103883void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
3884 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:503885 return;
3886 }
3887 current_program_->SetSamplers(location, 1, &v0);
3888 glUniform1i(location, v0);
3889}
3890
3891void GLES2DecoderImpl::DoUniform1iv(
3892 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:103893 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:503894 return;
3895 }
[email protected]43c2f1f2011-03-25 18:35:363896 GLenum type = 0;
3897 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
3898 return;
3899 }
3900 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE) {
3901 current_program_->SetSamplers(location, count, value);
3902 }
[email protected]3916c97e2010-02-25 03:20:503903 glUniform1iv(location, count, value);
3904}
3905
[email protected]939e7362010-05-13 20:49:103906void GLES2DecoderImpl::DoUniform1fv(
3907 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363908 GLenum type = 0;
3909 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103910 return;
3911 }
3912 if (type == GL_BOOL) {
3913 scoped_array<GLint> temp(new GLint[count]);
3914 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:533915 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103916 }
3917 DoUniform1iv(location, count, temp.get());
3918 } else {
3919 glUniform1fv(location, count, value);
3920 }
3921}
3922
3923void GLES2DecoderImpl::DoUniform2fv(
3924 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363925 GLenum type = 0;
3926 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103927 return;
3928 }
3929 if (type == GL_BOOL_VEC2) {
3930 GLsizei num_values = count * 2;
3931 scoped_array<GLint> temp(new GLint[num_values]);
3932 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533933 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103934 }
3935 glUniform2iv(location, count, temp.get());
3936 } else {
3937 glUniform2fv(location, count, value);
3938 }
3939}
3940
3941void GLES2DecoderImpl::DoUniform3fv(
3942 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363943 GLenum type = 0;
3944 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103945 return;
3946 }
3947 if (type == GL_BOOL_VEC3) {
3948 GLsizei num_values = count * 3;
3949 scoped_array<GLint> temp(new GLint[num_values]);
3950 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533951 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103952 }
3953 glUniform3iv(location, count, temp.get());
3954 } else {
3955 glUniform3fv(location, count, value);
3956 }
3957}
3958
3959void GLES2DecoderImpl::DoUniform4fv(
3960 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363961 GLenum type = 0;
3962 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103963 return;
3964 }
3965 if (type == GL_BOOL_VEC4) {
3966 GLsizei num_values = count * 4;
3967 scoped_array<GLint> temp(new GLint[num_values]);
3968 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533969 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103970 }
3971 glUniform4iv(location, count, temp.get());
3972 } else {
3973 glUniform4fv(location, count, value);
3974 }
3975}
3976
[email protected]43c2f1f2011-03-25 18:35:363977void GLES2DecoderImpl::DoUniform2iv(
3978 GLint location, GLsizei count, const GLint* value) {
3979 GLenum type = 0;
3980 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
3981 return;
3982 }
3983 glUniform2iv(location, count, value);
3984}
3985
3986void GLES2DecoderImpl::DoUniform3iv(
3987 GLint location, GLsizei count, const GLint* value) {
3988 GLenum type = 0;
3989 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
3990 return;
3991 }
3992 glUniform3iv(location, count, value);
3993}
3994
3995void GLES2DecoderImpl::DoUniform4iv(
3996 GLint location, GLsizei count, const GLint* value) {
3997 GLenum type = 0;
3998 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
3999 return;
4000 }
4001 glUniform4iv(location, count, value);
4002}
4003
4004void GLES2DecoderImpl::DoUniformMatrix2fv(
4005 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4006 GLenum type = 0;
4007 if (!PrepForSetUniformByLocation(
4008 location, "glUniformMatrix2fv", &type, &count)) {
4009 return;
4010 }
4011 glUniformMatrix2fv (location, count, transpose, value);
4012}
4013
4014void GLES2DecoderImpl::DoUniformMatrix3fv(
4015 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4016 GLenum type = 0;
4017 if (!PrepForSetUniformByLocation(
4018 location, "glUniformMatrix3fv", &type, &count)) {
4019 return;
4020 }
4021 glUniformMatrix3fv (location, count, transpose, value);
4022}
4023
4024void GLES2DecoderImpl::DoUniformMatrix4fv(
4025 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4026 GLenum type = 0;
4027 if (!PrepForSetUniformByLocation(
4028 location, "glUniformMatrix4fv", &type, &count)) {
4029 return;
4030 }
4031 glUniformMatrix4fv (location, count, transpose, value);
4032}
4033
[email protected]3916c97e2010-02-25 03:20:504034void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034035 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504036 ProgramManager::ProgramInfo* info = NULL;
4037 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584038 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504039 if (!info) {
[email protected]ae51d192010-04-27 00:48:034040 return;
4041 }
4042 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504043 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294044 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504045 return;
4046 }
[email protected]ae51d192010-04-27 00:48:034047 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504048 }
[email protected]ca488e12010-12-13 20:06:144049 if (current_program_) {
4050 program_manager()->UnuseProgram(shader_manager(), current_program_);
4051 }
[email protected]3916c97e2010-02-25 03:20:504052 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144053 if (current_program_) {
4054 program_manager()->UseProgram(current_program_);
4055 }
[email protected]ae51d192010-04-27 00:48:034056 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504057}
4058
[email protected]96449d2c2009-11-25 00:01:324059GLenum GLES2DecoderImpl::GetGLError() {
4060 // Check the GL error first, then our wrapped error.
4061 GLenum error = glGetError();
4062 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374063 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324064 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294065 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324066 break;
4067 }
4068 }
4069 }
4070
4071 if (error != GL_NO_ERROR) {
4072 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294073 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324074 }
4075 return error;
4076}
4077
[email protected]1002c2d2011-06-28 22:39:044078GLenum GLES2DecoderImpl::PeekGLError() {
4079 GLenum error = glGetError();
4080 if (error != GL_NO_ERROR) {
4081 SetGLError(error, "");
4082 }
4083 return error;
4084}
4085
[email protected]8eee29c2010-04-29 03:38:294086void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4087 if (msg) {
4088 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:014089 LOG(ERROR) << last_error_;
[email protected]8eee29c2010-04-29 03:38:294090 }
[email protected]ddd968b82010-03-02 00:44:294091 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324092}
4093
[email protected]07f54fcc2009-12-22 02:46:304094void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4095 GLenum error;
4096 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294097 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304098 }
4099}
4100
[email protected]6217d392010-03-25 22:08:354101void GLES2DecoderImpl::ClearRealGLErrors() {
4102 GLenum error;
4103 while ((error = glGetError()) != GL_NO_ERROR) {
4104 NOTREACHED() << "GL error " << error << " was unhandled.";
4105 }
4106}
4107
[email protected]ef526492010-06-02 23:12:254108bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504109 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254110 // Only check if there are some unrenderable textures.
4111 if (!texture_manager()->HaveUnrenderableTextures()) {
4112 return false;
4113 }
4114 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504115 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4116 current_program_->sampler_indices();
4117 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4118 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4119 current_program_->GetUniformInfo(sampler_indices[ii]);
4120 DCHECK(uniform_info);
4121 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4122 GLuint texture_unit_index = uniform_info->texture_units[jj];
4123 if (texture_unit_index < group_->max_texture_units()) {
4124 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4125 TextureManager::TextureInfo* texture_info =
4126 uniform_info->type == GL_SAMPLER_2D ?
4127 texture_unit.bound_texture_2d :
4128 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114129 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]ef526492010-06-02 23:12:254130 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504131 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4132 glBindTexture(
4133 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
4134 GL_TEXTURE_CUBE_MAP,
[email protected]00f893d2010-08-24 18:55:494135 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504136 }
4137 }
4138 // else: should this be an error?
4139 }
4140 }
[email protected]ef526492010-06-02 23:12:254141 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504142}
4143
4144void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4145 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504146 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4147 current_program_->sampler_indices();
4148 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4149 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4150 current_program_->GetUniformInfo(sampler_indices[ii]);
4151 DCHECK(uniform_info);
4152 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4153 GLuint texture_unit_index = uniform_info->texture_units[jj];
4154 if (texture_unit_index < group_->max_texture_units()) {
4155 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4156 TextureManager::TextureInfo* texture_info =
4157 uniform_info->type == GL_SAMPLER_2D ?
4158 texture_unit.bound_texture_2d :
4159 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114160 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]3916c97e2010-02-25 03:20:504161 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4162 // Get the texture info that was previously bound here.
4163 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4164 texture_unit.bound_texture_2d :
4165 texture_unit.bound_texture_cube_map;
4166 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034167 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504168 }
4169 }
4170 }
4171 }
4172 // Set the active texture back to whatever the user had it as.
4173 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304174}
4175
4176bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034177 // NOTE: We specifically do not check current_program->IsValid() because
4178 // it could never be invalid since glUseProgram would have failed. While
4179 // glLinkProgram could later mark the program as invalid the previous
4180 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144181 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504182 // The program does not exist.
4183 // But GL says no ERROR.
4184 return false;
4185 }
[email protected]f39f4b3f2010-05-12 17:04:084186 // Validate all attribs currently enabled. If they are used by the current
4187 // program then check that they have enough elements to handle the draw call.
4188 // If they are not used by the current program check that they have a buffer
4189 // assigned.
4190 const VertexAttribManager::VertexAttribInfoList& infos =
4191 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4192 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404193 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084194 const VertexAttribManager::VertexAttribInfo* info = *it;
4195 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4196 current_program_->GetAttribInfoByLocation(info->index());
4197 if (attrib_info) {
4198 // This attrib is used in the current program.
4199 if (!info->CanAccess(max_vertex_accessed)) {
4200 SetGLError(GL_INVALID_OPERATION,
4201 "glDrawXXX: attempt to access out of range vertices");
4202 return false;
4203 }
4204 } else {
4205 // This attrib is not used in the current program.
4206 if (!info->buffer() || info->buffer()->IsDeleted()) {
4207 SetGLError(
4208 GL_INVALID_OPERATION,
4209 "glDrawXXX: attempt to render with no buffer attached to enabled "
4210 "attrib");
4211 return false;
4212 }
[email protected]1d32bc82010-01-13 22:06:464213 }
[email protected]07f54fcc2009-12-22 02:46:304214 }
[email protected]3916c97e2010-02-25 03:20:504215 return true;
[email protected]b1122982010-05-17 23:04:244216}
4217
4218bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
[email protected]876f6fee2010-08-02 23:10:324219 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4220 return false;
4221
[email protected]b1122982010-05-17 23:04:244222 const VertexAttribManager::VertexAttribInfo* info =
4223 vertex_attrib_manager_.GetVertexAttribInfo(0);
4224 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494225 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4226 if (info->enabled() && attrib_0_used) {
[email protected]b1122982010-05-17 23:04:244227 return false;
4228 }
4229
4230 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4231
4232 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4233
4234 // Make a buffer with a single repeated vec4 value enough to
4235 // simulate the constant value that is supposed to be here.
4236 // This is required to emulate GLES2 on GL.
4237 GLsizei num_vertices = max_vertex_accessed + 1;
4238 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
[email protected]fc753442011-02-04 19:49:494239 if (size_needed > attrib_0_size_) {
4240 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4241 // TODO(gman): check for error here?
4242 attrib_0_buffer_matches_value_ = false;
4243 }
4244 if (attrib_0_used &&
4245 (!attrib_0_buffer_matches_value_ ||
4246 (info->value().v[0] != attrib_0_value_.v[0] ||
4247 info->value().v[1] != attrib_0_value_.v[1] ||
4248 info->value().v[2] != attrib_0_value_.v[2] ||
4249 info->value().v[3] != attrib_0_value_.v[3]))) {
4250 std::vector<Vec4> temp(num_vertices, info->value());
4251 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4252 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244253 attrib_0_value_ = info->value();
4254 attrib_0_size_ = size_needed;
4255 }
4256
4257 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4258
4259 return true;
[email protected]b1122982010-05-17 23:04:244260}
4261
4262void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4263 const VertexAttribManager::VertexAttribInfo* info =
4264 vertex_attrib_manager_.GetVertexAttribInfo(0);
4265 const void* ptr = reinterpret_cast<const void*>(info->offset());
4266 BufferManager::BufferInfo* buffer_info = info->buffer();
4267 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4268 glVertexAttribPointer(
4269 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4270 ptr);
4271 glBindBuffer(GL_ARRAY_BUFFER,
4272 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4273}
[email protected]07f54fcc2009-12-22 02:46:304274
[email protected]8fbedc02010-11-18 18:43:404275bool GLES2DecoderImpl::SimulateFixedAttribs(
4276 GLuint max_vertex_accessed, bool* simulated) {
4277 DCHECK(simulated);
4278 *simulated = false;
4279 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4280 return true;
4281
4282 if (!vertex_attrib_manager_.HaveFixedAttribs()) {
4283 return true;
4284 }
4285
4286 // NOTE: we could be smart and try to check if a buffer is used
4287 // twice in 2 different attribs, find the overlapping parts and therefore
4288 // duplicate the minimum amount of data but this whole code path is not meant
4289 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4290 // tests so we just add to the buffer attrib used.
4291
4292 // Compute the number of elements needed.
4293 int num_vertices = max_vertex_accessed + 1;
4294 int elements_needed = 0;
4295 const VertexAttribManager::VertexAttribInfoList& infos =
4296 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4297 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4298 infos.begin(); it != infos.end(); ++it) {
4299 const VertexAttribManager::VertexAttribInfo* info = *it;
4300 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4301 current_program_->GetAttribInfoByLocation(info->index());
4302 if (attrib_info &&
4303 info->CanAccess(max_vertex_accessed) &&
4304 info->type() == GL_FIXED) {
4305 int elements_used = 0;
4306 if (!SafeMultiply(
4307 static_cast<int>(num_vertices),
4308 info->size(), &elements_used) ||
4309 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4310 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4311 return false;
4312 }
4313 }
4314 }
4315
4316 const int kSizeOfFloat = sizeof(float); // NOLINT
4317 int size_needed = 0;
4318 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed)) {
4319 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4320 return false;
4321 }
4322
4323
4324 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
4325 if (size_needed > fixed_attrib_buffer_size_) {
4326 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4327 }
4328
4329 // Copy the elements and convert to float
4330 GLintptr offset = 0;
4331 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4332 infos.begin(); it != infos.end(); ++it) {
4333 const VertexAttribManager::VertexAttribInfo* info = *it;
4334 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4335 current_program_->GetAttribInfoByLocation(info->index());
4336 if (attrib_info &&
4337 info->CanAccess(max_vertex_accessed) &&
4338 info->type() == GL_FIXED) {
4339 int num_elements = info->size() * kSizeOfFloat;
4340 int size = num_elements * num_vertices;
4341 scoped_array<float> data(new float[size]);
4342 const int32* src = reinterpret_cast<const int32 *>(
4343 info->buffer()->GetRange(info->offset(), size));
4344 const int32* end = src + num_elements;
4345 float* dst = data.get();
4346 while (src != end) {
4347 *dst++ = static_cast<float>(*src++) / 65536.0f;
4348 }
4349 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
4350 glVertexAttribPointer(
4351 info->index(), info->size(), GL_FLOAT, false, 0,
4352 reinterpret_cast<GLvoid*>(offset));
4353 offset += size;
4354 }
4355 }
4356 *simulated = true;
4357 return true;
4358}
4359
4360void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
4361 // There's no need to call glVertexAttribPointer because we shadow all the
4362 // settings and passing GL_FIXED to it will not work.
4363 glBindBuffer(GL_ARRAY_BUFFER,
4364 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4365}
4366
[email protected]f7a64ee2010-02-01 22:24:144367error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:194368 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:504369 if (!bound_element_array_buffer_ ||
4370 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:294371 SetGLError(GL_INVALID_OPERATION,
4372 "glDrawElements: No element array buffer bound");
4373 return error::kNoError;
4374 }
4375
4376 GLenum mode = c.mode;
4377 GLsizei count = c.count;
4378 GLenum type = c.type;
4379 int32 offset = c.index_offset;
4380 if (count < 0) {
4381 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
4382 return error::kNoError;
4383 }
4384 if (offset < 0) {
4385 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
4386 return error::kNoError;
4387 }
[email protected]9438b012010-06-15 22:55:054388 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:294389 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
4390 return error::kNoError;
4391 }
[email protected]9438b012010-06-15 22:55:054392 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294393 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
4394 return error::kNoError;
4395 }
4396
[email protected]3a03a8f2011-03-19 00:51:274397 if (!CheckFramebufferComplete("glDrawElements")) {
4398 return error::kNoError;
4399 }
4400
[email protected]6c788fb72010-08-26 02:16:314401 if (count == 0) {
4402 return error::kNoError;
4403 }
4404
[email protected]8eee29c2010-04-29 03:38:294405 GLuint max_vertex_accessed;
4406 if (!bound_element_array_buffer_->GetMaxValueForRange(
4407 offset, count, type, &max_vertex_accessed)) {
4408 SetGLError(GL_INVALID_OPERATION,
4409 "glDrawElements: range out of bounds for buffer");
4410 return error::kNoError;
4411 }
4412
4413 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:244414 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]8fbedc02010-11-18 18:43:404415 bool simulated_fixed_attribs = false;
4416 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4417 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:464418 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:404419 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
4420 glDrawElements(mode, count, type, indices);
4421 if (textures_set) {
4422 RestoreStateForNonRenderableTextures();
4423 }
4424 if (simulated_fixed_attribs) {
4425 RestoreStateForSimulatedFixedAttribs();
4426 }
[email protected]ba3176a2009-12-16 18:19:464427 }
[email protected]b1122982010-05-17 23:04:244428 if (simulated_attrib_0) {
4429 RestoreStateForSimulatedAttrib0();
4430 }
[email protected]96449d2c2009-11-25 00:01:324431 }
[email protected]f7a64ee2010-02-01 22:24:144432 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324433}
4434
[email protected]269200b12010-11-18 22:53:064435GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:234436 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
4437 GLuint max_vertex_accessed = 0;
4438 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:294439 if (!info) {
[email protected]ae51d192010-04-27 00:48:034440 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294441 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064442 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:234443 } else {
4444 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:034445 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:064446 SetGLError(
4447 GL_INVALID_OPERATION,
4448 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:234449 }
4450 }
4451 return max_vertex_accessed;
4452}
4453
[email protected]96449d2c2009-11-25 00:01:324454// Calls glShaderSource for the various versions of the ShaderSource command.
4455// Assumes that data / data_size points to a piece of memory that is in range
4456// of whatever context it came from (shared memory, immediate memory, bucket
4457// memory.)
[email protected]45bf5152010-02-12 00:11:314458error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034459 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:584460 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4461 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:314462 if (!info) {
[email protected]45bf5152010-02-12 00:11:314463 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324464 }
[email protected]45bf5152010-02-12 00:11:314465 // Note: We don't actually call glShaderSource here. We wait until
4466 // the call to glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524467 info->Update(std::string(data, data + data_size).c_str());
[email protected]f7a64ee2010-02-01 22:24:144468 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324469}
4470
[email protected]f7a64ee2010-02-01 22:24:144471error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:194472 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:324473 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314474 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:324475 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:464476 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144477 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324478 }
[email protected]ae51d192010-04-27 00:48:034479 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:324480}
4481
[email protected]f7a64ee2010-02-01 22:24:144482error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:194483 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:324484 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314485 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:304486 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464487 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144488 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324489 }
[email protected]ae51d192010-04-27 00:48:034490 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:314491}
4492
[email protected]558847a2010-03-24 07:02:544493error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
4494 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:544495 Bucket* bucket = GetBucket(c.data_bucket_id);
4496 if (!bucket || bucket->size() == 0) {
4497 return error::kInvalidArguments;
4498 }
4499 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034500 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:544501 bucket->size() - 1);
4502}
4503
[email protected]ae51d192010-04-27 00:48:034504void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:224505 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:584506 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4507 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:314508 if (!info) {
[email protected]45bf5152010-02-12 00:11:314509 return;
4510 }
[email protected]de17df392010-04-23 21:09:414511 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
4512 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524513 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:344514 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:184515 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:344516 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:454517 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:234518
[email protected]a550584e2010-09-17 18:01:454519 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:344520 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:184521 return;
4522 }
[email protected]a550584e2010-09-17 18:01:454523 shader_src = translator->translated_shader();
[email protected]de17df392010-04-23 21:09:414524 }
[email protected]de17df392010-04-23 21:09:414525
[email protected]ae51d192010-04-27 00:48:034526 glShaderSource(info->service_id(), 1, &shader_src, NULL);
4527 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:414528 GLint status = GL_FALSE;
4529 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
4530 if (status) {
[email protected]f57bb282010-11-12 00:51:344531 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:414532 } else {
[email protected]d9977d42010-09-01 20:27:024533 // We cannot reach here if we are using the shader translator.
4534 // All invalid shaders must be rejected by the translator.
4535 // All translated shaders must compile.
4536 LOG_IF(ERROR, use_shader_translator_)
4537 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:334538 GLint max_len = 0;
4539 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
4540 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:414541 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:334542 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
4543 DCHECK(max_len == 0 || len < max_len);
4544 DCHECK(len ==0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:524545 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:414546 }
[email protected]45bf5152010-02-12 00:11:314547};
4548
[email protected]ddd968b82010-03-02 00:44:294549void GLES2DecoderImpl::DoGetShaderiv(
4550 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:584551 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4552 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:294553 if (!info) {
[email protected]ddd968b82010-03-02 00:44:294554 return;
4555 }
[email protected]8f1ccdac2010-05-19 21:01:484556 switch (pname) {
4557 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524558 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:484559 return;
4560 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:414561 *params = info->IsValid();
4562 return;
[email protected]8f1ccdac2010-05-19 21:01:484563 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524564 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:414565 return;
[email protected]8f1ccdac2010-05-19 21:01:484566 default:
4567 break;
[email protected]ddd968b82010-03-02 00:44:294568 }
[email protected]8f1ccdac2010-05-19 21:01:484569 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:294570}
4571
[email protected]ae51d192010-04-27 00:48:034572error::Error GLES2DecoderImpl::HandleGetShaderSource(
4573 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
4574 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:034575 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4576 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:584577 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4578 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:524579 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:294580 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:294581 return error::kNoError;
4582 }
[email protected]df6cf1ad2011-01-29 01:20:524583 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:034584 return error::kNoError;
4585}
4586
4587error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
4588 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
4589 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:584590 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4591 Bucket* bucket = CreateBucket(bucket_id);
4592 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4593 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524594 if (!info || !info->log_info()) {
4595 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034596 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:314597 }
[email protected]df6cf1ad2011-01-29 01:20:524598 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034599 return error::kNoError;
4600}
4601
4602error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
4603 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
4604 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:584605 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4606 Bucket* bucket = CreateBucket(bucket_id);
4607 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4608 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524609 if (!info || !info->log_info()) {
[email protected]6b8cf1a2010-05-06 16:13:584610 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034611 return error::kNoError;
4612 }
[email protected]df6cf1ad2011-01-29 01:20:524613 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034614 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324615}
4616
[email protected]1958e0e2010-04-22 05:17:154617bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364618 const BufferManager::BufferInfo* info = GetBufferInfo(client_id);
4619 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154620}
4621
4622bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364623 const FramebufferManager::FramebufferInfo* info =
4624 GetFramebufferInfo(client_id);
4625 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154626}
4627
4628bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364629 // IsProgram is true for programs as soon as they are created, until they are
4630 // deleted and no longer in use.
[email protected]ae51d192010-04-27 00:48:034631 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154632}
4633
4634bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364635 const RenderbufferManager::RenderbufferInfo* info =
4636 GetRenderbufferInfo(client_id);
4637 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154638}
4639
4640bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364641 // IsShader is true for shaders as soon as they are created, until they
4642 // are deleted and not attached to any programs.
[email protected]ae51d192010-04-27 00:48:034643 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154644}
4645
4646bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364647 const TextureManager::TextureInfo* info = GetTextureInfo(client_id);
4648 return info && info->IsValid();
[email protected]ae51d192010-04-27 00:48:034649}
4650
4651void GLES2DecoderImpl::DoAttachShader(
4652 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584653 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4654 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034655 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034656 return;
[email protected]1958e0e2010-04-22 05:17:154657 }
[email protected]6b8cf1a2010-05-06 16:13:584658 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4659 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034660 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034661 return;
4662 }
[email protected]ca488e12010-12-13 20:06:144663 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:314664 SetGLError(GL_INVALID_OPERATION,
4665 "glAttachShader: can not attach more than"
4666 " one shader of the same type.");
4667 return;
4668 }
[email protected]ae51d192010-04-27 00:48:034669 glAttachShader(program_info->service_id(), shader_info->service_id());
4670}
4671
4672void GLES2DecoderImpl::DoDetachShader(
4673 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584674 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4675 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034676 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034677 return;
4678 }
[email protected]6b8cf1a2010-05-06 16:13:584679 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4680 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034681 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034682 return;
4683 }
[email protected]9a0ccd42011-03-16 23:58:224684 if (!program_info->DetachShader(shader_manager(), shader_info)) {
4685 SetGLError(GL_INVALID_OPERATION,
4686 "glDetachShader: shader not attached to program");
4687 return;
4688 }
[email protected]ae51d192010-04-27 00:48:034689 glDetachShader(program_info->service_id(), shader_info->service_id());
4690}
4691
4692void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584693 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4694 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:034695 if (!info) {
[email protected]ae51d192010-04-27 00:48:034696 return;
4697 }
[email protected]d685a682011-04-29 16:19:574698 info->Validate();
[email protected]1958e0e2010-04-22 05:17:154699}
4700
[email protected]b1122982010-05-17 23:04:244701void GLES2DecoderImpl::DoGetVertexAttribfv(
4702 GLuint index, GLenum pname, GLfloat* params) {
4703 VertexAttribManager::VertexAttribInfo* info =
4704 vertex_attrib_manager_.GetVertexAttribInfo(index);
4705 if (!info) {
4706 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
4707 return;
4708 }
4709 switch (pname) {
4710 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4711 BufferManager::BufferInfo* buffer = info->buffer();
4712 if (buffer && !buffer->IsDeleted()) {
4713 GLuint client_id;
4714 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4715 *params = static_cast<GLfloat>(client_id);
4716 }
4717 break;
4718 }
4719 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4720 *params = static_cast<GLfloat>(info->enabled());
4721 break;
4722 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4723 *params = static_cast<GLfloat>(info->size());
4724 break;
4725 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4726 *params = static_cast<GLfloat>(info->gl_stride());
4727 break;
4728 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4729 *params = static_cast<GLfloat>(info->type());
4730 break;
4731 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4732 *params = static_cast<GLfloat>(info->normalized());
4733 break;
4734 case GL_CURRENT_VERTEX_ATTRIB:
4735 params[0] = info->value().v[0];
4736 params[1] = info->value().v[1];
4737 params[2] = info->value().v[2];
4738 params[3] = info->value().v[3];
4739 break;
4740 default:
4741 NOTREACHED();
4742 break;
4743 }
4744}
4745
4746void GLES2DecoderImpl::DoGetVertexAttribiv(
4747 GLuint index, GLenum pname, GLint* params) {
4748 VertexAttribManager::VertexAttribInfo* info =
4749 vertex_attrib_manager_.GetVertexAttribInfo(index);
4750 if (!info) {
4751 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
4752 return;
4753 }
4754 switch (pname) {
4755 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4756 BufferManager::BufferInfo* buffer = info->buffer();
4757 if (buffer && !buffer->IsDeleted()) {
4758 GLuint client_id;
4759 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4760 *params = client_id;
4761 }
4762 break;
4763 }
4764 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4765 *params = info->enabled();
4766 break;
4767 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4768 *params = info->size();
4769 break;
4770 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4771 *params = info->gl_stride();
4772 break;
4773 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4774 *params = info->type();
4775 break;
4776 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4777 *params = static_cast<GLint>(info->normalized());
4778 break;
4779 case GL_CURRENT_VERTEX_ATTRIB:
4780 params[0] = static_cast<GLint>(info->value().v[0]);
4781 params[1] = static_cast<GLint>(info->value().v[1]);
4782 params[2] = static_cast<GLint>(info->value().v[2]);
4783 params[3] = static_cast<GLint>(info->value().v[3]);
4784 break;
4785 default:
4786 NOTREACHED();
4787 break;
4788 }
4789}
4790
4791void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
4792 VertexAttribManager::VertexAttribInfo* info =
4793 vertex_attrib_manager_.GetVertexAttribInfo(index);
4794 if (!info) {
4795 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
4796 return;
4797 }
4798 VertexAttribManager::VertexAttribInfo::Vec4 value;
4799 value.v[0] = v0;
4800 value.v[1] = 0.0f;
4801 value.v[2] = 0.0f;
4802 value.v[3] = 1.0f;
4803 info->set_value(value);
4804 glVertexAttrib1f(index, v0);
4805}
4806
4807void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
4808 VertexAttribManager::VertexAttribInfo* info =
4809 vertex_attrib_manager_.GetVertexAttribInfo(index);
4810 if (!info) {
4811 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
4812 return;
4813 }
4814 VertexAttribManager::VertexAttribInfo::Vec4 value;
4815 value.v[0] = v0;
4816 value.v[1] = v1;
4817 value.v[2] = 0.0f;
4818 value.v[3] = 1.0f;
4819 info->set_value(value);
4820 glVertexAttrib2f(index, v0, v1);
4821}
4822
4823void GLES2DecoderImpl::DoVertexAttrib3f(
4824 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
4825 VertexAttribManager::VertexAttribInfo* info =
4826 vertex_attrib_manager_.GetVertexAttribInfo(index);
4827 if (!info) {
4828 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
4829 return;
4830 }
4831 VertexAttribManager::VertexAttribInfo::Vec4 value;
4832 value.v[0] = v0;
4833 value.v[1] = v1;
4834 value.v[2] = v2;
4835 value.v[3] = 1.0f;
4836 info->set_value(value);
4837 glVertexAttrib3f(index, v0, v1, v2);
4838}
4839
4840void GLES2DecoderImpl::DoVertexAttrib4f(
4841 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
4842 VertexAttribManager::VertexAttribInfo* info =
4843 vertex_attrib_manager_.GetVertexAttribInfo(index);
4844 if (!info) {
4845 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
4846 return;
4847 }
4848 VertexAttribManager::VertexAttribInfo::Vec4 value;
4849 value.v[0] = v0;
4850 value.v[1] = v1;
4851 value.v[2] = v2;
4852 value.v[3] = v3;
4853 info->set_value(value);
4854 glVertexAttrib4f(index, v0, v1, v2, v3);
4855}
4856
4857void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
4858 VertexAttribManager::VertexAttribInfo* info =
4859 vertex_attrib_manager_.GetVertexAttribInfo(index);
4860 if (!info) {
4861 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
4862 return;
4863 }
4864 VertexAttribManager::VertexAttribInfo::Vec4 value;
4865 value.v[0] = v[0];
4866 value.v[1] = 0.0f;
4867 value.v[2] = 0.0f;
4868 value.v[3] = 1.0f;
4869 info->set_value(value);
4870 glVertexAttrib1fv(index, v);
4871}
4872
4873void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
4874 VertexAttribManager::VertexAttribInfo* info =
4875 vertex_attrib_manager_.GetVertexAttribInfo(index);
4876 if (!info) {
4877 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
4878 return;
4879 }
4880 VertexAttribManager::VertexAttribInfo::Vec4 value;
4881 value.v[0] = v[0];
4882 value.v[1] = v[1];
4883 value.v[2] = 0.0f;
4884 value.v[3] = 1.0f;
4885 info->set_value(value);
4886 glVertexAttrib2fv(index, v);
4887}
4888
4889void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
4890 VertexAttribManager::VertexAttribInfo* info =
4891 vertex_attrib_manager_.GetVertexAttribInfo(index);
4892 if (!info) {
4893 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
4894 return;
4895 }
4896 VertexAttribManager::VertexAttribInfo::Vec4 value;
4897 value.v[0] = v[0];
4898 value.v[1] = v[1];
4899 value.v[2] = v[2];
4900 value.v[3] = 1.0f;
4901 info->set_value(value);
4902 glVertexAttrib3fv(index, v);
4903}
4904
4905void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
4906 VertexAttribManager::VertexAttribInfo* info =
4907 vertex_attrib_manager_.GetVertexAttribInfo(index);
4908 if (!info) {
4909 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
4910 return;
4911 }
4912 VertexAttribManager::VertexAttribInfo::Vec4 value;
4913 value.v[0] = v[0];
4914 value.v[1] = v[1];
4915 value.v[2] = v[2];
4916 value.v[3] = v[3];
4917 info->set_value(value);
4918 glVertexAttrib4fv(index, v);
4919}
4920
[email protected]f7a64ee2010-02-01 22:24:144921error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:194922 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:294923 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
4924 SetGLError(GL_INVALID_VALUE,
4925 "glVertexAttribPointer: no array buffer bound");
4926 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324927 }
[email protected]8eee29c2010-04-29 03:38:294928
4929 GLuint indx = c.indx;
4930 GLint size = c.size;
4931 GLenum type = c.type;
4932 GLboolean normalized = c.normalized;
4933 GLsizei stride = c.stride;
4934 GLsizei offset = c.offset;
4935 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:054936 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294937 SetGLError(GL_INVALID_ENUM,
4938 "glVertexAttribPointer: type GL_INVALID_ENUM");
4939 return error::kNoError;
4940 }
[email protected]9438b012010-06-15 22:55:054941 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:314942 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:294943 "glVertexAttribPointer: size GL_INVALID_VALUE");
4944 return error::kNoError;
4945 }
4946 if (indx >= group_->max_vertex_attribs()) {
4947 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
4948 return error::kNoError;
4949 }
4950 if (stride < 0) {
4951 SetGLError(GL_INVALID_VALUE,
4952 "glVertexAttribPointer: stride < 0");
4953 return error::kNoError;
4954 }
4955 if (stride > 255) {
4956 SetGLError(GL_INVALID_VALUE,
4957 "glVertexAttribPointer: stride > 255");
4958 return error::kNoError;
4959 }
4960 if (offset < 0) {
4961 SetGLError(GL_INVALID_VALUE,
4962 "glVertexAttribPointer: offset < 0");
4963 return error::kNoError;
4964 }
4965 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:314966 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:294967 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:314968 SetGLError(GL_INVALID_OPERATION,
4969 "glVertexAttribPointer: offset not valid for type");
4970 return error::kNoError;
4971 }
4972 if (stride % component_size > 0) {
4973 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:294974 "glVertexAttribPointer: stride not valid for type");
4975 return error::kNoError;
4976 }
[email protected]8fbedc02010-11-18 18:43:404977 vertex_attrib_manager_.SetAttribInfo(
4978 indx,
[email protected]8eee29c2010-04-29 03:38:294979 bound_array_buffer_,
4980 size,
4981 type,
[email protected]b1122982010-05-17 23:04:244982 normalized,
4983 stride,
4984 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:294985 offset);
[email protected]8fbedc02010-11-18 18:43:404986 if (type != GL_FIXED) {
4987 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
4988 }
[email protected]f7a64ee2010-02-01 22:24:144989 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324990}
4991
[email protected]f7a64ee2010-02-01 22:24:144992error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:194993 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:314994 GLint x = c.x;
4995 GLint y = c.y;
4996 GLsizei width = c.width;
4997 GLsizei height = c.height;
4998 GLenum format = c.format;
4999 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:565000 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:295001 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:565002 return error::kNoError;
5003 }
[email protected]a51788e2010-02-24 21:54:255004 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:185005 uint32 pixels_size;
5006 if (!GLES2Util::ComputeImageDataSize(
5007 width, height, format, type, pack_alignment_, &pixels_size)) {
5008 return error::kOutOfBounds;
5009 }
[email protected]612d2f82009-12-08 20:49:315010 void* pixels = GetSharedMemoryAs<void*>(
5011 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:255012 Result* result = GetSharedMemoryAs<Result*>(
5013 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5014 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:145015 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465016 }
[email protected]a51788e2010-02-24 21:54:255017
[email protected]9438b012010-06-15 22:55:055018 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295019 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
5020 return error::kNoError;
5021 }
[email protected]9438b012010-06-15 22:55:055022 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295023 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125024 return error::kNoError;
5025 }
[email protected]57f223832010-03-19 01:57:565026 if (width == 0 || height == 0) {
5027 return error::kNoError;
5028 }
5029
5030 CopyRealGLErrorsToWrapper();
5031
[email protected]c0701082011-04-20 00:34:525032 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]34ff8b0c2010-10-01 20:06:025033
[email protected]57f223832010-03-19 01:57:565034 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:305035 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:565036
5037 GLint max_x;
5038 GLint max_y;
5039 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:295040 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:145041 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:315042 }
[email protected]57f223832010-03-19 01:57:565043
[email protected]d37231fa2010-04-09 21:16:025044 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:565045 // The user requested an out of range area. Get the results 1 line
5046 // at a time.
5047 uint32 temp_size;
5048 if (!GLES2Util::ComputeImageDataSize(
5049 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295050 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565051 return error::kNoError;
5052 }
5053 GLsizei unpadded_row_size = temp_size;
5054 if (!GLES2Util::ComputeImageDataSize(
5055 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295056 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565057 return error::kNoError;
5058 }
5059 GLsizei padded_row_size = temp_size - unpadded_row_size;
5060 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:295061 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565062 return error::kNoError;
5063 }
5064
5065 GLint dest_x_offset = std::max(-x, 0);
5066 uint32 dest_row_offset;
5067 if (!GLES2Util::ComputeImageDataSize(
5068 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:295069 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565070 return error::kNoError;
5071 }
5072
5073 // Copy each row into the larger dest rect.
5074 int8* dst = static_cast<int8*>(pixels);
5075 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:025076 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:565077 GLint read_width = read_end_x - read_x;
5078 for (GLint yy = 0; yy < height; ++yy) {
5079 GLint ry = y + yy;
5080
5081 // Clear the row.
5082 memset(dst, 0, unpadded_row_size);
5083
5084 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025085 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565086 glReadPixels(
5087 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5088 }
5089 dst += padded_row_size;
5090 }
5091 } else {
5092 glReadPixels(x, y, width, height, format, type, pixels);
5093 }
[email protected]1002c2d2011-06-28 22:39:045094 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:255095 if (error == GL_NO_ERROR) {
5096 *result = true;
[email protected]4848b9f82011-03-10 18:37:565097
5098 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5099 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5100 if ((channels_exist & 0x0008) == 0) {
5101 // Set the alpha to 255 because some drivers are buggy in this regard.
5102 uint32 temp_size;
5103 if (!GLES2Util::ComputeImageDataSize(
5104 width, 1, format, type, pack_alignment_, &temp_size)) {
5105 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5106 return error::kNoError;
5107 }
5108 GLsizei unpadded_row_size = temp_size;
5109 if (!GLES2Util::ComputeImageDataSize(
5110 width, 2, format, type, pack_alignment_, &temp_size)) {
5111 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5112 return error::kNoError;
5113 }
5114 GLsizei padded_row_size = temp_size - unpadded_row_size;
5115 if (padded_row_size < 0 || unpadded_row_size < 0) {
5116 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5117 return error::kNoError;
5118 }
5119 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5120 // of this implementation.
5121 if (type != GL_UNSIGNED_BYTE) {
5122 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5123 return error::kNoError;
5124 }
5125 switch (format) {
5126 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:465127 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:565128 case GL_ALPHA: {
5129 int offset = (format == GL_ALPHA) ? 0 : 3;
5130 int step = (format == GL_ALPHA) ? 1 : 4;
5131 uint8* dst = static_cast<uint8*>(pixels) + offset;
5132 for (GLint yy = 0; yy < height; ++yy) {
5133 uint8* end = dst + unpadded_row_size;
5134 for (uint8* d = dst; d < end; d += step) {
5135 *d = 255;
5136 }
5137 dst += padded_row_size;
5138 }
5139 break;
5140 }
5141 default:
5142 break;
5143 }
5144 }
[email protected]a51788e2010-02-24 21:54:255145 }
[email protected]4848b9f82011-03-10 18:37:565146
[email protected]f7a64ee2010-02-01 22:24:145147 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325148}
5149
[email protected]f7a64ee2010-02-01 22:24:145150error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195151 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5152 GLenum pname = c.pname;
5153 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055154 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295155 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125156 return error::kNoError;
5157 }
[email protected]9438b012010-06-15 22:55:055158 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:295159 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:145160 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195161 }
5162 glPixelStorei(pname, param);
5163 switch (pname) {
5164 case GL_PACK_ALIGNMENT:
5165 pack_alignment_ = param;
5166 break;
5167 case GL_UNPACK_ALIGNMENT:
5168 unpack_alignment_ = param;
5169 break;
5170 default:
5171 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:375172 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:195173 break;
5174 }
[email protected]f7a64ee2010-02-01 22:24:145175 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195176}
5177
[email protected]558847a2010-03-24 07:02:545178error::Error GLES2DecoderImpl::GetAttribLocationHelper(
5179 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5180 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585181 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5182 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:035183 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145184 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195185 }
[email protected]ae51d192010-04-27 00:48:035186 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295187 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255188 return error::kNoError;
5189 }
[email protected]b9849abf2009-11-25 19:13:195190 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545191 location_shm_id, location_shm_offset, sizeof(GLint));
5192 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145193 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195194 }
[email protected]558847a2010-03-24 07:02:545195 // Require the client to init this incase the context is lost and we are no
5196 // longer executing commands.
5197 if (*location != -1) {
5198 return error::kGenericError;
5199 }
[email protected]0bfd9882010-02-05 23:02:255200 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145201 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195202}
5203
[email protected]558847a2010-03-24 07:02:545204error::Error GLES2DecoderImpl::HandleGetAttribLocation(
5205 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
5206 uint32 name_size = c.data_size;
5207 const char* name = GetSharedMemoryAs<const char*>(
5208 c.name_shm_id, c.name_shm_offset, name_size);
5209 if (!name) {
5210 return error::kOutOfBounds;
5211 }
5212 String name_str(name, name_size);
5213 return GetAttribLocationHelper(
5214 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5215}
5216
[email protected]f7a64ee2010-02-01 22:24:145217error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195218 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:545219 uint32 name_size = c.data_size;
5220 const char* name = GetImmediateDataAs<const char*>(
5221 c, name_size, immediate_data_size);
5222 if (!name) {
5223 return error::kOutOfBounds;
5224 }
5225 String name_str(name, name_size);
5226 return GetAttribLocationHelper(
5227 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5228}
5229
5230error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
5231 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
5232 Bucket* bucket = GetBucket(c.name_bucket_id);
5233 if (!bucket) {
5234 return error::kInvalidArguments;
5235 }
5236 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185237 if (!bucket->GetAsString(&name_str)) {
5238 return error::kInvalidArguments;
5239 }
[email protected]558847a2010-03-24 07:02:545240 return GetAttribLocationHelper(
5241 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5242}
5243
5244error::Error GLES2DecoderImpl::GetUniformLocationHelper(
5245 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5246 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585247 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5248 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:035249 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145250 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195251 }
[email protected]ae51d192010-04-27 00:48:035252 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295253 SetGLError(GL_INVALID_OPERATION,
5254 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255255 return error::kNoError;
5256 }
[email protected]b9849abf2009-11-25 19:13:195257 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545258 location_shm_id, location_shm_offset, sizeof(GLint));
5259 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145260 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195261 }
[email protected]558847a2010-03-24 07:02:545262 // Require the client to init this incase the context is lost an we are no
5263 // longer executing commands.
5264 if (*location != -1) {
5265 return error::kGenericError;
5266 }
5267 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145268 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195269}
5270
[email protected]f7a64ee2010-02-01 22:24:145271error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:195272 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:195273 uint32 name_size = c.data_size;
5274 const char* name = GetSharedMemoryAs<const char*>(
5275 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:545276 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145277 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195278 }
5279 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545280 return GetUniformLocationHelper(
5281 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195282}
5283
[email protected]f7a64ee2010-02-01 22:24:145284error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195285 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:195286 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:305287 const char* name = GetImmediateDataAs<const char*>(
5288 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:545289 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145290 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195291 }
5292 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545293 return GetUniformLocationHelper(
5294 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5295}
5296
5297error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
5298 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
5299 Bucket* bucket = GetBucket(c.name_bucket_id);
5300 if (!bucket) {
5301 return error::kInvalidArguments;
5302 }
5303 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185304 if (!bucket->GetAsString(&name_str)) {
5305 return error::kInvalidArguments;
5306 }
[email protected]558847a2010-03-24 07:02:545307 return GetUniformLocationHelper(
5308 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195309}
5310
[email protected]ddd968b82010-03-02 00:44:295311error::Error GLES2DecoderImpl::HandleGetString(
5312 uint32 immediate_data_size, const gles2::GetString& c) {
5313 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:055314 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:295315 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:295316 return error::kNoError;
5317 }
[email protected]1958e0e2010-04-22 05:17:155318 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
5319 const char* str = NULL;
5320 switch (name) {
5321 case GL_VERSION:
5322 str = "OpenGL ES 2.0 Chromium";
5323 break;
5324 case GL_SHADING_LANGUAGE_VERSION:
5325 str = "OpenGL ES GLSL ES 1.0 Chromium";
5326 break;
5327 case GL_EXTENSIONS:
[email protected]915a59a12010-09-30 21:29:115328 str = feature_info_->extensions().c_str();
[email protected]1958e0e2010-04-22 05:17:155329 break;
5330 default:
5331 str = gl_str;
5332 break;
5333 }
[email protected]ddd968b82010-03-02 00:44:295334 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:155335 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:295336 return error::kNoError;
5337}
5338
[email protected]0c86dbf2010-03-05 08:14:115339void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:155340 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:055341 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295342 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
5343 return;
5344 }
[email protected]9438b012010-06-15 22:55:055345 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:295346 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:115347 return;
[email protected]3b6ec202010-03-05 05:16:235348 }
5349 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:295350 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:285351 return;
[email protected]3b6ec202010-03-05 05:16:235352 }
5353 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
5354 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295355 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285356 return;
[email protected]3b6ec202010-03-05 05:16:235357 }
5358 // Clear the buffer to 0 if no initial data was passed in.
5359 scoped_array<int8> zero;
5360 if (!data) {
5361 zero.reset(new int8[size]);
5362 memset(zero.get(), 0, size);
5363 data = zero.get();
5364 }
[email protected]473c01ccb2011-06-07 01:33:305365
5366 if (!bufferdata_faster_than_buffersubdata_ &&
5367 size == info->size() && usage == info->usage()) {
5368 glBufferSubData(target, 0, size, data);
5369 info->SetRange(0, size, data);
5370 return;
5371 }
5372
[email protected]3b6ec202010-03-05 05:16:235373 CopyRealGLErrorsToWrapper();
5374 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:045375 GLenum error = PeekGLError();
5376 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:305377 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:115378 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:235379 }
[email protected]0c86dbf2010-03-05 08:14:115380}
5381
5382error::Error GLES2DecoderImpl::HandleBufferData(
5383 uint32 immediate_data_size, const gles2::BufferData& c) {
5384 GLenum target = static_cast<GLenum>(c.target);
5385 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
5386 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5387 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5388 GLenum usage = static_cast<GLenum>(c.usage);
5389 const void* data = NULL;
5390 if (data_shm_id != 0 || data_shm_offset != 0) {
5391 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
5392 if (!data) {
5393 return error::kOutOfBounds;
5394 }
5395 }
5396 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:145397 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195398}
5399
[email protected]f7a64ee2010-02-01 22:24:145400error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:195401 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
5402 GLenum target = static_cast<GLenum>(c.target);
5403 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:305404 const void* data = GetImmediateDataAs<const void*>(
5405 c, size, immediate_data_size);
5406 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145407 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:305408 }
[email protected]b9849abf2009-11-25 19:13:195409 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:115410 DoBufferData(target, size, data, usage);
5411 return error::kNoError;
5412}
5413
5414void GLES2DecoderImpl::DoBufferSubData(
5415 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:505416 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475417 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295418 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285419 return;
[email protected]a93bb842010-02-16 23:03:475420 }
[email protected]0c86dbf2010-03-05 08:14:115421 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:295422 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:305423 return;
[email protected]07f54fcc2009-12-22 02:46:305424 }
[email protected]473c01ccb2011-06-07 01:33:305425 if (bufferdata_faster_than_buffersubdata_ &&
5426 offset == 0 && size == info->size()) {
5427 glBufferData(target, size, data, info->usage());
5428 return;
5429 }
5430 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:195431}
5432
[email protected]a93bb842010-02-16 23:03:475433error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
5434 GLenum target,
5435 GLint level,
5436 GLenum internal_format,
5437 GLsizei width,
5438 GLsizei height,
5439 GLint border,
5440 GLsizei image_size,
5441 const void* data) {
[email protected]a93bb842010-02-16 23:03:475442 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:055443 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295444 SetGLError(GL_INVALID_ENUM,
5445 "glCompressedTexImage2D: target GL_INVALID_ENUM");
5446 return error::kNoError;
5447 }
[email protected]9438b012010-06-15 22:55:055448 if (!validators_->compressed_texture_format.IsValid(
5449 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295450 SetGLError(GL_INVALID_ENUM,
5451 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:475452 return error::kNoError;
5453 }
[email protected]915a59a12010-09-30 21:29:115454 if (!texture_manager()->ValidForTarget(
5455 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475456 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295457 SetGLError(GL_INVALID_VALUE,
5458 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475459 return error::kNoError;
5460 }
[email protected]3916c97e2010-02-25 03:20:505461 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475462 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295463 SetGLError(GL_INVALID_VALUE,
5464 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:475465 return error::kNoError;
5466 }
5467 scoped_array<int8> zero;
5468 if (!data) {
5469 zero.reset(new int8[image_size]);
5470 memset(zero.get(), 0, image_size);
5471 data = zero.get();
5472 }
[email protected]cadde4a2010-07-31 17:10:435473 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475474 glCompressedTexImage2D(
5475 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:045476 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435477 if (error == GL_NO_ERROR) {
5478 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115479 feature_info_,
[email protected]cadde4a2010-07-31 17:10:435480 info, target, level, internal_format, width, height, 1, border, 0, 0);
5481 }
[email protected]a93bb842010-02-16 23:03:475482 return error::kNoError;
5483}
5484
[email protected]f7a64ee2010-02-01 22:24:145485error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195486 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
5487 GLenum target = static_cast<GLenum>(c.target);
5488 GLint level = static_cast<GLint>(c.level);
5489 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5490 GLsizei width = static_cast<GLsizei>(c.width);
5491 GLsizei height = static_cast<GLsizei>(c.height);
5492 GLint border = static_cast<GLint>(c.border);
5493 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
5494 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5495 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5496 const void* data = NULL;
5497 if (data_shm_id != 0 || data_shm_offset != 0) {
5498 data = GetSharedMemoryAs<const void*>(
5499 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:465500 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145501 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195502 }
5503 }
[email protected]a93bb842010-02-16 23:03:475504 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195505 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:195506}
5507
[email protected]f7a64ee2010-02-01 22:24:145508error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195509 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
5510 GLenum target = static_cast<GLenum>(c.target);
5511 GLint level = static_cast<GLint>(c.level);
5512 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5513 GLsizei width = static_cast<GLsizei>(c.width);
5514 GLsizei height = static_cast<GLsizei>(c.height);
5515 GLint border = static_cast<GLint>(c.border);
5516 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:305517 const void* data = GetImmediateDataAs<const void*>(
5518 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465519 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145520 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465521 }
[email protected]a93bb842010-02-16 23:03:475522 return DoCompressedTexImage2D(
5523 target, level, internal_format, width, height, border, image_size, data);
5524}
5525
[email protected]b6140d02010-05-17 14:47:165526error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
5527 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
5528 GLenum target = static_cast<GLenum>(c.target);
5529 GLint level = static_cast<GLint>(c.level);
5530 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5531 GLsizei width = static_cast<GLsizei>(c.width);
5532 GLsizei height = static_cast<GLsizei>(c.height);
5533 GLint border = static_cast<GLint>(c.border);
5534 Bucket* bucket = GetBucket(c.bucket_id);
5535 return DoCompressedTexImage2D(
5536 target, level, internal_format, width, height, border,
5537 bucket->size(), bucket->GetData(0, bucket->size()));
5538}
5539
5540error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
5541 uint32 immediate_data_size,
5542 const gles2::CompressedTexSubImage2DBucket& c) {
5543 GLenum target = static_cast<GLenum>(c.target);
5544 GLint level = static_cast<GLint>(c.level);
5545 GLint xoffset = static_cast<GLint>(c.xoffset);
5546 GLint yoffset = static_cast<GLint>(c.yoffset);
5547 GLsizei width = static_cast<GLsizei>(c.width);
5548 GLsizei height = static_cast<GLsizei>(c.height);
5549 GLenum format = static_cast<GLenum>(c.format);
5550 Bucket* bucket = GetBucket(c.bucket_id);
5551 uint32 data_size = bucket->size();
5552 GLsizei imageSize = data_size;
5553 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:055554 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:165555 SetGLError(
5556 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
5557 return error::kNoError;
5558 }
[email protected]9438b012010-06-15 22:55:055559 if (!validators_->compressed_texture_format.IsValid(format)) {
5560 SetGLError(GL_INVALID_ENUM,
5561 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
5562 return error::kNoError;
5563 }
[email protected]b6140d02010-05-17 14:47:165564 if (width < 0) {
5565 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
5566 return error::kNoError;
5567 }
5568 if (height < 0) {
5569 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
5570 return error::kNoError;
5571 }
5572 if (imageSize < 0) {
5573 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
5574 return error::kNoError;
5575 }
[email protected]cadde4a2010-07-31 17:10:435576 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:165577 target, level, xoffset, yoffset, width, height, format, imageSize, data);
5578 return error::kNoError;
5579}
5580
[email protected]a93bb842010-02-16 23:03:475581error::Error GLES2DecoderImpl::DoTexImage2D(
5582 GLenum target,
5583 GLint level,
5584 GLenum internal_format,
5585 GLsizei width,
5586 GLsizei height,
5587 GLint border,
5588 GLenum format,
5589 GLenum type,
5590 const void* pixels,
5591 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:055592 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295593 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
5594 return error::kNoError;
5595 }
[email protected]9438b012010-06-15 22:55:055596 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295597 SetGLError(GL_INVALID_ENUM,
5598 "glTexImage2D: internal_format GL_INVALID_ENUM");
5599 return error::kNoError;
5600 }
[email protected]9438b012010-06-15 22:55:055601 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295602 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
5603 return error::kNoError;
5604 }
[email protected]9438b012010-06-15 22:55:055605 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295606 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145607 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195608 }
[email protected]7b92c412010-07-20 17:48:255609 if (format != internal_format) {
5610 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
5611 return error::kNoError;
5612 }
[email protected]915a59a12010-09-30 21:29:115613 if (!texture_manager()->ValidForTarget(
5614 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475615 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295616 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475617 return error::kNoError;
5618 }
[email protected]3916c97e2010-02-25 03:20:505619 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475620 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295621 SetGLError(GL_INVALID_OPERATION,
5622 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:475623 return error::kNoError;
5624 }
5625 scoped_array<int8> zero;
5626 if (!pixels) {
5627 zero.reset(new int8[pixels_size]);
5628 memset(zero.get(), 0, pixels_size);
5629 pixels = zero.get();
5630 }
[email protected]876f6fee2010-08-02 23:10:325631
[email protected]297ca1c2011-06-20 23:08:465632 if (info->IsAttachedToFramebuffer()) {
5633 state_dirty_ = true;
5634 }
5635
[email protected]473c01ccb2011-06-07 01:33:305636 if (!teximage2d_faster_than_texsubimage2d_) {
5637 GLsizei tex_width = 0;
5638 GLsizei tex_height = 0;
5639 GLenum tex_type = 0;
5640 GLenum tex_format = 0;
5641 if (info->GetLevelSize(target, level, &tex_width, &tex_height) &&
5642 info->GetLevelType(target, level, &tex_type, &tex_format) &&
5643 width == tex_width && height == tex_height &&
5644 type == tex_type && format == tex_format) {
5645 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
5646 tex_image_2d_failed_ = false;
5647 return error::kNoError;
[email protected]7b92c412010-07-20 17:48:255648 }
[email protected]7488d962010-07-16 02:41:585649 }
[email protected]876f6fee2010-08-02 23:10:325650
[email protected]cadde4a2010-07-31 17:10:435651 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:305652 WrappedTexImage2D(
5653 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475654 pixels);
[email protected]1002c2d2011-06-28 22:39:045655 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435656 if (error == GL_NO_ERROR) {
[email protected]915a59a12010-09-30 21:29:115657 texture_manager()->SetLevelInfo(feature_info_, info,
[email protected]cadde4a2010-07-31 17:10:435658 target, level, internal_format, width, height, 1, border, format, type);
[email protected]b493ee622011-04-13 23:52:005659 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:435660 }
[email protected]f7a64ee2010-02-01 22:24:145661 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195662}
5663
[email protected]f7a64ee2010-02-01 22:24:145664error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195665 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:585666 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:005667 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:195668 GLenum target = static_cast<GLenum>(c.target);
5669 GLint level = static_cast<GLint>(c.level);
5670 GLint internal_format = static_cast<GLint>(c.internalformat);
5671 GLsizei width = static_cast<GLsizei>(c.width);
5672 GLsizei height = static_cast<GLsizei>(c.height);
5673 GLint border = static_cast<GLint>(c.border);
5674 GLenum format = static_cast<GLenum>(c.format);
5675 GLenum type = static_cast<GLenum>(c.type);
5676 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
5677 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:185678 uint32 pixels_size;
5679 if (!GLES2Util::ComputeImageDataSize(
5680 width, height, format, type, unpack_alignment_, &pixels_size)) {
5681 return error::kOutOfBounds;
5682 }
[email protected]b9849abf2009-11-25 19:13:195683 const void* pixels = NULL;
5684 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
5685 pixels = GetSharedMemoryAs<const void*>(
5686 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:465687 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145688 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195689 }
5690 }
[email protected]a93bb842010-02-16 23:03:475691 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195692 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475693 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:195694}
5695
[email protected]f7a64ee2010-02-01 22:24:145696error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195697 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
5698 GLenum target = static_cast<GLenum>(c.target);
5699 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:465700 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:195701 GLsizei width = static_cast<GLsizei>(c.width);
5702 GLsizei height = static_cast<GLsizei>(c.height);
5703 GLint border = static_cast<GLint>(c.border);
5704 GLenum format = static_cast<GLenum>(c.format);
5705 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:185706 uint32 size;
5707 if (!GLES2Util::ComputeImageDataSize(
5708 width, height, format, type, unpack_alignment_, &size)) {
5709 return error::kOutOfBounds;
5710 }
[email protected]07f54fcc2009-12-22 02:46:305711 const void* pixels = GetImmediateDataAs<const void*>(
5712 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465713 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145714 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465715 }
[email protected]a93bb842010-02-16 23:03:475716 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:465717 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475718 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:145719 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325720}
5721
[email protected]cadde4a2010-07-31 17:10:435722void GLES2DecoderImpl::DoCompressedTexSubImage2D(
5723 GLenum target,
5724 GLint level,
5725 GLint xoffset,
5726 GLint yoffset,
5727 GLsizei width,
5728 GLsizei height,
5729 GLenum format,
5730 GLsizei image_size,
5731 const void * data) {
5732 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5733 if (!info) {
5734 SetGLError(GL_INVALID_OPERATION,
5735 "glCompressedTexSubImage2D: unknown texture for target");
5736 return;
5737 }
5738 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:525739 GLenum internal_format = 0;
5740 if (!info->GetLevelType(target, level, &type, &internal_format)) {
5741 SetGLError(
5742 GL_INVALID_OPERATION,
5743 "glCompressdTexSubImage2D: level does not exist.");
5744 return;
5745 }
5746 if (internal_format != format) {
5747 SetGLError(
5748 GL_INVALID_OPERATION,
5749 "glCompressdTexSubImage2D: format does not match internal format.");
5750 return;
5751 }
5752 if (!info->ValidForTexture(
5753 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:435754 SetGLError(GL_INVALID_VALUE,
5755 "glCompressdTexSubImage2D: bad dimensions.");
5756 return;
5757 }
5758 glCompressedTexSubImage2D(
5759 target, level, xoffset, yoffset, width, height, format, image_size, data);
5760}
5761
[email protected]6e288612010-12-21 20:45:035762static void Clip(
5763 GLint start, GLint range, GLint sourceRange,
5764 GLint* out_start, GLint* out_range) {
5765 DCHECK(out_start);
5766 DCHECK(out_range);
5767 if (start < 0) {
5768 range += start;
5769 start = 0;
5770 }
5771 GLint end = start + range;
5772 if (end > sourceRange) {
5773 range -= end - sourceRange;
5774 }
5775 *out_start = start;
5776 *out_range = range;
5777}
5778
5779
[email protected]cadde4a2010-07-31 17:10:435780void GLES2DecoderImpl::DoCopyTexImage2D(
5781 GLenum target,
5782 GLint level,
5783 GLenum internal_format,
5784 GLint x,
5785 GLint y,
5786 GLsizei width,
5787 GLsizei height,
5788 GLint border) {
5789 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5790 if (!info) {
5791 SetGLError(GL_INVALID_OPERATION,
5792 "glCopyTexImage2D: unknown texture for target");
5793 return;
5794 }
[email protected]915a59a12010-09-30 21:29:115795 if (!texture_manager()->ValidForTarget(
5796 feature_info_, target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:185797 border != 0) {
5798 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
5799 return;
5800 }
5801
[email protected]9edc6b22010-12-23 02:00:265802 // Check we have compatible formats.
5803 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5804 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5805 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
5806
5807 if ((channels_needed & channels_exist) != channels_needed) {
5808 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
5809 return;
5810 }
5811
[email protected]cadde4a2010-07-31 17:10:435812 CopyRealGLErrorsToWrapper();
[email protected]c0701082011-04-20 00:34:525813 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]6e288612010-12-21 20:45:035814 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:265815
[email protected]297ca1c2011-06-20 23:08:465816 if (info->IsAttachedToFramebuffer()) {
5817 state_dirty_ = true;
5818 }
5819
[email protected]9edc6b22010-12-23 02:00:265820 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:035821 GLint copyX = 0;
5822 GLint copyY = 0;
5823 GLint copyWidth = 0;
5824 GLint copyHeight = 0;
5825 Clip(x, width, size.width(), &copyX, &copyWidth);
5826 Clip(y, height, size.height(), &copyY, &copyHeight);
5827
5828 if (copyX != x ||
5829 copyY != y ||
5830 copyWidth != width ||
5831 copyHeight != height) {
5832 // some part was clipped so clear the texture.
5833 uint32 pixels_size = 0;
5834 if (!GLES2Util::ComputeImageDataSize(
5835 width, height, internal_format, GL_UNSIGNED_BYTE,
5836 unpack_alignment_, &pixels_size)) {
5837 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions too large");
5838 return;
5839 }
5840 scoped_array<char> zero(new char[pixels_size]);
5841 memset(zero.get(), 0, pixels_size);
5842 glTexImage2D(target, level, internal_format, width, height, 0,
5843 internal_format, GL_UNSIGNED_BYTE, zero.get());
5844 if (copyHeight > 0 && copyWidth > 0) {
5845 GLint dx = copyX - x;
5846 GLint dy = copyY - y;
5847 GLint destX = dx;
5848 GLint destY = dy;
5849 glCopyTexSubImage2D(target, level,
5850 destX, destY, copyX, copyY,
5851 copyWidth, copyHeight);
5852 }
5853 } else {
5854 glCopyTexImage2D(target, level, internal_format,
5855 copyX, copyY, copyWidth, copyHeight, border);
5856 }
[email protected]1002c2d2011-06-28 22:39:045857 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435858 if (error == GL_NO_ERROR) {
5859 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115860 feature_info_, info, target, level, internal_format, width, height, 1,
5861 border, internal_format, GL_UNSIGNED_BYTE);
[email protected]cadde4a2010-07-31 17:10:435862 }
5863}
5864
5865void GLES2DecoderImpl::DoCopyTexSubImage2D(
5866 GLenum target,
5867 GLint level,
5868 GLint xoffset,
5869 GLint yoffset,
5870 GLint x,
5871 GLint y,
5872 GLsizei width,
5873 GLsizei height) {
5874 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5875 if (!info) {
5876 SetGLError(GL_INVALID_OPERATION,
5877 "glCopyTexSubImage2D: unknown texture for target");
5878 return;
5879 }
5880 GLenum type = 0;
5881 GLenum format = 0;
5882 if (!info->GetLevelType(target, level, &type, &format) ||
5883 !info->ValidForTexture(
5884 target, level, xoffset, yoffset, width, height, format, type)) {
5885 SetGLError(GL_INVALID_VALUE,
5886 "glCopyTexSubImage2D: bad dimensions.");
5887 return;
5888 }
[email protected]9edc6b22010-12-23 02:00:265889
5890 // Check we have compatible formats.
5891 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5892 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5893 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
5894
5895 if ((channels_needed & channels_exist) != channels_needed) {
5896 SetGLError(
5897 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
5898 return;
5899 }
5900
[email protected]c0701082011-04-20 00:34:525901 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]6e288612010-12-21 20:45:035902 gfx::Size size = GetBoundReadFrameBufferSize();
5903 GLint copyX = 0;
5904 GLint copyY = 0;
5905 GLint copyWidth = 0;
5906 GLint copyHeight = 0;
5907 Clip(x, width, size.width(), &copyX, &copyWidth);
5908 Clip(y, height, size.height(), &copyY, &copyHeight);
5909 if (copyX != x ||
5910 copyY != y ||
5911 copyWidth != width ||
5912 copyHeight != height) {
5913 // some part was clipped so clear the texture.
5914 uint32 pixels_size = 0;
5915 if (!GLES2Util::ComputeImageDataSize(
5916 width, height, format, type, unpack_alignment_, &pixels_size)) {
5917 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
5918 return;
5919 }
5920 scoped_array<char> zero(new char[pixels_size]);
5921 memset(zero.get(), 0, pixels_size);
5922 glTexSubImage2D(
5923 target, level, xoffset, yoffset, width, height,
5924 format, type, zero.get());
5925 }
5926 if (copyHeight > 0 && copyWidth > 0) {
5927 GLint dx = copyX - x;
5928 GLint dy = copyY - y;
5929 GLint destX = xoffset + dx;
5930 GLint destY = yoffset + dy;
5931 glCopyTexSubImage2D(target, level,
5932 destX, destY, copyX, copyY,
5933 copyWidth, copyHeight);
5934 }
[email protected]cadde4a2010-07-31 17:10:435935}
5936
5937void GLES2DecoderImpl::DoTexSubImage2D(
5938 GLenum target,
5939 GLint level,
5940 GLint xoffset,
5941 GLint yoffset,
5942 GLsizei width,
5943 GLsizei height,
5944 GLenum format,
5945 GLenum type,
5946 const void * data) {
5947 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5948 if (!info) {
5949 SetGLError(GL_INVALID_OPERATION,
5950 "glTexSubImage2D: unknown texture for target");
5951 return;
5952 }
[email protected]df6cf1ad2011-01-29 01:20:525953 GLenum current_type = 0;
5954 GLenum internal_format = 0;
5955 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
5956 SetGLError(
5957 GL_INVALID_OPERATION,
5958 "glTexSubImage2D: level does not exist.");
5959 return;
5960 }
5961 if (format != internal_format) {
5962 SetGLError(GL_INVALID_OPERATION,
5963 "glTexSubImage2D: format does not match internal format.");
5964 return;
5965 }
5966 if (type != current_type) {
5967 SetGLError(GL_INVALID_OPERATION,
5968 "glTexSubImage2D: type does not match type of texture.");
5969 return;
5970 }
5971
[email protected]cadde4a2010-07-31 17:10:435972 if (!info->ValidForTexture(
5973 target, level, xoffset, yoffset, width, height, format, type)) {
5974 SetGLError(GL_INVALID_VALUE,
5975 "glTexSubImage2D: bad dimensions.");
5976 return;
5977 }
[email protected]473c01ccb2011-06-07 01:33:305978
5979 // See if we can call glTexImage2D instead since it appears to be faster.
5980 if (teximage2d_faster_than_texsubimage2d_ && xoffset == 0 && yoffset == 0) {
5981 GLsizei tex_width = 0;
5982 GLsizei tex_height = 0;
5983 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
5984 DCHECK(ok);
5985 if (width == tex_width && height == tex_height) {
5986 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
5987 // same as internal_foramt. If that changes we'll need to look them up.
5988 WrappedTexImage2D(
5989 target, level, format, width, height, 0, format, type, data);
5990 return;
5991 }
5992 }
[email protected]cadde4a2010-07-31 17:10:435993 glTexSubImage2D(
5994 target, level, xoffset, yoffset, width, height, format, type, data);
5995}
5996
[email protected]b493ee622011-04-13 23:52:005997error::Error GLES2DecoderImpl::HandleTexSubImage2D(
5998 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:585999 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:006000 GLboolean internal = static_cast<GLboolean>(c.internal);
6001 if (internal == GL_TRUE && tex_image_2d_failed_)
6002 return error::kNoError;
6003
6004 GLenum target = static_cast<GLenum>(c.target);
6005 GLint level = static_cast<GLint>(c.level);
6006 GLint xoffset = static_cast<GLint>(c.xoffset);
6007 GLint yoffset = static_cast<GLint>(c.yoffset);
6008 GLsizei width = static_cast<GLsizei>(c.width);
6009 GLsizei height = static_cast<GLsizei>(c.height);
6010 GLenum format = static_cast<GLenum>(c.format);
6011 GLenum type = static_cast<GLenum>(c.type);
6012 uint32 data_size;
6013 if (!GLES2Util::ComputeImageDataSize(
6014 width, height, format, type, unpack_alignment_, &data_size)) {
6015 return error::kOutOfBounds;
6016 }
6017 const void* pixels = GetSharedMemoryAs<const void*>(
6018 c.pixels_shm_id, c.pixels_shm_offset, data_size);
6019 if (!validators_->texture_target.IsValid(target)) {
6020 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6021 return error::kNoError;
6022 }
6023 if (width < 0) {
6024 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6025 return error::kNoError;
6026 }
6027 if (height < 0) {
6028 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6029 return error::kNoError;
6030 }
6031 if (!validators_->texture_format.IsValid(format)) {
6032 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6033 return error::kNoError;
6034 }
6035 if (!validators_->pixel_type.IsValid(type)) {
6036 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6037 return error::kNoError;
6038 }
6039 if (pixels == NULL) {
6040 return error::kOutOfBounds;
6041 }
6042 DoTexSubImage2D(
6043 target, level, xoffset, yoffset, width, height, format, type, pixels);
6044 return error::kNoError;
6045}
6046
6047error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
6048 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
6049 GLboolean internal = static_cast<GLboolean>(c.internal);
6050 if (internal == GL_TRUE && tex_image_2d_failed_)
6051 return error::kNoError;
6052
6053 GLenum target = static_cast<GLenum>(c.target);
6054 GLint level = static_cast<GLint>(c.level);
6055 GLint xoffset = static_cast<GLint>(c.xoffset);
6056 GLint yoffset = static_cast<GLint>(c.yoffset);
6057 GLsizei width = static_cast<GLsizei>(c.width);
6058 GLsizei height = static_cast<GLsizei>(c.height);
6059 GLenum format = static_cast<GLenum>(c.format);
6060 GLenum type = static_cast<GLenum>(c.type);
6061 uint32 data_size;
6062 if (!GLES2Util::ComputeImageDataSize(
6063 width, height, format, type, unpack_alignment_, &data_size)) {
6064 return error::kOutOfBounds;
6065 }
6066 const void* pixels = GetImmediateDataAs<const void*>(
6067 c, data_size, immediate_data_size);
6068 if (!validators_->texture_target.IsValid(target)) {
6069 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6070 return error::kNoError;
6071 }
6072 if (width < 0) {
6073 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6074 return error::kNoError;
6075 }
6076 if (height < 0) {
6077 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6078 return error::kNoError;
6079 }
6080 if (!validators_->texture_format.IsValid(format)) {
6081 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6082 return error::kNoError;
6083 }
6084 if (!validators_->pixel_type.IsValid(type)) {
6085 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6086 return error::kNoError;
6087 }
6088 if (pixels == NULL) {
6089 return error::kOutOfBounds;
6090 }
6091 DoTexSubImage2D(
6092 target, level, xoffset, yoffset, width, height, format, type, pixels);
6093 return error::kNoError;
6094}
6095
[email protected]f7a64ee2010-02-01 22:24:146096error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:196097 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:366098 GLuint index = static_cast<GLuint>(c.index);
6099 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:256100 typedef gles2::GetVertexAttribPointerv::Result Result;
6101 Result* result = GetSharedMemoryAs<Result*>(
6102 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:366103 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:146104 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:366105 }
[email protected]07d0cc82010-02-17 04:51:406106 // Check that the client initialized the result.
6107 if (result->size != 0) {
6108 return error::kInvalidArguments;
6109 }
[email protected]9438b012010-06-15 22:55:056110 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296111 SetGLError(GL_INVALID_ENUM,
6112 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146113 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366114 }
[email protected]3916c97e2010-02-25 03:20:506115 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:296116 SetGLError(GL_INVALID_VALUE,
6117 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:146118 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366119 }
[email protected]0bfd9882010-02-05 23:02:256120 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:086121 *result->GetData() =
6122 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:146123 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326124}
6125
[email protected]f7b85372010-02-03 01:11:376126bool GLES2DecoderImpl::GetUniformSetup(
6127 GLuint program, GLint location,
6128 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:106129 error::Error* error, GLuint* service_id, void** result_pointer,
6130 GLenum* result_type) {
6131 DCHECK(error);
6132 DCHECK(service_id);
6133 DCHECK(result_pointer);
6134 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:376135 *error = error::kNoError;
6136 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:256137 SizedResult<GLint>* result;
6138 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6139 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
6140 if (!result) {
[email protected]f7b85372010-02-03 01:11:376141 *error = error::kOutOfBounds;
6142 return false;
6143 }
[email protected]0bfd9882010-02-05 23:02:256144 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:376145 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:256146 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:586147 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6148 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:376149 if (!info) {
[email protected]ae51d192010-04-27 00:48:036150 return false;
6151 }
6152 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:376153 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:296154 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:376155 return false;
6156 }
[email protected]ae51d192010-04-27 00:48:036157 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:366158 GLint array_index = -1;
6159 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6160 info->GetUniformInfoByLocation(location, &array_index);
6161 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:376162 // No such location.
[email protected]8eee29c2010-04-29 03:38:296163 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:376164 return false;
6165 }
[email protected]43c2f1f2011-03-25 18:35:366166 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:506167 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:376168 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:296169 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:376170 return false;
6171 }
[email protected]0bfd9882010-02-05 23:02:256172 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6173 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
6174 if (!result) {
[email protected]f7b85372010-02-03 01:11:376175 *error = error::kOutOfBounds;
6176 return false;
6177 }
[email protected]0bfd9882010-02-05 23:02:256178 result->size = size;
[email protected]939e7362010-05-13 20:49:106179 *result_type = type;
[email protected]f7b85372010-02-03 01:11:376180 return true;
6181}
6182
[email protected]f7a64ee2010-02-01 22:24:146183error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:196184 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:376185 GLuint program = c.program;
6186 GLint location = c.location;
6187 GLuint service_id;
[email protected]939e7362010-05-13 20:49:106188 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376189 Error error;
[email protected]0bfd9882010-02-05 23:02:256190 void* result;
[email protected]f7b85372010-02-03 01:11:376191 if (GetUniformSetup(
6192 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106193 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:256194 glGetUniformiv(
6195 service_id, location,
6196 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:376197 }
6198 return error;
[email protected]96449d2c2009-11-25 00:01:326199}
6200
[email protected]f7a64ee2010-02-01 22:24:146201error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:196202 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:376203 GLuint program = c.program;
6204 GLint location = c.location;
6205 GLuint service_id;
6206 Error error;
[email protected]0bfd9882010-02-05 23:02:256207 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:106208 Result* result;
6209 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376210 if (GetUniformSetup(
6211 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106212 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
6213 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
6214 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
6215 GLsizei num_values = result->GetNumResults();
6216 scoped_array<GLint> temp(new GLint[num_values]);
6217 glGetUniformiv(service_id, location, temp.get());
6218 GLfloat* dst = result->GetData();
6219 for (GLsizei ii = 0; ii < num_values; ++ii) {
6220 dst[ii] = (temp[ii] != 0);
6221 }
6222 } else {
6223 glGetUniformfv(service_id, location, result->GetData());
6224 }
[email protected]f7b85372010-02-03 01:11:376225 }
6226 return error;
[email protected]96449d2c2009-11-25 00:01:326227}
6228
[email protected]f7a64ee2010-02-01 22:24:146229error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:196230 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:256231 GLenum shader_type = static_cast<GLenum>(c.shadertype);
6232 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
6233 typedef gles2::GetShaderPrecisionFormat::Result Result;
6234 Result* result = GetSharedMemoryAs<Result*>(
6235 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6236 if (!result) {
6237 return error::kOutOfBounds;
6238 }
[email protected]07d0cc82010-02-17 04:51:406239 // Check that the client initialized the result.
6240 if (result->success != 0) {
6241 return error::kInvalidArguments;
6242 }
[email protected]9438b012010-06-15 22:55:056243 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:296244 SetGLError(GL_INVALID_ENUM,
6245 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
6246 return error::kNoError;
6247 }
[email protected]9438b012010-06-15 22:55:056248 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:296249 SetGLError(GL_INVALID_ENUM,
6250 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
6251 return error::kNoError;
6252 }
6253
6254 result->success = 1; // true
6255 switch (precision_type) {
6256 case GL_LOW_INT:
6257 case GL_MEDIUM_INT:
6258 case GL_HIGH_INT:
6259 result->min_range = -31;
6260 result->max_range = 31;
6261 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:106262 break;
[email protected]8eee29c2010-04-29 03:38:296263 case GL_LOW_FLOAT:
6264 case GL_MEDIUM_FLOAT:
6265 case GL_HIGH_FLOAT:
6266 result->min_range = -62;
6267 result->max_range = 62;
6268 result->precision = -16;
6269 break;
6270 default:
6271 NOTREACHED();
6272 break;
[email protected]0bfd9882010-02-05 23:02:256273 }
[email protected]f7a64ee2010-02-01 22:24:146274 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326275}
6276
[email protected]f7a64ee2010-02-01 22:24:146277error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:196278 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:256279 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:586280 GLuint program = static_cast<GLuint>(c.program);
6281 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6282 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:036283 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256284 return error::kNoError;
6285 }
6286 typedef gles2::GetAttachedShaders::Result Result;
6287 uint32 max_count = Result::ComputeMaxResults(result_size);
6288 Result* result = GetSharedMemoryAs<Result*>(
6289 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
6290 if (!result) {
6291 return error::kOutOfBounds;
6292 }
[email protected]07d0cc82010-02-17 04:51:406293 // Check that the client initialized the result.
6294 if (result->size != 0) {
6295 return error::kInvalidArguments;
6296 }
[email protected]0bfd9882010-02-05 23:02:256297 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:036298 glGetAttachedShaders(
6299 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:256300 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:036301 if (!shader_manager()->GetClientId(result->GetData()[ii],
6302 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:256303 NOTREACHED();
6304 return error::kGenericError;
6305 }
6306 }
6307 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:146308 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326309}
6310
[email protected]f7a64ee2010-02-01 22:24:146311error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:196312 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:256313 GLuint program = c.program;
6314 GLuint index = c.index;
6315 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256316 typedef gles2::GetActiveUniform::Result Result;
6317 Result* result = GetSharedMemoryAs<Result*>(
6318 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6319 if (!result) {
6320 return error::kOutOfBounds;
6321 }
[email protected]07d0cc82010-02-17 04:51:406322 // Check that the client initialized the result.
6323 if (result->success != 0) {
6324 return error::kInvalidArguments;
6325 }
[email protected]6b8cf1a2010-05-06 16:13:586326 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6327 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:036328 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256329 return error::kNoError;
6330 }
6331 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6332 info->GetUniformInfo(index);
6333 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:296334 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:256335 return error::kNoError;
6336 }
6337 result->success = 1; // true.
6338 result->size = uniform_info->size;
6339 result->type = uniform_info->type;
6340 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296341 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146342 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326343}
6344
[email protected]f7a64ee2010-02-01 22:24:146345error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:196346 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:256347 GLuint program = c.program;
6348 GLuint index = c.index;
6349 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256350 typedef gles2::GetActiveAttrib::Result Result;
6351 Result* result = GetSharedMemoryAs<Result*>(
6352 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6353 if (!result) {
6354 return error::kOutOfBounds;
6355 }
[email protected]07d0cc82010-02-17 04:51:406356 // Check that the client initialized the result.
6357 if (result->success != 0) {
6358 return error::kInvalidArguments;
6359 }
[email protected]6b8cf1a2010-05-06 16:13:586360 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6361 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:036362 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256363 return error::kNoError;
6364 }
6365 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
6366 info->GetAttribInfo(index);
6367 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:296368 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:256369 return error::kNoError;
6370 }
6371 result->success = 1; // true.
6372 result->size = attrib_info->size;
6373 result->type = attrib_info->type;
6374 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296375 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146376 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326377}
6378
[email protected]b273e432010-04-12 17:23:586379error::Error GLES2DecoderImpl::HandleShaderBinary(
6380 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
6381#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:296382 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:586383 return error::kNoError;
6384#else
6385 GLsizei n = static_cast<GLsizei>(c.n);
6386 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:296387 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:586388 return error::kNoError;
6389 }
6390 GLsizei length = static_cast<GLsizei>(c.length);
6391 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:296392 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:586393 return error::kNoError;
6394 }
6395 uint32 data_size;
6396 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
6397 return error::kOutOfBounds;
6398 }
6399 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
6400 c.shaders_shm_id, c.shaders_shm_offset, data_size);
6401 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
6402 const void* binary = GetSharedMemoryAs<const void*>(
6403 c.binary_shm_id, c.binary_shm_offset, length);
6404 if (shaders == NULL || binary == NULL) {
6405 return error::kOutOfBounds;
6406 }
6407 scoped_array<GLuint> service_ids(new GLuint[n]);
6408 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:036409 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
6410 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296411 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:586412 return error::kNoError;
6413 }
[email protected]ae51d192010-04-27 00:48:036414 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:586415 }
6416 // TODO(gman): call glShaderBinary
6417 return error::kNoError;
6418#endif
6419}
6420
[email protected]6217d392010-03-25 22:08:356421error::Error GLES2DecoderImpl::HandleSwapBuffers(
6422 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:496423 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
6424 int this_frame_number = frame_number_++;
6425 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
6426 "offscreen", is_offscreen,
6427 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:356428 // If offscreen then don't actually SwapBuffers to the display. Just copy
6429 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:496430 if (is_offscreen) {
[email protected]6217d392010-03-25 22:08:356431 ScopedGLErrorSuppressor suppressor(this);
6432
6433 // First check to see if a deferred offscreen render buffer resize is
6434 // pending.
[email protected]d0498742010-09-20 20:27:016435 if (!UpdateOffscreenFrameBufferSize()) {
6436 LOG(ERROR) << "Context lost because reallocation of offscreen FBO "
6437 << "failed.";
[email protected]6217d392010-03-25 22:08:356438 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016439 }
[email protected]6217d392010-03-25 22:08:356440
[email protected]34ff8b0c2010-10-01 20:06:026441 if (IsOffscreenBufferMultisampled()) {
6442 // For multisampled buffers, bind the resolved frame buffer so that
6443 // callbacks can call ReadPixels or CopyTexImage2D.
[email protected]c0701082011-04-20 00:34:526444 ScopedResolvedFrameBufferBinder binder(this, true);
[email protected]34ff8b0c2010-10-01 20:06:026445 if (swap_buffers_callback_.get()) {
6446 swap_buffers_callback_->Run();
6447 }
[email protected]89d6ed02011-04-20 00:23:236448 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:486449 } else {
[email protected]0c8c9d22010-06-25 17:36:396450 ScopedFrameBufferBinder binder(this,
6451 offscreen_target_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:406452
[email protected]b86b14982010-10-11 18:45:486453 if (parent_) {
6454 // Copy the target frame buffer to the saved offscreen texture.
6455 offscreen_saved_color_texture_->Copy(
[email protected]3a4d0c52011-06-29 23:11:586456 offscreen_saved_color_texture_->size(),
6457 offscreen_saved_color_format_);
[email protected]b86b14982010-10-11 18:45:486458
[email protected]a3ded6d2010-10-19 06:44:396459 // Ensure the side effects of the copy are visible to the parent
6460 // context. There is no need to do this for ANGLE because it uses a
6461 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:486462 if (!IsAngle())
6463 glFlush();
6464 }
6465
6466 // Run the callback with |binder| in scope, so that the callback can call
6467 // ReadPixels or CopyTexImage2D.
6468 if (swap_buffers_callback_.get()) {
6469 swap_buffers_callback_->Run();
6470 }
[email protected]89d6ed02011-04-20 00:23:236471 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:396472 }
[email protected]6217d392010-03-25 22:08:356473 } else {
[email protected]64ace852011-05-19 21:49:496474 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:156475 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:016476 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:026477 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016478 }
[email protected]6217d392010-03-25 22:08:356479 }
6480
6481 if (swap_buffers_callback_.get()) {
6482 swap_buffers_callback_->Run();
6483 }
6484
[email protected]89d6ed02011-04-20 00:23:236485 return error::kNoError;
[email protected]6217d392010-03-25 22:08:356486}
6487
[email protected]1e6f58d2011-03-24 00:00:406488error::Error GLES2DecoderImpl::HandleSetLatchCHROMIUM(
6489 uint32 immediate_data_size, const gles2::SetLatchCHROMIUM& c) {
[email protected]3ae316442011-06-22 23:39:146490 TRACE_EVENT1("gpu", "SetLatch", "latch_id", c.latch_id);
[email protected]ce9eea602011-04-12 20:09:576491 // Ensure the side effects of previous commands are visible to other contexts.
6492 // There is no need to do this for ANGLE because it uses a
6493 // single D3D device for all contexts.
6494 if (!IsAngle())
6495 glFlush();
6496
6497 int32 shm_id = gpu::kLatchSharedMemoryId;
[email protected]1e6f58d2011-03-24 00:00:406498 uint32 latch_id = c.latch_id;
6499 uint32 shm_offset = 0;
6500 base::subtle::Atomic32* latch;
6501 if (!SafeMultiplyUint32(latch_id, sizeof(*latch), &shm_offset)) {
6502 return error::kOutOfBounds;
6503 }
6504 latch = GetSharedMemoryAs<base::subtle::Atomic32*>(
6505 shm_id, shm_offset, sizeof(*latch));
6506 if (!latch) {
6507 return error::kOutOfBounds;
6508 }
[email protected]fbe20372011-06-01 01:46:386509 base::subtle::Atomic32 old =
6510 base::subtle::NoBarrier_CompareAndSwap(latch, 0, 1);
6511 DCHECK(old == 0);
[email protected]80c49752011-04-18 23:55:106512 if (!latch_callback_.is_null())
6513 latch_callback_.Run(true);
[email protected]1e6f58d2011-03-24 00:00:406514 return error::kNoError;
6515}
6516
6517error::Error GLES2DecoderImpl::HandleWaitLatchCHROMIUM(
6518 uint32 immediate_data_size, const gles2::WaitLatchCHROMIUM& c) {
[email protected]3ae316442011-06-22 23:39:146519 TRACE_EVENT1("gpu", "WaitLatch", "latch_id", c.latch_id);
[email protected]ce9eea602011-04-12 20:09:576520 int32 shm_id = gpu::kLatchSharedMemoryId;
[email protected]1e6f58d2011-03-24 00:00:406521 uint32 latch_id = c.latch_id;
6522 uint32 shm_offset = 0;
6523 base::subtle::Atomic32* latch;
6524 if (!SafeMultiplyUint32(latch_id, sizeof(*latch), &shm_offset)) {
6525 return error::kOutOfBounds;
6526 }
6527 latch = GetSharedMemoryAs<base::subtle::Atomic32*>(
6528 shm_id, shm_offset, sizeof(*latch));
6529 if (!latch) {
6530 return error::kOutOfBounds;
6531 }
6532
6533 base::subtle::Atomic32 old =
6534 base::subtle::NoBarrier_CompareAndSwap(latch, 1, 0);
[email protected]80c49752011-04-18 23:55:106535 if (old == 0) {
6536 if (!latch_callback_.is_null())
6537 latch_callback_.Run(false);
6538 return error::kWaiting;
6539 } else {
6540 return error::kNoError;
6541 }
[email protected]1e6f58d2011-03-24 00:00:406542}
6543
[email protected]269200b12010-11-18 22:53:066544error::Error GLES2DecoderImpl::HandleCommandBufferEnableCHROMIUM(
6545 uint32 immediate_data_size, const gles2::CommandBufferEnableCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:186546 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]269200b12010-11-18 22:53:066547 typedef gles2::CommandBufferEnableCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:186548 Result* result = GetSharedMemoryAs<Result*>(
6549 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6550 if (!result) {
6551 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:106552 }
[email protected]b1d2dcb2010-05-17 19:24:186553 // Check that the client initialized the result.
6554 if (*result != 0) {
6555 return error::kInvalidArguments;
6556 }
6557 std::string feature_str;
6558 if (!bucket->GetAsString(&feature_str)) {
6559 return error::kInvalidArguments;
6560 }
6561
6562 // TODO(gman): make this some kind of table to function pointer thingy.
6563 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
6564 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]8fbedc02010-11-18 18:43:406565 } else if (feature_str.compare(PEPPER3D_SUPPORT_FIXED_ATTRIBS) == 0) {
6566 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
6567 // TODO(gman): decide how to remove the need for this const_cast.
6568 // I could make validators_ non const but that seems bad as this is the only
6569 // place it is needed. I could make some special friend class of validators
6570 // just to allow this to set them. That seems silly. I could refactor this
6571 // code to use the extension mechanism or the initialization attributes to
6572 // turn this feature on. Given that the only real point of this is to make
6573 // the conformance tests pass and given that there is lots of real work that
6574 // needs to be done it seems like refactoring for one to one of those
6575 // methods is a very low priority.
6576 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]b1d2dcb2010-05-17 19:24:186577 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
6578 use_shader_translator_ = false;
6579 } else {
6580 return error::kNoError;
6581 }
6582
6583 *result = 1; // true.
6584 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:106585}
6586
[email protected]c2f8c8402010-12-06 18:07:246587error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
6588 uint32 immediate_data_size,
6589 const gles2::GetRequestableExtensionsCHROMIUM& c) {
6590 Bucket* bucket = CreateBucket(c.bucket_id);
6591 scoped_ptr<FeatureInfo> info(new FeatureInfo());
[email protected]c410da802011-03-14 19:17:416592 info->Initialize(disallowed_extensions_, NULL);
[email protected]c2f8c8402010-12-06 18:07:246593 bucket->SetFromString(info->extensions().c_str());
6594 return error::kNoError;
6595}
6596
6597error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
6598 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
6599 Bucket* bucket = GetBucket(c.bucket_id);
6600 std::string feature_str;
6601 if (!bucket->GetAsString(&feature_str)) {
6602 return error::kInvalidArguments;
6603 }
6604
6605 bool std_derivatives_enabled =
6606 feature_info_->feature_flags().oes_standard_derivatives;
6607 bool webglsl_enabled =
6608 feature_info_->feature_flags().chromium_webglsl;
6609
6610 feature_info_->AddFeatures(feature_str.c_str());
6611
6612 // If we just enabled a feature which affects the shader translator,
6613 // we may need to re-initialize it.
6614 if (std_derivatives_enabled !=
6615 feature_info_->feature_flags().oes_standard_derivatives ||
6616 webglsl_enabled !=
6617 feature_info_->feature_flags().chromium_webglsl) {
6618 InitializeShaderTranslator();
6619 }
6620
[email protected]302ce6d2011-07-07 23:28:116621 UpdateCapabilities();
6622
[email protected]c2f8c8402010-12-06 18:07:246623 return error::kNoError;
6624}
6625
[email protected]372e0412011-06-28 16:08:566626error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
6627 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
6628 GLuint count = c.count;
6629 uint32 pnames_size;
6630 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
6631 return error::kOutOfBounds;
6632 }
6633 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
6634 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
6635 if (pnames == NULL) {
6636 return error::kOutOfBounds;
6637 }
6638
6639 // We have to copy them since we use them twice so the client
6640 // can't change them between the time we validate them and the time we use
6641 // them.
6642 scoped_array<GLenum> enums(new GLenum[count]);
6643 memcpy(enums.get(), pnames, pnames_size);
6644
6645 // Count up the space needed for the result.
6646 uint32 num_results = 0;
6647 for (GLuint ii = 0; ii < count; ++ii) {
6648 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
6649 if (num == 0) {
6650 SetGLError(GL_INVALID_ENUM,
6651 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
6652 return error::kNoError;
6653 }
6654 // Num will never be more than 4.
6655 DCHECK_LE(num, 4u);
6656 if (!SafeAdd(num_results, num, &num_results)) {
6657 return error::kOutOfBounds;
6658 }
6659 }
6660
6661 uint32 result_size = 0;
6662 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
6663 return error::kOutOfBounds;
6664 }
6665
6666 if (result_size != static_cast<uint32>(c.size)) {
6667 SetGLError(GL_INVALID_VALUE,
6668 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
6669 return error::kNoError;
6670 }
6671
6672 GLint* results = GetSharedMemoryAs<GLint*>(
6673 c.results_shm_id, c.results_shm_offset, result_size);
6674 if (results == NULL) {
6675 return error::kOutOfBounds;
6676 }
6677
6678 // Check the results have been cleared in case the context was lost.
6679 for (uint32 ii = 0; ii < num_results; ++ii) {
6680 if (results[ii]) {
6681 return error::kInvalidArguments;
6682 }
6683 }
6684
6685 // Get each result.
6686 GLint* start = results;
6687 for (GLuint ii = 0; ii < count; ++ii) {
6688 GLsizei num_written = 0;
6689 if (!GetHelper(enums[ii], results, &num_written)) {
6690 glGetIntegerv(enums[ii], results);
6691 }
6692 results += num_written;
6693 }
6694
6695 // Just to verify. Should this be a DCHECK?
6696 if (static_cast<uint32>(results - start) != num_results) {
6697 return error::kOutOfBounds;
6698 }
6699
6700 return error::kNoError;
6701}
6702
[email protected]2318d342011-07-11 22:27:426703error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
6704 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
6705 GLuint program = static_cast<GLuint>(c.program);
6706 uint32 bucket_id = c.bucket_id;
6707 Bucket* bucket = CreateBucket(bucket_id);
6708 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
6709 ProgramManager::ProgramInfo* info = NULL;
6710 if (program) {
6711 info = GetProgramInfoNotShader(program, "glGetProgramInfoCHROMIUM");
6712 if (!info) {
6713 return error::kNoError;
6714 }
6715 if (!info->IsValid()) {
6716 // Program was not linked successfully. (ie, glLinkProgram)
6717 SetGLError(GL_INVALID_OPERATION,
6718 "glGetProgramInfoCHROMIUM: program not linked");
6719 return error::kNoError;
6720 }
6721 }
6722 info->GetProgramInfo(bucket);
6723 return error::kNoError;
6724}
6725
[email protected]96449d2c2009-11-25 00:01:326726// Include the auto-generated part of this file. We split this because it means
6727// we can easily edit the non-auto generated parts right here in this file
6728// instead of having to edit some template or the code generator.
6729#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
6730
6731} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:256732} // namespace gpu