blob: 70e084725a01332d98be797d16d64c49a8b30b12 [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]a93bb842010-02-16 23:03:4737#include "gpu/command_buffer/service/texture_manager.h"
[email protected]4e8a5b122010-05-08 22:00:1038#include "gpu/GLES2/gles2_command_buffer.h"
[email protected]5ae0b282011-03-28 19:24:4939#include "ui/gfx/gl/gl_context.h"
40#include "ui/gfx/gl/gl_implementation.h"
[email protected]de17df392010-04-23 21:09:4141
[email protected]6217d392010-03-25 22:08:3542#if !defined(GL_DEPTH24_STENCIL8)
43#define GL_DEPTH24_STENCIL8 0x88F0
44#endif
45
[email protected]a7a27ace2009-12-12 00:11:2546namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3247namespace gles2 {
48
[email protected]6217d392010-03-25 22:08:3549class GLES2DecoderImpl;
50
[email protected]07f54fcc2009-12-22 02:46:3051// Check that certain assumptions the code makes are true. There are places in
52// the code where shared memory is passed direclty to GL. Example, glUniformiv,
53// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
54// a few others) are 32bits. If they are not 32bits the code will have to change
55// to call those GL functions with service side memory and then copy the results
56// to shared memory, converting the sizes.
57COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
58 GLint_not_same_size_as_uint32);
59COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
60 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3761COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
62 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3063
[email protected]43f28f832010-02-03 02:28:4864// TODO(kbr): the use of this anonymous namespace core dumps the
65// linker on Mac OS X 10.6 when the symbol ordering file is used
66// namespace {
[email protected]96449d2c2009-11-25 00:01:3267
68// Returns the address of the first byte after a struct.
69template <typename T>
70const void* AddressAfterStruct(const T& pod) {
71 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
72}
73
[email protected]07f54fcc2009-12-22 02:46:3074// Returns the address of the frst byte after the struct or NULL if size >
75// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3276template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3077RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
78 uint32 size,
79 uint32 immediate_data_size) {
80 return (size <= immediate_data_size) ?
81 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
82 NULL;
[email protected]96449d2c2009-11-25 00:01:3283}
84
[email protected]07f54fcc2009-12-22 02:46:3085// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1886bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3287 GLuint count,
88 size_t size,
[email protected]a76b0052010-03-05 00:33:1889 unsigned int elements_per_unit,
90 uint32* dst) {
91 uint32 value;
92 if (!SafeMultiplyUint32(count, size, &value)) {
93 return false;
94 }
95 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
96 return false;
97 }
98 *dst = value;
99 return true;
[email protected]96449d2c2009-11-25 00:01:32100}
101
102// A struct to hold info about each command.
103struct CommandInfo {
104 int arg_flags; // How to handle the arguments for this command
105 int arg_count; // How many arguments are expected for this command.
106};
107
108// A table of CommandInfo for all the commands.
109const CommandInfo g_command_info[] = {
110 #define GLES2_CMD_OP(name) { \
111 name::kArgFlags, \
112 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
113
114 GLES2_COMMAND_LIST(GLES2_CMD_OP)
115
116 #undef GLES2_CMD_OP
117};
118
[email protected]34ff8b0c2010-10-01 20:06:02119static bool IsAngle() {
120#if defined(OS_WIN)
121 return gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
122#else
123 return false;
124#endif
125}
126
[email protected]6217d392010-03-25 22:08:35127// This class prevents any GL errors that occur when it is in scope from
128// being reported to the client.
129class ScopedGLErrorSuppressor {
130 public:
131 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
132 ~ScopedGLErrorSuppressor();
133 private:
134 GLES2DecoderImpl* decoder_;
135 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
136};
137
138// Temporarily changes a decoder's bound 2D texture and restore it when this
139// object goes out of scope. Also temporarily switches to using active texture
140// unit zero in case the client has changed that to something invalid.
141class ScopedTexture2DBinder {
142 public:
143 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
144 ~ScopedTexture2DBinder();
145
146 private:
147 GLES2DecoderImpl* decoder_;
148 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
149};
150
151// Temporarily changes a decoder's bound render buffer and restore it when this
152// object goes out of scope.
153class ScopedRenderBufferBinder {
154 public:
155 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
156 ~ScopedRenderBufferBinder();
157
158 private:
159 GLES2DecoderImpl* decoder_;
160 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
161};
162
163// Temporarily changes a decoder's bound frame buffer and restore it when this
164// object goes out of scope.
165class ScopedFrameBufferBinder {
166 public:
167 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
168 ~ScopedFrameBufferBinder();
169
170 private:
171 GLES2DecoderImpl* decoder_;
172 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
173};
174
[email protected]34ff8b0c2010-10-01 20:06:02175// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52176// the multisampled offscreen render buffer if that buffer is multisampled, and,
177// if it is bound or enforce_internal_framebuffer is true.
[email protected]34ff8b0c2010-10-01 20:06:02178class ScopedResolvedFrameBufferBinder {
179 public:
[email protected]c0701082011-04-20 00:34:52180 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
181 bool enforce_internal_framebuffer);
[email protected]34ff8b0c2010-10-01 20:06:02182 ~ScopedResolvedFrameBufferBinder();
183
184 private:
185 GLES2DecoderImpl* decoder_;
186 bool resolve_and_bind_;
187 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
188};
189
[email protected]6217d392010-03-25 22:08:35190// Encapsulates an OpenGL texture.
191class Texture {
192 public:
193 explicit Texture(GLES2DecoderImpl* decoder);
194 ~Texture();
195
196 // Create a new render texture.
197 void Create();
198
199 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02200 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35201
202 // Copy the contents of the currently bound frame buffer.
203 void Copy(const gfx::Size& size);
204
205 // Destroy the render texture. This must be explicitly called before
206 // destroying this object.
207 void Destroy();
208
[email protected]97872062010-11-03 19:07:05209 // Invalidate the texture. This can be used when a context is lost and it is
210 // not possible to make it current in order to free the resource.
211 void Invalidate();
212
[email protected]6217d392010-03-25 22:08:35213 GLuint id() const {
214 return id_;
215 }
216
[email protected]d37231fa2010-04-09 21:16:02217 gfx::Size size() const {
218 return size_;
219 }
220
[email protected]6217d392010-03-25 22:08:35221 private:
222 GLES2DecoderImpl* decoder_;
223 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02224 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35225 DISALLOW_COPY_AND_ASSIGN(Texture);
226};
227
228// Encapsulates an OpenGL render buffer of any format.
229class RenderBuffer {
230 public:
231 explicit RenderBuffer(GLES2DecoderImpl* decoder);
232 ~RenderBuffer();
233
234 // Create a new render buffer.
235 void Create();
236
237 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02238 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35239
240 // Destroy the render buffer. This must be explicitly called before destroying
241 // this object.
242 void Destroy();
243
[email protected]97872062010-11-03 19:07:05244 // Invalidate the render buffer. This can be used when a context is lost and
245 // it is not possible to make it current in order to free the resource.
246 void Invalidate();
247
[email protected]6217d392010-03-25 22:08:35248 GLuint id() const {
249 return id_;
250 }
251
252 private:
253 GLES2DecoderImpl* decoder_;
254 GLuint id_;
255 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
256};
257
258// Encapsulates an OpenGL frame buffer.
259class FrameBuffer {
260 public:
261 explicit FrameBuffer(GLES2DecoderImpl* decoder);
262 ~FrameBuffer();
263
264 // Create a new frame buffer.
265 void Create();
266
267 // Attach a color render buffer to a frame buffer.
268 void AttachRenderTexture(Texture* texture);
269
[email protected]b9363b22010-06-09 22:06:15270 // Attach a render buffer to a frame buffer. Note that this unbinds any
271 // currently bound frame buffer.
272 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35273
274 // Clear the given attached buffers.
275 void Clear(GLbitfield buffers);
276
277 // Destroy the frame buffer. This must be explicitly called before destroying
278 // this object.
279 void Destroy();
280
[email protected]97872062010-11-03 19:07:05281 // Invalidate the frame buffer. This can be used when a context is lost and it
282 // is not possible to make it current in order to free the resource.
283 void Invalidate();
284
[email protected]6217d392010-03-25 22:08:35285 // See glCheckFramebufferStatusEXT.
286 GLenum CheckStatus();
287
288 GLuint id() const {
289 return id_;
290 }
291
292 private:
293 GLES2DecoderImpl* decoder_;
294 GLuint id_;
295 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
296};
[email protected]34ff8b0c2010-10-01 20:06:02297
298class ContextCreationAttribParser {
299 public:
300 ContextCreationAttribParser();
301 bool Parse(const std::vector<int32>& attribs);
302
303 // -1 if invalid or unspecified.
304 int32 alpha_size_;
305 int32 blue_size_;
306 int32 green_size_;
307 int32 red_size_;
308 int32 depth_size_;
309 int32 stencil_size_;
310 int32 samples_;
311 int32 sample_buffers_;
312};
313
314ContextCreationAttribParser::ContextCreationAttribParser()
315 : alpha_size_(-1),
316 blue_size_(-1),
317 green_size_(-1),
318 red_size_(-1),
319 depth_size_(-1),
320 stencil_size_(-1),
321 samples_(-1),
322 sample_buffers_(-1) {
323}
324
325bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
326 // From <EGL/egl.h>.
327 const int32 EGL_ALPHA_SIZE = 0x3021;
328 const int32 EGL_BLUE_SIZE = 0x3022;
329 const int32 EGL_GREEN_SIZE = 0x3023;
330 const int32 EGL_RED_SIZE = 0x3024;
331 const int32 EGL_DEPTH_SIZE = 0x3025;
332 const int32 EGL_STENCIL_SIZE = 0x3026;
333 const int32 EGL_SAMPLES = 0x3031;
334 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
335 const int32 EGL_NONE = 0x3038;
336
337 for (size_t i = 0; i < attribs.size(); i += 2) {
338 const int32 attrib = attribs[i];
339 if (i + 1 >= attribs.size()) {
340 if (attrib == EGL_NONE)
341 return true;
342
343 DLOG(ERROR) << "Missing value after context creation attribute: "
344 << attrib;
345 return false;
346 }
347
348 const int32 value = attribs[i+1];
349 switch (attrib) {
350 case EGL_ALPHA_SIZE:
351 alpha_size_ = value;
352 break;
353 case EGL_BLUE_SIZE:
354 blue_size_ = value;
355 break;
356 case EGL_GREEN_SIZE:
357 green_size_ = value;
358 break;
359 case EGL_RED_SIZE:
360 red_size_ = value;
361 break;
362 case EGL_DEPTH_SIZE:
363 depth_size_ = value;
364 break;
365 case EGL_STENCIL_SIZE:
366 stencil_size_ = value;
367 break;
368 case EGL_SAMPLES:
369 samples_ = value;
370 break;
371 case EGL_SAMPLE_BUFFERS:
372 sample_buffers_ = value;
373 break;
374 case EGL_NONE:
375 // Terminate list, even if more attributes.
376 return true;
377 default:
378 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
379 return false;
380 }
381 }
382
383 return true;
384}
385
[email protected]43f28f832010-02-03 02:28:48386// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32387
[email protected]ddb1e5a2010-12-13 20:10:45388bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
389 uint32* service_texture_id) {
390 return false;
391}
392
[email protected]a3ded6d2010-10-19 06:44:39393GLES2Decoder::GLES2Decoder()
394 : debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32395}
396
[email protected]3916c97e2010-02-25 03:20:50397GLES2Decoder::~GLES2Decoder() {
398}
399
[email protected]f39f4b3f2010-05-12 17:04:08400class VertexAttribManager {
[email protected]96449d2c2009-11-25 00:01:32401 public:
[email protected]07f54fcc2009-12-22 02:46:30402 // Info about Vertex Attributes. This is used to track what the user currently
403 // has bound on each Vertex Attribute so that checking can be done at
404 // glDrawXXX time.
405 class VertexAttribInfo {
406 public:
[email protected]f39f4b3f2010-05-12 17:04:08407 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
[email protected]b1122982010-05-17 23:04:24408 struct Vec4 {
409 float v[4];
410 };
[email protected]f39f4b3f2010-05-12 17:04:08411
[email protected]07f54fcc2009-12-22 02:46:30412 VertexAttribInfo()
[email protected]f39f4b3f2010-05-12 17:04:08413 : index_(0),
414 enabled_(false),
415 size_(4),
416 type_(GL_FLOAT),
[email protected]07f54fcc2009-12-22 02:46:30417 offset_(0),
[email protected]b1122982010-05-17 23:04:24418 normalized_(GL_FALSE),
419 gl_stride_(0),
[email protected]f39f4b3f2010-05-12 17:04:08420 real_stride_(16),
421 list_(NULL) {
[email protected]b1122982010-05-17 23:04:24422 value_.v[0] = 0.0f;
423 value_.v[1] = 0.0f;
424 value_.v[2] = 0.0f;
425 value_.v[3] = 1.0f;
[email protected]07f54fcc2009-12-22 02:46:30426 }
[email protected]3916c97e2010-02-25 03:20:50427
[email protected]07f54fcc2009-12-22 02:46:30428 // Returns true if this VertexAttrib can access index.
[email protected]f39f4b3f2010-05-12 17:04:08429 bool CanAccess(GLuint index) const;
[email protected]07f54fcc2009-12-22 02:46:30430
[email protected]3916c97e2010-02-25 03:20:50431 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30432 return buffer_;
433 }
434
[email protected]8bf5a3e2010-01-29 04:21:36435 GLsizei offset() const {
436 return offset_;
437 }
438
[email protected]f39f4b3f2010-05-12 17:04:08439 GLuint index() const {
440 return index_;
441 }
442
[email protected]b1122982010-05-17 23:04:24443 GLint size() const {
444 return size_;
445 }
446
447 GLenum type() const {
448 return type_;
449 }
450
451 GLboolean normalized() const {
452 return normalized_;
453 }
454
455 GLsizei gl_stride() const {
456 return gl_stride_;
457 }
458
[email protected]f39f4b3f2010-05-12 17:04:08459 bool enabled() const {
460 return enabled_;
461 }
462
[email protected]b1122982010-05-17 23:04:24463 void set_value(const Vec4& value) {
464 value_ = value;
465 }
466
467 const Vec4& value() const {
468 return value_;
469 }
470
[email protected]07f54fcc2009-12-22 02:46:30471 private:
[email protected]f39f4b3f2010-05-12 17:04:08472 friend class VertexAttribManager;
473
474 void set_enabled(bool enabled) {
475 enabled_ = enabled;
476 }
477
478 void set_index(GLuint index) {
479 index_ = index;
480 }
481
482 void SetList(VertexAttribInfoList* new_list) {
483 DCHECK(new_list);
484
485 if (list_) {
486 list_->erase(it_);
487 }
488
489 it_ = new_list->insert(new_list->end(), this);
490 list_ = new_list;
491 }
492
[email protected]8fbedc02010-11-18 18:43:40493 void SetInfo(
494 BufferManager::BufferInfo* buffer,
495 GLint size,
496 GLenum type,
497 GLboolean normalized,
498 GLsizei gl_stride,
499 GLsizei real_stride,
500 GLsizei offset) {
501 DCHECK_GT(real_stride, 0);
502 buffer_ = buffer;
503 size_ = size;
504 type_ = type;
505 normalized_ = normalized;
506 gl_stride_ = gl_stride;
507 real_stride_ = real_stride;
508 offset_ = offset;
509 }
510
[email protected]f39f4b3f2010-05-12 17:04:08511 // The index of this attrib.
512 GLuint index_;
513
[email protected]07f54fcc2009-12-22 02:46:30514 // Whether or not this attribute is enabled.
515 bool enabled_;
516
517 // number of components (1, 2, 3, 4)
518 GLint size_;
519
520 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
521 GLenum type_;
522
523 // The offset into the buffer.
524 GLsizei offset_;
525
[email protected]b1122982010-05-17 23:04:24526 GLboolean normalized_;
527
528 // The stride passed to glVertexAttribPointer.
529 GLsizei gl_stride_;
530
[email protected]07f54fcc2009-12-22 02:46:30531 // The stride that will be used to access the buffer. This is the actual
532 // stide, NOT the GL bogus stride. In other words there is never a stride
533 // of 0.
534 GLsizei real_stride_;
535
[email protected]b1122982010-05-17 23:04:24536 // The current value of the attrib.
537 Vec4 value_;
538
[email protected]3916c97e2010-02-25 03:20:50539 // The buffer bound to this attribute.
540 BufferManager::BufferInfo::Ref buffer_;
[email protected]f39f4b3f2010-05-12 17:04:08541
542 // List this info is on.
543 VertexAttribInfoList* list_;
544
545 // Iterator for list this info is on. Enabled/Disabled
546 VertexAttribInfoList::iterator it_;
[email protected]07f54fcc2009-12-22 02:46:30547 };
548
[email protected]f39f4b3f2010-05-12 17:04:08549 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
550
551 VertexAttribManager()
[email protected]8fbedc02010-11-18 18:43:40552 : max_vertex_attribs_(0),
553 num_fixed_attribs_(0) {
[email protected]f39f4b3f2010-05-12 17:04:08554 }
555
556 void Initialize(uint32 num_vertex_attribs);
557
558 bool Enable(GLuint index, bool enable);
559
[email protected]8fbedc02010-11-18 18:43:40560 bool HaveFixedAttribs() const {
561 return num_fixed_attribs_ != 0;
562 }
563
[email protected]f39f4b3f2010-05-12 17:04:08564 const VertexAttribInfoList& GetEnabledVertexAttribInfos() const {
565 return enabled_vertex_attribs_;
566 }
567
568 VertexAttribInfo* GetVertexAttribInfo(GLuint index) {
[email protected]b1122982010-05-17 23:04:24569 if (index < max_vertex_attribs_) {
570 return &vertex_attrib_infos_[index];
571 }
572 return NULL;
[email protected]f39f4b3f2010-05-12 17:04:08573 }
574
[email protected]8fbedc02010-11-18 18:43:40575 void SetAttribInfo(
576 GLuint index,
577 BufferManager::BufferInfo* buffer,
578 GLint size,
579 GLenum type,
580 GLboolean normalized,
581 GLsizei gl_stride,
582 GLsizei real_stride,
583 GLsizei offset) {
584 VertexAttribInfo* info = GetVertexAttribInfo(index);
585 if (info) {
586 if (info->type() == GL_FIXED) {
587 --num_fixed_attribs_;
588 }
589 if (type == GL_FIXED) {
590 ++num_fixed_attribs_;
591 }
592 info->SetInfo(
593 buffer, size, type, normalized, gl_stride, real_stride, offset);
594 }
595 }
596
597
[email protected]f39f4b3f2010-05-12 17:04:08598 private:
599 uint32 max_vertex_attribs_;
600
[email protected]8fbedc02010-11-18 18:43:40601 // number of attribs using type GL_FIXED.
602 int num_fixed_attribs_;
603
[email protected]f39f4b3f2010-05-12 17:04:08604 // Info for each vertex attribute saved so we can check at glDrawXXX time
605 // if it is safe to draw.
606 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
607
608 // Lists for which vertex attribs are enabled, disabled.
609 VertexAttribInfoList enabled_vertex_attribs_;
610 VertexAttribInfoList disabled_vertex_attribs_;
611};
612
613bool VertexAttribManager::VertexAttribInfo::CanAccess(GLuint index) const {
614 if (!enabled_) {
615 return true;
616 }
617
618 if (!buffer_ || buffer_->IsDeleted()) {
619 return false;
620 }
621
622 // The number of elements that can be accessed.
623 GLsizeiptr buffer_size = buffer_->size();
624 if (offset_ > buffer_size || real_stride_ == 0) {
625 return false;
626 }
627
628 uint32 usable_size = buffer_size - offset_;
629 GLuint num_elements = usable_size / real_stride_ +
630 ((usable_size % real_stride_) >=
631 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
632 return index < num_elements;
633}
634
635
636void VertexAttribManager::Initialize(uint32 max_vertex_attribs) {
637 max_vertex_attribs_ = max_vertex_attribs;
638 vertex_attrib_infos_.reset(
639 new VertexAttribInfo[max_vertex_attribs]);
640 for (uint32 vv = 0; vv < max_vertex_attribs; ++vv) {
641 vertex_attrib_infos_[vv].set_index(vv);
642 vertex_attrib_infos_[vv].SetList(&disabled_vertex_attribs_);
643 }
644}
645
646bool VertexAttribManager::Enable(GLuint index, bool enable) {
647 if (index >= max_vertex_attribs_) {
648 return false;
649 }
650 VertexAttribInfo& info = vertex_attrib_infos_[index];
651 if (info.enabled() != enable) {
652 info.set_enabled(enable);
653 info.SetList(enable ? &enabled_vertex_attribs_ : &disabled_vertex_attribs_);
654 }
655 return true;
656}
657
658// This class implements GLES2Decoder so we don't have to expose all the GLES2
659// cmd stuff to outside this class.
660class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
661 public GLES2Decoder {
662 public:
663 explicit GLES2DecoderImpl(ContextGroup* group);
664
[email protected]96449d2c2009-11-25 00:01:32665 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14666 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50667 unsigned int arg_count,
668 const void* args);
[email protected]96449d2c2009-11-25 00:01:32669
670 // Overridden from AsyncAPIInterface.
671 virtual const char* GetCommandName(unsigned int command_id) const;
672
673 // Overridden from GLES2Decoder.
[email protected]5a6db6c2010-04-22 18:32:06674 virtual bool Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:35675 const gfx::Size& size,
[email protected]c410da802011-03-14 19:17:41676 const DisallowedExtensions& disallowed_extensions,
[email protected]a3ded6d2010-10-19 06:44:39677 const char* allowed_extensions,
[email protected]34ff8b0c2010-10-01 20:06:02678 const std::vector<int32>& attribs,
[email protected]d37231fa2010-04-09 21:16:02679 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35680 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32681 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35682 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]c71caa82010-06-02 23:25:45683 virtual bool UpdateOffscreenFrameBufferSize();
[email protected]eb54a562010-01-20 21:55:18684 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55685 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30686 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39687 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48688
[email protected]7ff86b92010-11-25 17:50:00689 virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
[email protected]43f28f832010-02-03 02:28:48690 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
[email protected]80c49752011-04-18 23:55:10691 virtual void SetLatchCallback(const base::Callback<void(bool)>& callback);;
[email protected]1318e922010-09-17 22:03:16692 virtual bool GetServiceTextureId(uint32 client_texture_id,
693 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48694
[email protected]8e3e0662010-08-23 18:46:30695 // Restores the current state to the user's settings.
696 void RestoreCurrentFramebufferBindings();
697 void RestoreCurrentRenderbufferBindings();
698 void RestoreCurrentTexture2DBindings();
699
[email protected]96449d2c2009-11-25 00:01:32700 private:
[email protected]6217d392010-03-25 22:08:35701 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02702 friend class ScopedResolvedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35703 friend class RenderBuffer;
704 friend class FrameBuffer;
705
[email protected]3916c97e2010-02-25 03:20:50706 // State associated with each texture unit.
707 struct TextureUnit {
708 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
709
710 // The last target that was bound to this texture unit.
711 GLenum bind_target;
712
713 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
714 TextureManager::TextureInfo::Ref bound_texture_2d;
715
716 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
717 // glBindTexture
718 TextureManager::TextureInfo::Ref bound_texture_cube_map;
719 };
720
[email protected]c2f8c8402010-12-06 18:07:24721 // Initialize or re-initialize the shader translator.
722 bool InitializeShaderTranslator();
723
[email protected]ae51d192010-04-27 00:48:03724 // Helpers for the glGen and glDelete functions.
725 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
726 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
727 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
728 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
729 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
730 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
731 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
732 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47733
[email protected]3916c97e2010-02-25 03:20:50734 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50735 BufferManager* buffer_manager() {
736 return group_->buffer_manager();
737 }
738
[email protected]a25fa872010-03-25 02:57:58739 RenderbufferManager* renderbuffer_manager() {
740 return group_->renderbuffer_manager();
741 }
742
743 FramebufferManager* framebuffer_manager() {
744 return group_->framebuffer_manager();
745 }
746
[email protected]3916c97e2010-02-25 03:20:50747 ProgramManager* program_manager() {
748 return group_->program_manager();
749 }
750
751 ShaderManager* shader_manager() {
752 return group_->shader_manager();
753 }
754
755 TextureManager* texture_manager() {
756 return group_->texture_manager();
757 }
758
[email protected]34ff8b0c2010-10-01 20:06:02759 bool IsOffscreenBufferMultisampled() const {
760 return offscreen_target_samples_ > 1;
761 }
762
[email protected]a93bb842010-02-16 23:03:47763 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03764 TextureManager::TextureInfo* CreateTextureInfo(
765 GLuint client_id, GLuint service_id) {
[email protected]915a59a12010-09-30 21:29:11766 return texture_manager()->CreateTextureInfo(
767 feature_info_, client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47768 }
769
770 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03771 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50772 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03773 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50774 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47775 }
776
777 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03778 void RemoveTextureInfo(GLuint client_id) {
[email protected]915a59a12010-09-30 21:29:11779 texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]3916c97e2010-02-25 03:20:50780 }
[email protected]a93bb842010-02-16 23:03:47781
[email protected]d37231fa2010-04-09 21:16:02782 // Get the size (in pixels) of the currently bound frame buffer (either FBO
783 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30784 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02785
[email protected]9edc6b22010-12-23 02:00:26786 // Get the format of the currently bound frame buffer (either FBO or regular
787 // back buffer)
788 GLenum GetBoundReadFrameBufferInternalFormat();
789
[email protected]a93bb842010-02-16 23:03:47790 // Wrapper for CompressedTexImage2D commands.
791 error::Error DoCompressedTexImage2D(
792 GLenum target,
793 GLint level,
794 GLenum internal_format,
795 GLsizei width,
796 GLsizei height,
797 GLint border,
798 GLsizei image_size,
799 const void* data);
800
[email protected]cadde4a2010-07-31 17:10:43801 // Wrapper for CompressedTexSubImage2D.
802 void DoCompressedTexSubImage2D(
803 GLenum target,
804 GLint level,
805 GLint xoffset,
806 GLint yoffset,
807 GLsizei width,
808 GLsizei height,
809 GLenum format,
810 GLsizei imageSize,
811 const void * data);
812
813 // Wrapper for CopyTexImage2D.
814 void DoCopyTexImage2D(
815 GLenum target,
816 GLint level,
817 GLenum internal_format,
818 GLint x,
819 GLint y,
820 GLsizei width,
821 GLsizei height,
822 GLint border);
823
824 // Wrapper for CopyTexSubImage2D.
825 void DoCopyTexSubImage2D(
826 GLenum target,
827 GLint level,
828 GLint xoffset,
829 GLint yoffset,
830 GLint x,
831 GLint y,
832 GLsizei width,
833 GLsizei height);
834
[email protected]a93bb842010-02-16 23:03:47835 // Wrapper for TexImage2D commands.
836 error::Error DoTexImage2D(
837 GLenum target,
838 GLint level,
839 GLenum internal_format,
840 GLsizei width,
841 GLsizei height,
842 GLint border,
843 GLenum format,
844 GLenum type,
845 const void* pixels,
846 uint32 pixels_size);
847
[email protected]cadde4a2010-07-31 17:10:43848 // Wrapper for TexSubImage2D.
849 void DoTexSubImage2D(
850 GLenum target,
851 GLint level,
852 GLint xoffset,
853 GLint yoffset,
854 GLsizei width,
855 GLsizei height,
856 GLenum format,
857 GLenum type,
858 const void * data);
859
[email protected]a93bb842010-02-16 23:03:47860 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57861 ProgramManager::ProgramInfo* CreateProgramInfo(
862 GLuint client_id, GLuint service_id) {
863 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47864 }
865
[email protected]07f54fcc2009-12-22 02:46:30866 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03867 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14868 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46869 }
[email protected]07f54fcc2009-12-22 02:46:30870
[email protected]6b8cf1a2010-05-06 16:13:58871 // Gets the program info for the given program. If it's not a program
872 // generates a GL error. Returns NULL if not program.
873 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
874 GLuint client_id, const char* function_name) {
875 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
876 if (!info) {
877 if (GetShaderInfo(client_id)) {
878 SetGLError(GL_INVALID_OPERATION,
879 (std::string(function_name) +
880 ": shader passed for program").c_str());
881 } else {
882 SetGLError(GL_INVALID_VALUE,
883 (std::string(function_name) + ": unknown program").c_str());
884 }
885 }
886 return info;
887 }
888
889
[email protected]45bf5152010-02-12 00:11:31890 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57891 ShaderManager::ShaderInfo* CreateShaderInfo(
892 GLuint client_id,
893 GLuint service_id,
894 GLenum shader_type) {
895 return shader_manager()->CreateShaderInfo(
896 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31897 }
898
899 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03900 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14901 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31902 }
903
[email protected]6b8cf1a2010-05-06 16:13:58904 // Gets the shader info for the given shader. If it's not a shader generates a
905 // GL error. Returns NULL if not shader.
906 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
907 GLuint client_id, const char* function_name) {
908 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
909 if (!info) {
910 if (GetProgramInfo(client_id)) {
911 SetGLError(
912 GL_INVALID_OPERATION,
913 (std::string(function_name) +
914 ": program passed for shader").c_str());
915 } else {
916 SetGLError(GL_INVALID_VALUE,
917 (std::string(function_name) + ": unknown shader").c_str());
918 }
919 }
920 return info;
921 }
922
[email protected]a93bb842010-02-16 23:03:47923 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03924 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
925 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47926 }
927
[email protected]07f54fcc2009-12-22 02:46:30928 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03929 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
930 BufferManager::BufferInfo* info =
931 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50932 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46933 }
[email protected]07f54fcc2009-12-22 02:46:30934
[email protected]a93bb842010-02-16 23:03:47935 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
936 // on glDeleteBuffers so we can make sure the user does not try to render
937 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03938 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47939
[email protected]a25fa872010-03-25 02:57:58940 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03941 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
942 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58943 }
944
945 // Gets the framebuffer info for the given framebuffer.
946 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03947 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58948 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03949 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58950 return (info && !info->IsDeleted()) ? info : NULL;
951 }
952
953 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03954 void RemoveFramebufferInfo(GLuint client_id) {
955 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58956 }
957
958 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03959 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
960 return renderbuffer_manager()->CreateRenderbufferInfo(
961 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58962 }
963
964 // Gets the renderbuffer info for the given renderbuffer.
965 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03966 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58967 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03968 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58969 return (info && !info->IsDeleted()) ? info : NULL;
970 }
971
972 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03973 void RemoveRenderbufferInfo(GLuint client_id) {
974 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58975 }
976
[email protected]558847a2010-03-24 07:02:54977 error::Error GetAttribLocationHelper(
978 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
979 const std::string& name_str);
980
981 error::Error GetUniformLocationHelper(
982 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
983 const std::string& name_str);
984
[email protected]3916c97e2010-02-25 03:20:50985 // Helper for glShaderSource.
986 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03987 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30988
[email protected]3a2e7c7b2010-08-06 01:12:28989 // Clears any uncleared render buffers attached to the given frame buffer.
[email protected]8e3e0662010-08-23 18:46:30990 void ClearUnclearedRenderbuffers(
991 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28992
[email protected]c007aa02010-09-02 22:22:40993 // Restore all GL state that affects clearing.
994 void RestoreClearState();
995
[email protected]3a2e7c7b2010-08-06 01:12:28996 // Remembers the state of some capabilities.
997 void SetCapabilityState(GLenum cap, bool enabled);
998
[email protected]3a03a8f2011-03-19 00:51:27999 // Check that the current frame buffer is complete. Generates error if not.
1000 bool CheckFramebufferComplete(const char* func_name);
1001
[email protected]939e7362010-05-13 20:49:101002 // Checks if the current program exists and is valid. If not generates the
1003 // appropriate GL error. Returns true if the current program is in a usable
1004 // state.
1005 bool CheckCurrentProgram(const char* function_name);
1006
1007 // Checks if the current program exists and is valid and that location is not
1008 // -1. If the current program is not valid generates the appropriate GL
1009 // error. Returns true if the current program is in a usable state and
1010 // location is not -1.
1011 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1012
1013 // Gets the type of a uniform for a location in the current program. Sets GL
1014 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:361015 // program is valid and the location exists. Adjusts count so it
1016 // does not overflow the uniform.
1017 bool PrepForSetUniformByLocation(
1018 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:101019
[email protected]b273e432010-04-12 17:23:581020 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1021 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1022
[email protected]96449d2c2009-11-25 00:01:321023 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:031024 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321025
1026 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:031027 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321028
[email protected]3916c97e2010-02-25 03:20:501029 // Wrapper for glActiveTexture
1030 void DoActiveTexture(GLenum texture_unit);
1031
[email protected]ae51d192010-04-27 00:48:031032 // Wrapper for glAttachShader
1033 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1034
[email protected]96449d2c2009-11-25 00:01:321035 // Wrapper for glBindBuffer since we need to track the current targets.
1036 void DoBindBuffer(GLenum target, GLuint buffer);
1037
[email protected]86093972010-03-11 00:13:561038 // Wrapper for glBindFramebuffer since we need to track the current targets.
1039 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1040
1041 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1042 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1043
[email protected]a93bb842010-02-16 23:03:471044 // Wrapper for glBindTexture since we need to track the current targets.
1045 void DoBindTexture(GLenum target, GLuint texture);
1046
[email protected]8e3e0662010-08-23 18:46:301047 // Wrapper for glBlitFramebufferEXT.
1048 void DoBlitFramebufferEXT(
1049 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1050 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1051 GLbitfield mask, GLenum filter);
1052
[email protected]36cef8ce2010-03-16 07:34:451053 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111054 void DoBufferData(
1055 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1056
[email protected]36cef8ce2010-03-16 07:34:451057 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111058 void DoBufferSubData(
1059 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1060
[email protected]36cef8ce2010-03-16 07:34:451061 // Wrapper for glCheckFramebufferStatus
1062 GLenum DoCheckFramebufferStatus(GLenum target);
1063
[email protected]3a03a8f2011-03-19 00:51:271064 // Wrapper for glClear
1065 void DoClear(GLbitfield mask);
1066
[email protected]3a2e7c7b2010-08-06 01:12:281067 // Wrappers for clear and mask settings functions.
1068 void DoClearColor(
1069 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1070 void DoClearDepthf(GLclampf depth);
1071 void DoClearStencil(GLint s);
1072 void DoColorMask(
1073 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1074 void DoDepthMask(GLboolean depth);
1075 void DoStencilMask(GLuint mask);
1076 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1077
[email protected]45bf5152010-02-12 00:11:311078 // Wrapper for glCompileShader.
1079 void DoCompileShader(GLuint shader);
1080
[email protected]269200b12010-11-18 22:53:061081 // Helper for DeleteSharedIdsCHROMIUM commands.
1082 void DoDeleteSharedIdsCHROMIUM(
1083 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101084
[email protected]ae51d192010-04-27 00:48:031085 // Wrapper for glDetachShader
1086 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1087
[email protected]07f54fcc2009-12-22 02:46:301088 // Wrapper for glDrawArrays.
1089 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
1090
[email protected]3a2e7c7b2010-08-06 01:12:281091 // Wrapper for glDisable
1092 void DoDisable(GLenum cap);
1093
[email protected]07f54fcc2009-12-22 02:46:301094 // Wrapper for glDisableVertexAttribArray.
1095 void DoDisableVertexAttribArray(GLuint index);
1096
[email protected]3a2e7c7b2010-08-06 01:12:281097 // Wrapper for glEnable
1098 void DoEnable(GLenum cap);
1099
[email protected]07f54fcc2009-12-22 02:46:301100 // Wrapper for glEnableVertexAttribArray.
1101 void DoEnableVertexAttribArray(GLuint index);
1102
[email protected]36cef8ce2010-03-16 07:34:451103 // Wrapper for glFramebufferRenderbufffer.
1104 void DoFramebufferRenderbuffer(
1105 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1106 GLuint renderbuffer);
1107
1108 // Wrapper for glFramebufferTexture2D.
1109 void DoFramebufferTexture2D(
1110 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1111 GLint level);
1112
[email protected]a93bb842010-02-16 23:03:471113 // Wrapper for glGenerateMipmap
1114 void DoGenerateMipmap(GLenum target);
1115
[email protected]269200b12010-11-18 22:53:061116 // Helper for GenSharedIdsCHROMIUM commands.
1117 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101118 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1119
[email protected]b273e432010-04-12 17:23:581120 // Wrapper for DoGetBooleanv.
1121 void DoGetBooleanv(GLenum pname, GLboolean* params);
1122
1123 // Wrapper for DoGetFloatv.
1124 void DoGetFloatv(GLenum pname, GLfloat* params);
1125
[email protected]36cef8ce2010-03-16 07:34:451126 // Wrapper for glGetFramebufferAttachmentParameteriv.
1127 void DoGetFramebufferAttachmentParameteriv(
1128 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1129
[email protected]a0c3e972010-04-21 00:49:131130 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581131 void DoGetIntegerv(GLenum pname, GLint* params);
1132
[email protected]29a9eb52010-04-13 09:04:231133 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061134 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231135 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1136
[email protected]a0c3e972010-04-21 00:49:131137 // Wrapper for glGetProgramiv.
1138 void DoGetProgramiv(
1139 GLuint program_id, GLenum pname, GLint* params);
1140
[email protected]36cef8ce2010-03-16 07:34:451141 // Wrapper for glRenderbufferParameteriv.
1142 void DoGetRenderbufferParameteriv(
1143 GLenum target, GLenum pname, GLint* params);
1144
[email protected]ddd968b82010-03-02 00:44:291145 // Wrapper for glGetShaderiv
1146 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1147
[email protected]b1122982010-05-17 23:04:241148 // Wrappers for glGetVertexAttrib.
1149 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1150 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1151
[email protected]1958e0e2010-04-22 05:17:151152 // Wrappers for glIsXXX functions.
1153 bool DoIsBuffer(GLuint client_id);
1154 bool DoIsFramebuffer(GLuint client_id);
1155 bool DoIsProgram(GLuint client_id);
1156 bool DoIsRenderbuffer(GLuint client_id);
1157 bool DoIsShader(GLuint client_id);
1158 bool DoIsTexture(GLuint client_id);
1159
[email protected]07f54fcc2009-12-22 02:46:301160 // Wrapper for glLinkProgram
1161 void DoLinkProgram(GLuint program);
1162
[email protected]269200b12010-11-18 22:53:061163 // Helper for RegisterSharedIdsCHROMIUM.
1164 void DoRegisterSharedIdsCHROMIUM(
1165 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101166
[email protected]36cef8ce2010-03-16 07:34:451167 // Wrapper for glRenderbufferStorage.
1168 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031169 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451170
[email protected]8e3e0662010-08-23 18:46:301171 // Wrapper for glRenderbufferStorageMultisampleEXT.
1172 void DoRenderbufferStorageMultisample(
1173 GLenum target, GLsizei samples, GLenum internalformat,
1174 GLsizei width, GLsizei height);
1175
[email protected]b273e432010-04-12 17:23:581176 // Wrapper for glReleaseShaderCompiler.
1177 void DoReleaseShaderCompiler() { }
1178
[email protected]3916c97e2010-02-25 03:20:501179 // Wrappers for glTexParameter functions.
1180 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1181 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1182 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1183 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1184
1185 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1186 // spec only these 2 functions can be used to set sampler uniforms.
1187 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101188 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:361189 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
1190 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
1191 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101192
1193 // Wrappers for glUniformfv because some drivers don't correctly accept
1194 // bool uniforms.
1195 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1196 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1197 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1198 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501199
[email protected]43c2f1f2011-03-25 18:35:361200 void DoUniformMatrix2fv(
1201 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1202 void DoUniformMatrix3fv(
1203 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1204 void DoUniformMatrix4fv(
1205 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1206
[email protected]b1122982010-05-17 23:04:241207 // Wrappers for glVertexAttrib??
1208 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1209 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1210 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1211 void DoVertexAttrib4f(
1212 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1213 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1214 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1215 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1216 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1217
[email protected]07f54fcc2009-12-22 02:46:301218 // Wrapper for glUseProgram
1219 void DoUseProgram(GLuint program);
1220
[email protected]ae51d192010-04-27 00:48:031221 // Wrapper for glValidateProgram.
1222 void DoValidateProgram(GLuint program_client_id);
1223
[email protected]269200b12010-11-18 22:53:061224 void DoCopyTextureToParentTextureCHROMIUM(GLuint client_texture_id,
[email protected]c007aa02010-09-02 22:22:401225 GLuint parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:561226
[email protected]43ecf372010-11-16 19:19:391227 void DoResizeCHROMIUM(GLuint width, GLuint height);
1228
[email protected]4e8a5b122010-05-08 22:00:101229 // Gets the number of values that will be returned by glGetXXX. Returns
1230 // false if pname is unknown.
1231 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1232
[email protected]96449d2c2009-11-25 00:01:321233 // Gets the GLError through our wrapper.
1234 GLenum GetGLError();
1235
1236 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:291237 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:321238
[email protected]07f54fcc2009-12-22 02:46:301239 // Copies the real GL errors to the wrapper. This is so we can
1240 // make sure there are no native GL errors before calling some GL function
1241 // so that on return we know any error generated was for that specific
1242 // command.
1243 void CopyRealGLErrorsToWrapper();
1244
[email protected]6217d392010-03-25 22:08:351245 // Clear all real GL errors. This is to prevent the client from seeing any
1246 // errors caused by GL calls that it was not responsible for issuing.
1247 void ClearRealGLErrors();
1248
[email protected]07f54fcc2009-12-22 02:46:301249 // Checks if the current program and vertex attributes are valid for drawing.
1250 bool IsDrawValid(GLuint max_vertex_accessed);
1251
[email protected]b1122982010-05-17 23:04:241252 // Returns true if attrib0 was simulated.
1253 bool SimulateAttrib0(GLuint max_vertex_accessed);
1254 void RestoreStateForSimulatedAttrib0();
1255
[email protected]ef526492010-06-02 23:12:251256 // Returns true if textures were set.
1257 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501258 void RestoreStateForNonRenderableTextures();
1259
[email protected]8fbedc02010-11-18 18:43:401260 // Returns true if GL_FIXED attribs were simulated.
1261 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1262 void RestoreStateForSimulatedFixedAttribs();
1263
[email protected]07f54fcc2009-12-22 02:46:301264 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501265 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301266 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501267 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1268 bound_array_buffer_ : bound_element_array_buffer_;
1269 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301270 }
1271
[email protected]a93bb842010-02-16 23:03:471272 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501273 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1274 TextureUnit& unit = texture_units_[active_texture_unit_];
1275 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471276 switch (target) {
1277 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501278 info = unit.bound_texture_2d;
1279 break;
[email protected]a93bb842010-02-16 23:03:471280 case GL_TEXTURE_CUBE_MAP:
1281 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1282 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1283 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1284 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1285 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1286 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501287 info = unit.bound_texture_cube_map;
1288 break;
[email protected]1aef98132010-02-23 18:00:071289 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1290 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1291 // because |texture_| is used by the FBO rendering mechanism for readback
1292 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471293 default:
1294 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501295 return NULL;
[email protected]a93bb842010-02-16 23:03:471296 }
[email protected]3916c97e2010-02-25 03:20:501297 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471298 }
1299
[email protected]8e3e0662010-08-23 18:46:301300 // Gets the framebuffer info for a particular target.
1301 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1302 GLenum target) {
1303 FramebufferManager::FramebufferInfo* info = NULL;
1304 switch (target) {
1305 case GL_FRAMEBUFFER:
1306 case GL_DRAW_FRAMEBUFFER:
1307 info = bound_draw_framebuffer_;
1308 break;
1309 case GL_READ_FRAMEBUFFER:
1310 info = bound_read_framebuffer_;
1311 break;
1312 default:
1313 NOTREACHED();
1314 break;
1315 }
1316 return (info && !info->IsDeleted()) ? info : NULL;
1317 }
1318
[email protected]f7b85372010-02-03 01:11:371319 // Validates the program and location for a glGetUniform call and returns
1320 // a SizeResult setup to receive the result. Returns true if glGetUniform
1321 // should be called.
1322 bool GetUniformSetup(
1323 GLuint program, GLint location,
1324 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101325 error::Error* error, GLuint* service_id, void** result,
1326 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371327
[email protected]96449d2c2009-11-25 00:01:321328 // Generate a member function prototype for each command in an automated and
1329 // typesafe way.
1330 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141331 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191332 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321333 const gles2::name& args); \
1334
1335 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1336
1337 #undef GLES2_CMD_OP
1338
[email protected]2f2d7042010-04-14 21:45:581339 // The GL context this decoder renders to on behalf of the client.
[email protected]66791e382010-07-14 20:48:301340 scoped_ptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021341
[email protected]a3ded6d2010-10-19 06:44:391342 // The ContextGroup for this decoder uses to track resources.
1343 ContextGroup::Ref group_;
1344
[email protected]6217d392010-03-25 22:08:351345 // A parent decoder can access this decoders saved offscreen frame buffer.
1346 // The parent pointer is reset if the parent is destroyed.
1347 base::WeakPtr<GLES2DecoderImpl> parent_;
1348
1349 // Width and height to which an offscreen frame buffer should be resized on
1350 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021351 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351352
[email protected]34ff8b0c2010-10-01 20:06:021353 // Current width and height of the offscreen frame buffer.
1354 gfx::Size offscreen_size_;
1355
[email protected]96449d2c2009-11-25 00:01:321356 // Current GL error bits.
1357 uint32 error_bits_;
1358
[email protected]96449d2c2009-11-25 00:01:321359 // Util to help with GL.
1360 GLES2Util util_;
1361
1362 // pack alignment as last set by glPixelStorei
1363 GLint pack_alignment_;
1364
1365 // unpack alignment as last set by glPixelStorei
1366 GLint unpack_alignment_;
1367
1368 // The currently bound array buffer. If this is 0 it is illegal to call
1369 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501370 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321371
1372 // The currently bound element array buffer. If this is 0 it is illegal
1373 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501374 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301375
[email protected]f39f4b3f2010-05-12 17:04:081376 // Class that manages vertex attribs.
1377 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301378
[email protected]b1122982010-05-17 23:04:241379 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1380 GLuint attrib_0_buffer_id_;
1381
1382 // The value currently in attrib_0.
1383 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1384
[email protected]fc753442011-02-04 19:49:491385 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1386 bool attrib_0_buffer_matches_value_;
1387
[email protected]b1122982010-05-17 23:04:241388 // The size of attrib 0.
1389 GLsizei attrib_0_size_;
1390
[email protected]8fbedc02010-11-18 18:43:401391 // The buffer used to simulate GL_FIXED attribs.
1392 GLuint fixed_attrib_buffer_id_;
1393
1394 // The size of fiixed attrib buffer.
1395 GLsizei fixed_attrib_buffer_size_;
1396
[email protected]3916c97e2010-02-25 03:20:501397 // Current active texture by 0 - n index.
1398 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1399 // be 2.
1400 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301401
[email protected]3916c97e2010-02-25 03:20:501402 // Which textures are bound to texture units through glActiveTexture.
1403 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471404
[email protected]3a2e7c7b2010-08-06 01:12:281405 // state saved for clearing so we can clear render buffers and then
1406 // restore to these values.
1407 GLclampf clear_red_;
1408 GLclampf clear_green_;
1409 GLclampf clear_blue_;
1410 GLclampf clear_alpha_;
1411 GLboolean mask_red_;
1412 GLboolean mask_green_;
1413 GLboolean mask_blue_;
1414 GLboolean mask_alpha_;
1415 GLint clear_stencil_;
1416 GLuint mask_stencil_front_;
1417 GLuint mask_stencil_back_;
1418 GLclampf clear_depth_;
1419 GLboolean mask_depth_;
1420 bool enable_scissor_test_;
1421
[email protected]1d32bc82010-01-13 22:06:461422 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501423 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301424
[email protected]8e3e0662010-08-23 18:46:301425 // The currently bound framebuffers
1426 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1427 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561428
1429 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081430 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561431
[email protected]b9363b22010-06-09 22:06:151432 // The offscreen frame buffer that the client renders to. With EGL, the
1433 // depth and stencil buffers are separate. With regular GL there is a single
1434 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1435 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351436 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1437 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021438 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151439 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1440 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021441 GLenum offscreen_target_color_format_;
1442 GLenum offscreen_target_depth_format_;
1443 GLenum offscreen_target_stencil_format_;
1444 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351445
[email protected]a3a93e7b2010-08-28 00:48:561446 GLuint copy_texture_to_parent_texture_fb_;
1447
[email protected]34ff8b0c2010-10-01 20:06:021448 // The copy that is saved when SwapBuffers is called. It is also
1449 // used as the destination for multi-sample resolves.
1450 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351451 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]97872062010-11-03 19:07:051452 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351453
[email protected]7ff86b92010-11-25 17:50:001454 scoped_ptr<Callback1<gfx::Size>::Type> resize_callback_;
[email protected]43f28f832010-02-03 02:28:481455 scoped_ptr<Callback0::Type> swap_buffers_callback_;
[email protected]80c49752011-04-18 23:55:101456 base::Callback<void(bool)> latch_callback_;
[email protected]43f28f832010-02-03 02:28:481457
[email protected]32fe9aa2011-01-21 23:47:131458 // The format of the back buffer_
1459 GLenum back_buffer_color_format_;
1460
[email protected]8eee29c2010-04-29 03:38:291461 // The last error message set.
1462 std::string last_error_;
1463
[email protected]a3a93e7b2010-08-28 00:48:561464 // The current decoder error.
1465 error::Error current_decoder_error_;
1466
[email protected]b1d2dcb2010-05-17 19:24:181467 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451468 scoped_ptr<ShaderTranslator> vertex_translator_;
1469 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181470
[email protected]c410da802011-03-14 19:17:411471 DisallowedExtensions disallowed_extensions_;
1472
[email protected]915a59a12010-09-30 21:29:111473 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051474 const Validators* validators_;
[email protected]915a59a12010-09-30 21:29:111475 FeatureInfo* feature_info_;
[email protected]9438b012010-06-15 22:55:051476
[email protected]b493ee622011-04-13 23:52:001477 // This indicates all the following texSubImage2D calls that are part of the
1478 // failed texImage2D call should be ignored.
1479 bool tex_image_2d_failed_;
1480
[email protected]65225772011-05-12 21:10:241481 int frame_number_;
1482
[email protected]96449d2c2009-11-25 00:01:321483 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1484};
1485
[email protected]6217d392010-03-25 22:08:351486ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1487 : decoder_(decoder) {
1488 decoder_->CopyRealGLErrorsToWrapper();
1489}
1490
1491ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1492 decoder_->ClearRealGLErrors();
1493}
1494
1495ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1496 GLuint id)
1497 : decoder_(decoder) {
1498 ScopedGLErrorSuppressor suppressor(decoder_);
1499
1500 // TODO(apatrick): Check if there are any other states that need to be reset
1501 // before binding a new texture.
1502 glActiveTexture(GL_TEXTURE0);
1503 glBindTexture(GL_TEXTURE_2D, id);
1504}
1505
1506ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1507 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301508 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351509}
1510
1511ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1512 GLuint id)
1513 : decoder_(decoder) {
1514 ScopedGLErrorSuppressor suppressor(decoder_);
1515 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1516}
1517
1518ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1519 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301520 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351521}
1522
1523ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1524 GLuint id)
1525 : decoder_(decoder) {
1526 ScopedGLErrorSuppressor suppressor(decoder_);
1527 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1528}
1529
1530ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1531 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301532 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351533}
1534
[email protected]34ff8b0c2010-10-01 20:06:021535ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]c0701082011-04-20 00:34:521536 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer)
1537 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021538 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1539 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521540 (!decoder_->bound_read_framebuffer_.get() ||
1541 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021542 if (!resolve_and_bind_)
1543 return;
1544
1545 ScopedGLErrorSuppressor suppressor(decoder_);
1546 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1547 decoder_->offscreen_target_frame_buffer_->id());
1548 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT,
1549 decoder_->offscreen_saved_frame_buffer_->id());
1550 const int width = decoder_->offscreen_size_.width();
1551 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181552 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021553 if (IsAngle()) {
1554 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1555 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1556 } else {
1557 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1558 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1559 }
1560 glBindFramebufferEXT(GL_FRAMEBUFFER,
1561 decoder_->offscreen_saved_frame_buffer_->id());
1562}
1563
1564ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1565 if (!resolve_and_bind_)
1566 return;
1567
1568 ScopedGLErrorSuppressor suppressor(decoder_);
1569 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181570 if (decoder_->enable_scissor_test_) {
1571 glEnable(GL_SCISSOR_TEST);
1572 }
[email protected]34ff8b0c2010-10-01 20:06:021573}
1574
[email protected]6217d392010-03-25 22:08:351575Texture::Texture(GLES2DecoderImpl* decoder)
1576 : decoder_(decoder),
1577 id_(0) {
1578}
1579
1580Texture::~Texture() {
1581 // This does not destroy the render texture because that would require that
1582 // the associated GL context was current. Just check that it was explicitly
1583 // destroyed.
1584 DCHECK_EQ(id_, 0u);
1585}
1586
1587void Texture::Create() {
1588 ScopedGLErrorSuppressor suppressor(decoder_);
1589 Destroy();
1590 glGenTextures(1, &id_);
1591}
1592
[email protected]34ff8b0c2010-10-01 20:06:021593bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351594 DCHECK_NE(id_, 0u);
1595 ScopedGLErrorSuppressor suppressor(decoder_);
1596 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]8c515f82010-11-09 03:40:041597 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1598 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1599 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1600 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351601
1602 glTexImage2D(GL_TEXTURE_2D,
1603 0, // mip level
[email protected]34ff8b0c2010-10-01 20:06:021604 format,
[email protected]6217d392010-03-25 22:08:351605 size.width(),
1606 size.height(),
1607 0, // border
[email protected]34ff8b0c2010-10-01 20:06:021608 format,
[email protected]6217d392010-03-25 22:08:351609 GL_UNSIGNED_BYTE,
1610 NULL);
1611
[email protected]d37231fa2010-04-09 21:16:021612 size_ = size;
1613
[email protected]6217d392010-03-25 22:08:351614 return glGetError() == GL_NO_ERROR;
1615}
1616
1617void Texture::Copy(const gfx::Size& size) {
1618 DCHECK_NE(id_, 0u);
1619 ScopedGLErrorSuppressor suppressor(decoder_);
1620 ScopedTexture2DBinder binder(decoder_, id_);
1621 glCopyTexImage2D(GL_TEXTURE_2D,
1622 0, // level
1623 GL_RGBA,
1624 0, 0,
1625 size.width(),
1626 size.height(),
1627 0); // border
1628}
1629
1630void Texture::Destroy() {
1631 if (id_ != 0) {
1632 ScopedGLErrorSuppressor suppressor(decoder_);
1633 glDeleteTextures(1, &id_);
1634 id_ = 0;
1635 }
1636}
1637
[email protected]97872062010-11-03 19:07:051638void Texture::Invalidate() {
1639 id_ = 0;
1640}
1641
[email protected]6217d392010-03-25 22:08:351642RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1643 : decoder_(decoder),
1644 id_(0) {
1645}
1646
1647RenderBuffer::~RenderBuffer() {
1648 // This does not destroy the render buffer because that would require that
1649 // the associated GL context was current. Just check that it was explicitly
1650 // destroyed.
1651 DCHECK_EQ(id_, 0u);
1652}
1653
1654void RenderBuffer::Create() {
1655 ScopedGLErrorSuppressor suppressor(decoder_);
1656 Destroy();
1657 glGenRenderbuffersEXT(1, &id_);
1658}
1659
[email protected]34ff8b0c2010-10-01 20:06:021660bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1661 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351662 ScopedGLErrorSuppressor suppressor(decoder_);
1663 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021664 if (samples <= 1) {
1665 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1666 format,
1667 size.width(),
1668 size.height());
1669 } else {
1670 if (IsAngle()) {
1671 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1672 samples,
1673 format,
1674 size.width(),
1675 size.height());
1676 } else {
1677 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1678 samples,
1679 format,
1680 size.width(),
1681 size.height());
1682 }
1683 }
[email protected]6217d392010-03-25 22:08:351684 return glGetError() == GL_NO_ERROR;
1685}
1686
1687void RenderBuffer::Destroy() {
1688 if (id_ != 0) {
1689 ScopedGLErrorSuppressor suppressor(decoder_);
1690 glDeleteRenderbuffersEXT(1, &id_);
1691 id_ = 0;
1692 }
1693}
1694
[email protected]97872062010-11-03 19:07:051695void RenderBuffer::Invalidate() {
1696 id_ = 0;
1697}
1698
[email protected]6217d392010-03-25 22:08:351699FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1700 : decoder_(decoder),
1701 id_(0) {
1702}
1703
1704FrameBuffer::~FrameBuffer() {
1705 // This does not destroy the frame buffer because that would require that
1706 // the associated GL context was current. Just check that it was explicitly
1707 // destroyed.
1708 DCHECK_EQ(id_, 0u);
1709}
1710
1711void FrameBuffer::Create() {
1712 ScopedGLErrorSuppressor suppressor(decoder_);
1713 Destroy();
1714 glGenFramebuffersEXT(1, &id_);
1715}
1716
1717void FrameBuffer::AttachRenderTexture(Texture* texture) {
1718 DCHECK_NE(id_, 0u);
1719 ScopedGLErrorSuppressor suppressor(decoder_);
1720 ScopedFrameBufferBinder binder(decoder_, id_);
1721 GLuint attach_id = texture ? texture->id() : 0;
1722 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1723 GL_COLOR_ATTACHMENT0,
1724 GL_TEXTURE_2D,
1725 attach_id,
1726 0);
1727}
1728
[email protected]b9363b22010-06-09 22:06:151729void FrameBuffer::AttachRenderBuffer(GLenum target,
1730 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351731 DCHECK_NE(id_, 0u);
1732 ScopedGLErrorSuppressor suppressor(decoder_);
1733 ScopedFrameBufferBinder binder(decoder_, id_);
1734 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1735 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151736 target,
[email protected]6217d392010-03-25 22:08:351737 GL_RENDERBUFFER,
1738 attach_id);
1739}
1740
1741void FrameBuffer::Clear(GLbitfield buffers) {
1742 ScopedGLErrorSuppressor suppressor(decoder_);
1743 ScopedFrameBufferBinder binder(decoder_, id_);
1744 glClear(buffers);
1745}
1746
1747void FrameBuffer::Destroy() {
1748 if (id_ != 0) {
1749 ScopedGLErrorSuppressor suppressor(decoder_);
1750 glDeleteFramebuffersEXT(1, &id_);
1751 id_ = 0;
1752 }
1753}
1754
[email protected]97872062010-11-03 19:07:051755void FrameBuffer::Invalidate() {
1756 id_ = 0;
1757}
1758
[email protected]6217d392010-03-25 22:08:351759GLenum FrameBuffer::CheckStatus() {
1760 DCHECK_NE(id_, 0u);
1761 ScopedGLErrorSuppressor suppressor(decoder_);
1762 ScopedFrameBufferBinder binder(decoder_, id_);
1763 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1764}
1765
[email protected]3916c97e2010-02-25 03:20:501766GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1767 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321768}
1769
[email protected]3916c97e2010-02-25 03:20:501770GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391771 : GLES2Decoder(),
1772 group_(ContextGroup::Ref(group ? group : new ContextGroup())),
[email protected]96449d2c2009-11-25 00:01:321773 error_bits_(0),
1774 util_(0), // TODO(gman): Set to actual num compress texture formats.
1775 pack_alignment_(4),
1776 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241777 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491778 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241779 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401780 fixed_attrib_buffer_id_(0),
1781 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501782 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281783 clear_red_(0),
1784 clear_green_(0),
1785 clear_blue_(0),
1786 clear_alpha_(0),
1787 mask_red_(true),
1788 mask_green_(true),
1789 mask_blue_(true),
1790 mask_alpha_(true),
1791 clear_stencil_(0),
1792 mask_stencil_front_(-1),
1793 mask_stencil_back_(-1),
1794 clear_depth_(1.0f),
1795 mask_depth_(true),
1796 enable_scissor_test_(false),
[email protected]34ff8b0c2010-10-01 20:06:021797 offscreen_target_color_format_(0),
1798 offscreen_target_depth_format_(0),
1799 offscreen_target_stencil_format_(0),
1800 offscreen_target_samples_(0),
[email protected]5ea88812011-03-28 10:45:391801 copy_texture_to_parent_texture_fb_(0),
[email protected]97872062010-11-03 19:07:051802 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:131803 back_buffer_color_format_(0),
[email protected]a3a93e7b2010-08-28 00:48:561804 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051805 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111806 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001807 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241808 tex_image_2d_failed_(false),
1809 frame_number_(0) {
[email protected]b1122982010-05-17 23:04:241810 attrib_0_value_.v[0] = 0.0f;
1811 attrib_0_value_.v[1] = 0.0f;
1812 attrib_0_value_.v[2] = 0.0f;
1813 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151814
[email protected]c2f8c8402010-12-06 18:07:241815 // The shader translator is used for WebGL even when running on EGL
1816 // because additional restrictions are needed (like only enabling
1817 // GL_OES_standard_derivatives on demand). It is used for the unit
1818 // tests because
1819 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1820 // empty string to CompileShader and this is not a valid shader.
1821 // TODO(apatrick): fix this test.
1822 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1823 !feature_info_->feature_flags().chromium_webglsl) ||
[email protected]b9363b22010-06-09 22:06:151824 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1825 use_shader_translator_ = false;
1826 }
[email protected]96449d2c2009-11-25 00:01:321827}
1828
[email protected]c410da802011-03-14 19:17:411829bool GLES2DecoderImpl::Initialize(
1830 gfx::GLContext* context,
1831 const gfx::Size& size,
1832 const DisallowedExtensions& disallowed_extensions,
1833 const char* allowed_extensions,
1834 const std::vector<int32>& attribs,
1835 GLES2Decoder* parent,
1836 uint32 parent_client_texture_id) {
[email protected]4bedba72010-04-20 22:08:541837 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301838 DCHECK(!context_.get());
1839
1840 // Take ownership of the GLContext.
1841 context_.reset(context);
[email protected]d37231fa2010-04-09 21:16:021842
[email protected]6217d392010-03-25 22:08:351843 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021844 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351845 if (parent)
1846 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1847
[email protected]246a70452010-03-05 21:53:501848 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011849 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1850 << "MakeCurrent failed.";
[email protected]246a70452010-03-05 21:53:501851 Destroy();
1852 return false;
[email protected]eb54a562010-01-20 21:55:181853 }
1854
[email protected]c410da802011-03-14 19:17:411855 if (!group_->Initialize(disallowed_extensions, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221856 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391857 << "failed to initialize.";
1858 Destroy();
[email protected]ae1741092010-11-17 19:16:031859 return false;
[email protected]a3ded6d2010-10-19 06:44:391860 }
1861
[email protected]246a70452010-03-05 21:53:501862 CHECK_GL_ERROR();
[email protected]c410da802011-03-14 19:17:411863 disallowed_extensions_ = disallowed_extensions;
[email protected]246a70452010-03-05 21:53:501864
[email protected]f39f4b3f2010-05-12 17:04:081865 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321866
[email protected]32fe9aa2011-01-21 23:47:131867 GLint v = 0;
1868 glGetIntegerv(GL_ALPHA_BITS, &v);
1869 back_buffer_color_format_ = v ? GL_RGBA : GL_RGB;
1870
[email protected]1071e572011-02-09 20:00:121871 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1872 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1873 // OpenGL ES 2.0 does not have this issue.
1874 glEnableVertexAttribArray(0);
1875 }
[email protected]b1122982010-05-17 23:04:241876 glGenBuffersARB(1, &attrib_0_buffer_id_);
1877 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1878 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1879 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401880 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081881
[email protected]246a70452010-03-05 21:53:501882 texture_units_.reset(
1883 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151884 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491885 glActiveTexture(GL_TEXTURE0 + tt);
1886 // Do cube map first because we want the last bind to be 2D.
1887 TextureManager::TextureInfo* info =
[email protected]1958e0e2010-04-22 05:17:151888 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491889 texture_units_[tt].bound_texture_cube_map = info;
1890 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1891 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1892 texture_units_[tt].bound_texture_2d = info;
1893 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151894 }
[email protected]00f893d2010-08-24 18:55:491895 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501896 CHECK_GL_ERROR();
1897
[email protected]d37231fa2010-04-09 21:16:021898 if (context_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:021899 ContextCreationAttribParser attrib_parser;
1900 if (!attrib_parser.Parse(attribs))
1901 return false;
1902
1903 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:541904 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:021905 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
1906 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:431907 // max_sample_count must be initialized to a sane value. If
1908 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
1909 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:021910 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
1911 offscreen_target_samples_ = std::min(attrib_parser.samples_,
1912 max_sample_count);
1913 } else {
1914 offscreen_target_samples_ = 1;
1915 }
1916
1917 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1918 const bool rgb8_supported =
1919 context_->HasExtension("GL_OES_rgb8_rgba8");
1920 // The only available default render buffer formats in GLES2 have very
1921 // little precision. Don't enable multisampling unless 8-bit render
1922 // buffer formats are available--instead fall back to 8-bit textures.
1923 if (rgb8_supported && offscreen_target_samples_ > 1) {
1924 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1925 GL_RGBA8 : GL_RGB8;
1926 } else {
1927 offscreen_target_samples_ = 1;
1928 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1929 GL_RGBA : GL_RGB;
1930 }
1931
1932 // ANGLE only supports packed depth/stencil formats, so use it if it is
1933 // available.
1934 const bool depth24_stencil8_supported =
1935 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271936 VLOG(1) << "GL_OES_packed_depth_stencil "
1937 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:001938 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1939 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021940 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1941 offscreen_target_stencil_format_ = 0;
1942 } else {
1943 // It may be the case that this depth/stencil combination is not
1944 // supported, but this will be checked later by CheckFramebufferStatus.
1945 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1946 GL_DEPTH_COMPONENT16 : 0;
1947 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1948 GL_STENCIL_INDEX8 : 0;
1949 }
1950 } else {
1951 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1952 GL_RGBA : GL_RGB;
1953
1954 // If depth is requested at all, use the packed depth stencil format if
1955 // it's available, as some desktop GL drivers don't support any non-packed
1956 // formats for depth attachments.
1957 const bool depth24_stencil8_supported =
1958 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271959 VLOG(1) << "GL_EXT_packed_depth_stencil "
1960 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:021961
[email protected]71ee3642010-10-14 18:08:001962 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1963 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021964 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1965 offscreen_target_stencil_format_ = 0;
1966 } else {
1967 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1968 GL_DEPTH_COMPONENT : 0;
1969 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1970 GL_STENCIL_INDEX : 0;
1971 }
1972 }
1973
[email protected]97872062010-11-03 19:07:051974 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
1975 GL_RGBA : GL_RGB;
1976
[email protected]6217d392010-03-25 22:08:351977 // Create the target frame buffer. This is the one that the client renders
1978 // directly to.
1979 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1980 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021981 // Due to GLES2 format limitations, either the color texture (for
1982 // non-multisampling) or the color render buffer (for multisampling) will be
1983 // attached to the offscreen frame buffer. The render buffer has more
1984 // limited formats available to it, but the texture can't do multisampling.
1985 if (IsOffscreenBufferMultisampled()) {
1986 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
1987 offscreen_target_color_render_buffer_->Create();
1988 } else {
1989 offscreen_target_color_texture_.reset(new Texture(this));
1990 offscreen_target_color_texture_->Create();
1991 }
1992 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151993 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021994 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151995 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:351996
1997 // Create the saved offscreen texture. The target frame buffer is copied
1998 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021999 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2000 offscreen_saved_frame_buffer_->Create();
2001 //
[email protected]6217d392010-03-25 22:08:352002 offscreen_saved_color_texture_.reset(new Texture(this));
2003 offscreen_saved_color_texture_->Create();
2004
[email protected]6217d392010-03-25 22:08:352005 // Map the ID of the saved offscreen texture into the parent so that
2006 // it can reference it.
2007 if (parent_) {
2008 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]6217d392010-03-25 22:08:352009 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:032010 parent_->CreateTextureInfo(parent_client_texture_id, service_id);
[email protected]4874aae2011-03-18 01:19:562011 info->SetNotOwned();
[email protected]6217d392010-03-25 22:08:352012 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
2013 }
2014
2015 // Allocate the render buffers at their initial size and check the status
2016 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:022017 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352018 if (!UpdateOffscreenFrameBufferSize()) {
[email protected]d0498742010-09-20 20:27:012019 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352020 Destroy();
2021 return false;
2022 }
2023
2024 // Bind to the new default frame buffer (the offscreen target frame buffer).
2025 // This should now be associated with ID zero.
2026 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]a3a93e7b2010-08-28 00:48:562027
2028 glGenFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:352029 }
2030
[email protected]76a0ee102010-04-07 21:03:042031 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2032 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2033 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372034 // mailing list archives. It also implicitly enables the desktop GL
2035 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2036 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152037 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2038 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372039 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152040 }
[email protected]de17df392010-04-23 21:09:412041
[email protected]c2f8c8402010-12-06 18:07:242042 if (!InitializeShaderTranslator()) {
2043 return false;
[email protected]de17df392010-04-23 21:09:412044 }
[email protected]76a0ee102010-04-07 21:03:042045
[email protected]246a70452010-03-05 21:53:502046 return true;
[email protected]96449d2c2009-11-25 00:01:322047}
2048
[email protected]c2f8c8402010-12-06 18:07:242049bool GLES2DecoderImpl::InitializeShaderTranslator() {
2050 // Re-check the state of use_shader_translator_ each time this is called.
2051 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
2052 feature_info_->feature_flags().chromium_webglsl &&
2053 !use_shader_translator_) {
2054 use_shader_translator_ = true;
2055 }
2056 if (!use_shader_translator_) {
2057 return true;
2058 }
2059 ShBuiltInResources resources;
2060 ShInitBuiltInResources(&resources);
2061 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2062 resources.MaxVertexUniformVectors =
2063 group_->max_vertex_uniform_vectors();
2064 resources.MaxVaryingVectors = group_->max_varying_vectors();
2065 resources.MaxVertexTextureImageUnits =
2066 group_->max_vertex_texture_image_units();
2067 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2068 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2069 resources.MaxFragmentUniformVectors =
2070 group_->max_fragment_uniform_vectors();
2071 resources.MaxDrawBuffers = 1;
2072 resources.OES_standard_derivatives =
2073 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
2074 vertex_translator_.reset(new ShaderTranslator);
2075 ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ?
2076 SH_WEBGL_SPEC : SH_GLES2_SPEC;
2077 bool is_glsl_es =
2078 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
2079 if (!vertex_translator_->Init(
2080 SH_VERTEX_SHADER, shader_spec, &resources, is_glsl_es)) {
2081 LOG(ERROR) << "Could not initialize vertex shader translator.";
2082 Destroy();
2083 return false;
2084 }
2085 fragment_translator_.reset(new ShaderTranslator);
2086 if (!fragment_translator_->Init(
2087 SH_FRAGMENT_SHADER, shader_spec, &resources, is_glsl_es)) {
2088 LOG(ERROR) << "Could not initialize fragment shader translator.";
2089 Destroy();
2090 return false;
2091 }
2092 return true;
2093}
2094
[email protected]ae51d192010-04-27 00:48:032095bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472096 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032097 if (GetBufferInfo(client_ids[ii])) {
2098 return false;
2099 }
2100 }
2101 scoped_array<GLuint> service_ids(new GLuint[n]);
2102 glGenBuffersARB(n, service_ids.get());
2103 for (GLsizei ii = 0; ii < n; ++ii) {
2104 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2105 }
2106 return true;
2107}
2108
2109bool GLES2DecoderImpl::GenFramebuffersHelper(
2110 GLsizei n, const GLuint* client_ids) {
2111 for (GLsizei ii = 0; ii < n; ++ii) {
2112 if (GetFramebufferInfo(client_ids[ii])) {
2113 return false;
2114 }
2115 }
2116 scoped_array<GLuint> service_ids(new GLuint[n]);
2117 glGenFramebuffersEXT(n, service_ids.get());
2118 for (GLsizei ii = 0; ii < n; ++ii) {
2119 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2120 }
2121 return true;
2122}
2123
2124bool GLES2DecoderImpl::GenRenderbuffersHelper(
2125 GLsizei n, const GLuint* client_ids) {
2126 for (GLsizei ii = 0; ii < n; ++ii) {
2127 if (GetRenderbufferInfo(client_ids[ii])) {
2128 return false;
2129 }
2130 }
2131 scoped_array<GLuint> service_ids(new GLuint[n]);
2132 glGenRenderbuffersEXT(n, service_ids.get());
2133 for (GLsizei ii = 0; ii < n; ++ii) {
2134 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2135 }
2136 return true;
2137}
2138
2139bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2140 for (GLsizei ii = 0; ii < n; ++ii) {
2141 if (GetTextureInfo(client_ids[ii])) {
2142 return false;
2143 }
2144 }
2145 scoped_array<GLuint> service_ids(new GLuint[n]);
2146 glGenTextures(n, service_ids.get());
2147 for (GLsizei ii = 0; ii < n; ++ii) {
2148 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2149 }
2150 return true;
2151}
2152
2153void GLES2DecoderImpl::DeleteBuffersHelper(
2154 GLsizei n, const GLuint* client_ids) {
2155 for (GLsizei ii = 0; ii < n; ++ii) {
2156 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
2157 if (info) {
2158 GLuint service_id = info->service_id();
2159 glDeleteBuffersARB(1, &service_id);
2160 RemoveBufferInfo(client_ids[ii]);
2161 }
[email protected]a93bb842010-02-16 23:03:472162 }
[email protected]07f54fcc2009-12-22 02:46:302163}
2164
[email protected]ae51d192010-04-27 00:48:032165void GLES2DecoderImpl::DeleteFramebuffersHelper(
2166 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582167 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032168 FramebufferManager::FramebufferInfo* info =
2169 GetFramebufferInfo(client_ids[ii]);
2170 if (info) {
2171 GLuint service_id = info->service_id();
2172 glDeleteFramebuffersEXT(1, &service_id);
2173 RemoveFramebufferInfo(client_ids[ii]);
2174 }
[email protected]a25fa872010-03-25 02:57:582175 }
[email protected]07f54fcc2009-12-22 02:46:302176}
2177
[email protected]ae51d192010-04-27 00:48:032178void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2179 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582180 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032181 RenderbufferManager::RenderbufferInfo* info =
2182 GetRenderbufferInfo(client_ids[ii]);
2183 if (info) {
2184 GLuint service_id = info->service_id();
2185 glDeleteRenderbuffersEXT(1, &service_id);
2186 RemoveRenderbufferInfo(client_ids[ii]);
2187 }
[email protected]a25fa872010-03-25 02:57:582188 }
[email protected]07f54fcc2009-12-22 02:46:302189}
2190
[email protected]ae51d192010-04-27 00:48:032191void GLES2DecoderImpl::DeleteTexturesHelper(
2192 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472193 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032194 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
2195 if (info) {
2196 GLuint service_id = info->service_id();
2197 glDeleteTextures(1, &service_id);
2198 RemoveTextureInfo(client_ids[ii]);
2199 }
[email protected]a93bb842010-02-16 23:03:472200 }
[email protected]07f54fcc2009-12-22 02:46:302201}
2202
[email protected]43f28f832010-02-03 02:28:482203// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322204
[email protected]eb54a562010-01-20 21:55:182205bool GLES2DecoderImpl::MakeCurrent() {
[email protected]66791e382010-07-14 20:48:302206 return context_.get() ? context_->MakeCurrent() : false;
[email protected]eb54a562010-01-20 21:55:182207}
2208
[email protected]8e3e0662010-08-23 18:46:302209void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2210 glBindRenderbufferEXT(
2211 GL_RENDERBUFFER,
2212 bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
2213}
2214
2215static void RebindCurrentFramebuffer(
2216 GLenum target,
2217 FramebufferManager::FramebufferInfo* info,
2218 FrameBuffer* offscreen_frame_buffer) {
2219 GLuint framebuffer_id = info ? info->service_id() : 0;
2220 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2221 framebuffer_id = offscreen_frame_buffer->id();
2222 }
2223 glBindFramebufferEXT(target, framebuffer_id);
2224}
2225
2226void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]a3ded6d2010-10-19 06:44:392227 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302228 RebindCurrentFramebuffer(
2229 GL_FRAMEBUFFER,
2230 bound_draw_framebuffer_.get(),
2231 offscreen_target_frame_buffer_.get());
2232 } else {
2233 RebindCurrentFramebuffer(
2234 GL_READ_FRAMEBUFFER_EXT,
2235 bound_read_framebuffer_.get(),
2236 offscreen_target_frame_buffer_.get());
2237 RebindCurrentFramebuffer(
2238 GL_DRAW_FRAMEBUFFER_EXT,
2239 bound_draw_framebuffer_.get(),
2240 offscreen_target_frame_buffer_.get());
2241 }
2242}
2243
2244void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2245 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2246 GLuint last_id;
2247 if (info.bound_texture_2d) {
2248 last_id = info.bound_texture_2d->service_id();
2249 } else {
2250 last_id = 0;
2251 }
2252
2253 glBindTexture(GL_TEXTURE_2D, last_id);
2254 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2255}
2256
[email protected]3a03a8f2011-03-19 00:51:272257bool GLES2DecoderImpl::CheckFramebufferComplete(const char* func_name) {
2258 if (bound_draw_framebuffer_ && bound_draw_framebuffer_->IsNotComplete()) {
[email protected]be45d7c2011-04-15 18:03:352259 SetGLError(GL_INVALID_FRAMEBUFFER_OPERATION,
[email protected]3a03a8f2011-03-19 00:51:272260 (std::string(func_name) + " framebuffer incomplete").c_str());
2261 return false;
2262 }
2263 return true;
2264}
2265
[email protected]8e3e0662010-08-23 18:46:302266gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2267 if (bound_read_framebuffer_ != 0) {
[email protected]9edc6b22010-12-23 02:00:262268 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2269 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2270 if (attachment) {
2271 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502272 }
[email protected]9edc6b22010-12-23 02:00:262273 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022274 } else if (offscreen_target_frame_buffer_.get()) {
2275 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352276 } else {
[email protected]d37231fa2010-04-09 21:16:022277 return context_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022278 }
[email protected]246a70452010-03-05 21:53:502279}
2280
[email protected]9edc6b22010-12-23 02:00:262281GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
2282 if (bound_read_framebuffer_ != 0) {
2283 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2284 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2285 if (attachment) {
2286 return attachment->internal_format();
2287 }
2288 return 0;
2289 } else if (offscreen_target_frame_buffer_.get()) {
2290 return offscreen_target_color_format_;
2291 } else {
[email protected]32fe9aa2011-01-21 23:47:132292 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262293 }
2294}
2295
[email protected]6217d392010-03-25 22:08:352296bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]34ff8b0c2010-10-01 20:06:022297 if (offscreen_size_ == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:352298 return true;
2299
[email protected]34ff8b0c2010-10-01 20:06:022300 offscreen_size_ = pending_offscreen_size_;
[email protected]a470d612011-02-25 04:15:002301 int w = offscreen_size_.width();
2302 int h = offscreen_size_.height();
2303 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2304 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2305 << "to allocate storage due to excessive dimensions.";
2306 return false;
2307 }
[email protected]34ff8b0c2010-10-01 20:06:022308
[email protected]6217d392010-03-25 22:08:352309 // Reallocate the offscreen target buffers.
[email protected]34ff8b0c2010-10-01 20:06:022310 DCHECK(offscreen_target_color_format_);
2311 if (IsOffscreenBufferMultisampled()) {
2312 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2313 pending_offscreen_size_, offscreen_target_color_format_,
2314 offscreen_target_samples_)) {
2315 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2316 << "to allocate storage for offscreen target color buffer.";
2317 return false;
2318 }
2319 } else {
2320 if (!offscreen_target_color_texture_->AllocateStorage(
2321 pending_offscreen_size_, offscreen_target_color_format_)) {
2322 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2323 << "to allocate storage for offscreen target color texture.";
2324 return false;
2325 }
2326 }
2327 if (offscreen_target_depth_format_ &&
2328 !offscreen_target_depth_render_buffer_->AllocateStorage(
2329 pending_offscreen_size_, offscreen_target_depth_format_,
2330 offscreen_target_samples_)) {
[email protected]d0498742010-09-20 20:27:012331 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
[email protected]34ff8b0c2010-10-01 20:06:022332 << "to allocate storage for offscreen target depth buffer.";
2333 return false;
2334 }
2335 if (offscreen_target_stencil_format_ &&
2336 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2337 pending_offscreen_size_, offscreen_target_stencil_format_,
2338 offscreen_target_samples_)) {
2339 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2340 << "to allocate storage for offscreen target stencil buffer.";
[email protected]6217d392010-03-25 22:08:352341 return false;
2342 }
2343
[email protected]2f2d7042010-04-14 21:45:582344 // Attach the offscreen target buffers to the target frame buffer.
[email protected]34ff8b0c2010-10-01 20:06:022345 if (IsOffscreenBufferMultisampled()) {
[email protected]b9363b22010-06-09 22:06:152346 offscreen_target_frame_buffer_->AttachRenderBuffer(
[email protected]34ff8b0c2010-10-01 20:06:022347 GL_COLOR_ATTACHMENT0,
2348 offscreen_target_color_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152349 } else {
[email protected]34ff8b0c2010-10-01 20:06:022350 offscreen_target_frame_buffer_->AttachRenderTexture(
2351 offscreen_target_color_texture_.get());
2352 }
2353 if (offscreen_target_depth_format_) {
2354 offscreen_target_frame_buffer_->AttachRenderBuffer(
2355 GL_DEPTH_ATTACHMENT,
2356 offscreen_target_depth_render_buffer_.get());
2357 }
2358 const bool packed_depth_stencil =
2359 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2360 if (packed_depth_stencil) {
[email protected]b9363b22010-06-09 22:06:152361 offscreen_target_frame_buffer_->AttachRenderBuffer(
2362 GL_STENCIL_ATTACHMENT,
2363 offscreen_target_depth_render_buffer_.get());
[email protected]34ff8b0c2010-10-01 20:06:022364 } else if (offscreen_target_stencil_format_) {
2365 offscreen_target_frame_buffer_->AttachRenderBuffer(
2366 GL_STENCIL_ATTACHMENT,
2367 offscreen_target_stencil_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152368 }
[email protected]34ff8b0c2010-10-01 20:06:022369
[email protected]6217d392010-03-25 22:08:352370 if (offscreen_target_frame_buffer_->CheckStatus() !=
2371 GL_FRAMEBUFFER_COMPLETE) {
[email protected]d0498742010-09-20 20:27:012372 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2373 << "because offscreen FBO was incomplete.";
[email protected]6217d392010-03-25 22:08:352374 return false;
2375 }
2376
[email protected]c007aa02010-09-02 22:22:402377 // Clear the target frame buffer.
2378 {
2379 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]3f0add5e2010-09-13 20:16:282380 glClearColor(0, 0, 0, 0);
[email protected]c007aa02010-09-02 22:22:402381 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2382 glClearStencil(0);
2383 glStencilMaskSeparate(GL_FRONT, GL_TRUE);
2384 glStencilMaskSeparate(GL_BACK, GL_TRUE);
2385 glClearDepth(0);
2386 glDepthMask(GL_TRUE);
2387 glDisable(GL_SCISSOR_TEST);
[email protected]2f2d7042010-04-14 21:45:582388 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402389 RestoreClearState();
[email protected]2f2d7042010-04-14 21:45:582390 }
[email protected]2f2d7042010-04-14 21:45:582391
[email protected]34ff8b0c2010-10-01 20:06:022392 if (parent_ || IsOffscreenBufferMultisampled()) {
[email protected]97872062010-11-03 19:07:052393 DCHECK(offscreen_saved_color_format_);
2394 offscreen_saved_color_texture_->AllocateStorage(
2395 pending_offscreen_size_, offscreen_saved_color_format_);
[email protected]d37231fa2010-04-09 21:16:022396
[email protected]34ff8b0c2010-10-01 20:06:022397 offscreen_saved_frame_buffer_->AttachRenderTexture(
2398 offscreen_saved_color_texture_.get());
2399 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2400 GL_FRAMEBUFFER_COMPLETE) {
2401 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2402 << "because offscreen saved FBO was incomplete.";
2403 return false;
2404 }
2405 }
2406
2407 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582408 // Update the info about the offscreen saved color texture in the parent.
2409 // The reference to the parent is a weak pointer and will become null if the
2410 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352411 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142412 GLuint client_id;
[email protected]262d7aa2010-12-03 22:07:292413 TextureManager* parent_texture_manager = parent_->texture_manager();
2414 CHECK(parent_texture_manager->GetClientId(service_id, &client_id));
[email protected]8d25d042010-06-16 19:48:142415 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352416 DCHECK(info);
2417
[email protected]262d7aa2010-12-03 22:07:292418 parent_texture_manager->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:112419 feature_info_,
[email protected]ef526492010-06-02 23:12:252420 info,
2421 GL_TEXTURE_2D,
2422 0, // level
2423 GL_RGBA,
2424 pending_offscreen_size_.width(),
2425 pending_offscreen_size_.height(),
2426 1, // depth
2427 0, // border
2428 GL_RGBA,
2429 GL_UNSIGNED_BYTE);
[email protected]262d7aa2010-12-03 22:07:292430 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042431 feature_info_,
2432 info,
2433 GL_TEXTURE_MAG_FILTER,
2434 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292435 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042436 feature_info_,
2437 info,
2438 GL_TEXTURE_MIN_FILTER,
2439 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292440 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042441 feature_info_,
2442 info,
2443 GL_TEXTURE_WRAP_S,
2444 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292445 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042446 feature_info_,
2447 info,
2448 GL_TEXTURE_WRAP_T,
2449 GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:352450
[email protected]c007aa02010-09-02 22:22:402451 // Clear the offscreen color texture.
2452 {
[email protected]34ff8b0c2010-10-01 20:06:022453 ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:402454 glClearColor(0, 0, 0, 0);
2455 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2456 glDisable(GL_SCISSOR_TEST);
[email protected]0c8c9d22010-06-25 17:36:392457 glClear(GL_COLOR_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402458 RestoreClearState();
[email protected]0c8c9d22010-06-25 17:36:392459 }
[email protected]0c8c9d22010-06-25 17:36:392460 }
[email protected]e566b955d2010-06-22 19:26:512461
[email protected]6217d392010-03-25 22:08:352462 return true;
2463}
2464
[email protected]7ff86b92010-11-25 17:50:002465void GLES2DecoderImpl::SetResizeCallback(Callback1<gfx::Size>::Type* callback) {
2466 resize_callback_.reset(callback);
2467}
2468
[email protected]43f28f832010-02-03 02:28:482469void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
2470 swap_buffers_callback_.reset(callback);
2471}
2472
[email protected]80c49752011-04-18 23:55:102473void GLES2DecoderImpl::SetLatchCallback(
2474 const base::Callback<void(bool)>& callback) {
2475 latch_callback_ = callback;
2476}
2477
[email protected]1318e922010-09-17 22:03:162478bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2479 uint32* service_texture_id) {
2480 TextureManager::TextureInfo* texture =
2481 texture_manager()->GetTextureInfo(client_texture_id);
2482 if (texture) {
2483 *service_texture_id = texture->service_id();
2484 return true;
2485 }
2486 return false;
2487}
2488
[email protected]96449d2c2009-11-25 00:01:322489void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392490 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052491
2492 if (group_.get())
2493 group_->set_have_context(have_context);
2494
[email protected]eadc96792010-10-27 19:39:392495 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142496 if (current_program_) {
2497 program_manager()->UnuseProgram(shader_manager(), current_program_);
2498 current_program_ = NULL;
2499 }
2500
[email protected]b1122982010-05-17 23:04:242501 if (attrib_0_buffer_id_) {
2502 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2503 }
[email protected]8fbedc02010-11-18 18:43:402504 if (fixed_attrib_buffer_id_) {
2505 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2506 }
[email protected]b1122982010-05-17 23:04:242507
[email protected]4bedba72010-04-20 22:08:542508 // Remove the saved frame buffer mapping from the parent decoder. The
2509 // parent pointer is a weak pointer so it will be null if the parent has
2510 // already been destroyed.
2511 if (parent_) {
2512 // First check the texture has been mapped into the parent. This might not
2513 // be the case if initialization failed midway through.
2514 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]ae51d192010-04-27 00:48:032515 GLuint client_id = 0;
2516 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]915a59a12010-09-30 21:29:112517 parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]4bedba72010-04-20 22:08:542518 }
[email protected]a3a93e7b2010-08-28 00:48:562519
2520 glDeleteFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:352521 }
[email protected]6217d392010-03-25 22:08:352522
[email protected]97872062010-11-03 19:07:052523 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542524 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052525 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542526 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052527 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022528 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052529 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152530 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052531 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152532 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052533 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022534 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052535 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542536 offscreen_saved_color_texture_->Destroy();
[email protected]66791e382010-07-14 20:48:302537
[email protected]eadc96792010-10-27 19:39:392538 // must release the ContextGroup before destroying the context as its
2539 // destructor uses GL.
2540 group_ = NULL;
[email protected]97872062010-11-03 19:07:052541 } else {
2542 if (offscreen_target_frame_buffer_.get())
2543 offscreen_target_frame_buffer_->Invalidate();
2544 if (offscreen_target_color_texture_.get())
2545 offscreen_target_color_texture_->Invalidate();
2546 if (offscreen_target_color_render_buffer_.get())
2547 offscreen_target_color_render_buffer_->Invalidate();
2548 if (offscreen_target_depth_render_buffer_.get())
2549 offscreen_target_depth_render_buffer_->Invalidate();
2550 if (offscreen_target_stencil_render_buffer_.get())
2551 offscreen_target_stencil_render_buffer_->Invalidate();
2552 if (offscreen_saved_frame_buffer_.get())
2553 offscreen_saved_frame_buffer_->Invalidate();
2554 if (offscreen_saved_color_texture_.get())
2555 offscreen_saved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022556 }
[email protected]97872062010-11-03 19:07:052557
[email protected]0fc35742011-04-13 17:57:542558 if (context_.get())
2559 context_->Destroy();
2560 context_.reset();
2561
[email protected]97872062010-11-03 19:07:052562 offscreen_target_frame_buffer_.reset();
2563 offscreen_target_color_texture_.reset();
2564 offscreen_target_color_render_buffer_.reset();
2565 offscreen_target_depth_render_buffer_.reset();
2566 offscreen_target_stencil_render_buffer_.reset();
2567 offscreen_saved_frame_buffer_.reset();
2568 offscreen_saved_color_texture_.reset();
[email protected]96449d2c2009-11-25 00:01:322569}
2570
[email protected]6217d392010-03-25 22:08:352571void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2572 // We can't resize the render buffers immediately because there might be a
2573 // partial frame rendered into them and we don't want the tail end of that
2574 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:022575 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352576}
2577
[email protected]269200b12010-11-18 22:53:062578void GLES2DecoderImpl::DoCopyTextureToParentTextureCHROMIUM(
[email protected]c007aa02010-09-02 22:22:402579 GLuint client_texture_id,
2580 GLuint parent_client_texture_id) {
[email protected]a3a93e7b2010-08-28 00:48:562581 if (parent_) {
[email protected]c007aa02010-09-02 22:22:402582 TextureManager::TextureInfo* texture = texture_manager()->GetTextureInfo(
2583 client_texture_id);
2584 TextureManager::TextureInfo* parent_texture =
2585 parent_->texture_manager()->GetTextureInfo(parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:562586 if (!texture || !parent_texture) {
2587 current_decoder_error_ = error::kInvalidArguments;
2588 return;
2589 }
2590 ScopedFrameBufferBinder fb_binder(this, copy_texture_to_parent_texture_fb_);
2591 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2592 GL_COLOR_ATTACHMENT0,
2593 GL_TEXTURE_2D,
2594 texture->service_id(),
2595 0);
2596 ScopedTexture2DBinder tex_binder(this, parent_texture->service_id());
2597 GLsizei width, height;
2598 parent_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
2599 glCopyTexImage2D(GL_TEXTURE_2D,
2600 0, // level
2601 GL_RGBA,
[email protected]c007aa02010-09-02 22:22:402602 0, 0, // x, y
[email protected]a3a93e7b2010-08-28 00:48:562603 width,
2604 height,
2605 0); // border
2606 }
2607}
2608
[email protected]43ecf372010-11-16 19:19:392609void GLES2DecoderImpl::DoResizeCHROMIUM(GLuint width, GLuint height) {
[email protected]7ff86b92010-11-25 17:50:002610#if defined(OS_LINUX)
2611 // Make sure that we are done drawing to the back buffer before resizing.
2612 glFinish();
2613#endif
2614 if (resize_callback_.get()) {
2615 gfx::Size size(width, height);
2616 resize_callback_->Run(size);
2617 }
[email protected]43ecf372010-11-16 19:19:392618}
2619
[email protected]96449d2c2009-11-25 00:01:322620const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2621 if (command_id > kStartPoint && command_id < kNumCommands) {
2622 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2623 }
2624 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2625}
2626
2627// Decode command with its arguments, and call the corresponding GL function.
2628// Note: args is a pointer to the command buffer. As such, it could be changed
2629// by a (malicious) client at any time, so if validation has to happen, it
2630// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142631error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322632 unsigned int command,
2633 unsigned int arg_count,
2634 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142635 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192636 if (debug()) {
2637 // TODO(gman): Change output to something useful for NaCl.
[email protected]d366c482010-10-20 00:11:272638 DVLOG(1) << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192639 }
[email protected]96449d2c2009-11-25 00:01:322640 unsigned int command_index = command - kStartPoint - 1;
2641 if (command_index < arraysize(g_command_info)) {
2642 const CommandInfo& info = g_command_info[command_index];
2643 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2644 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2645 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192646 uint32 immediate_data_size =
2647 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322648 switch (command) {
2649 #define GLES2_CMD_OP(name) \
2650 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192651 result = Handle ## name( \
2652 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322653 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192654 break; \
[email protected]96449d2c2009-11-25 00:01:322655
2656 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322657 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382658 }
2659 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302660 GLenum error;
2661 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382662 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292663 SetGLError(error, NULL);
[email protected]d366c482010-10-20 00:11:272664 DVLOG(1) << "GL ERROR: " << error << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192665 }
[email protected]96449d2c2009-11-25 00:01:322666 }
2667 } else {
[email protected]f7a64ee2010-02-01 22:24:142668 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322669 }
[email protected]b9849abf2009-11-25 19:13:192670 } else {
2671 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322672 }
[email protected]a3a93e7b2010-08-28 00:48:562673 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
2674 result = current_decoder_error_;
2675 current_decoder_error_ = error::kNoError;
2676 }
[email protected]b9849abf2009-11-25 19:13:192677 return result;
[email protected]96449d2c2009-11-25 00:01:322678}
2679
[email protected]ae51d192010-04-27 00:48:032680void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2681 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502682}
2683
[email protected]ae51d192010-04-27 00:48:032684bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2685 if (GetProgramInfo(client_id)) {
2686 return false;
2687 }
[email protected]96449d2c2009-11-25 00:01:322688 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032689 if (service_id != 0) {
2690 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322691 }
[email protected]ae51d192010-04-27 00:48:032692 return true;
[email protected]96449d2c2009-11-25 00:01:322693}
2694
[email protected]ae51d192010-04-27 00:48:032695bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2696 if (GetShaderInfo(client_id)) {
2697 return false;
[email protected]96449d2c2009-11-25 00:01:322698 }
[email protected]ae51d192010-04-27 00:48:032699 GLuint service_id = glCreateShader(type);
2700 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382701 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032702 }
2703 return true;
[email protected]96449d2c2009-11-25 00:01:322704}
2705
[email protected]3916c97e2010-02-25 03:20:502706void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452707 GLuint texture_index = texture_unit - GL_TEXTURE0;
2708 if (texture_index > group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292709 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502710 return;
2711 }
[email protected]36cef8ce2010-03-16 07:34:452712 active_texture_unit_ = texture_index;
2713 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502714}
2715
[email protected]051b1372010-04-12 02:42:082716void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502717 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082718 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032719 if (client_id != 0) {
2720 info = GetBufferInfo(client_id);
2721 if (!info) {
2722 // It's a new id so make a buffer info for it.
2723 glGenBuffersARB(1, &service_id);
2724 CreateBufferInfo(client_id, service_id);
2725 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102726 IdAllocator* id_allocator =
2727 group_->GetIdAllocator(id_namespaces::kBuffers);
2728 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032729 }
[email protected]051b1372010-04-12 02:42:082730 }
[email protected]ae51d192010-04-27 00:48:032731 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102732 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292733 SetGLError(GL_INVALID_OPERATION,
2734 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472735 return;
2736 }
[email protected]ae51d192010-04-27 00:48:032737 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472738 }
[email protected]96449d2c2009-11-25 00:01:322739 switch (target) {
2740 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502741 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322742 break;
2743 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502744 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322745 break;
2746 default:
[email protected]a93bb842010-02-16 23:03:472747 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322748 break;
2749 }
[email protected]051b1372010-04-12 02:42:082750 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322751}
2752
[email protected]051b1372010-04-12 02:42:082753void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2754 FramebufferManager::FramebufferInfo* info = NULL;
2755 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032756 if (client_id != 0) {
2757 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082758 if (!info) {
[email protected]ae51d192010-04-27 00:48:032759 // It's a new id so make a framebuffer info for it.
2760 glGenFramebuffersEXT(1, &service_id);
2761 CreateFramebufferInfo(client_id, service_id);
2762 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102763 IdAllocator* id_allocator =
2764 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2765 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032766 } else {
2767 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082768 }
[email protected]06c8b082011-01-05 18:00:362769 info->MarkAsValid();
[email protected]eff9a222010-12-21 21:48:562770 } else {
2771 service_id = context_->GetBackingFrameBufferObject();
[email protected]051b1372010-04-12 02:42:082772 }
[email protected]8e3e0662010-08-23 18:46:302773
2774 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
2775 bound_draw_framebuffer_ = info;
2776 }
2777 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
2778 bound_read_framebuffer_ = info;
2779 }
[email protected]6217d392010-03-25 22:08:352780
2781 // When rendering to an offscreen frame buffer, instead of unbinding from
2782 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:082783 if (info == NULL && offscreen_target_frame_buffer_.get())
2784 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:352785
[email protected]051b1372010-04-12 02:42:082786 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562787}
2788
[email protected]051b1372010-04-12 02:42:082789void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2790 RenderbufferManager::RenderbufferInfo* info = NULL;
2791 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032792 if (client_id != 0) {
2793 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082794 if (!info) {
[email protected]ae51d192010-04-27 00:48:032795 // It's a new id so make a renderbuffer info for it.
2796 glGenRenderbuffersEXT(1, &service_id);
2797 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102798 info = GetRenderbufferInfo(client_id);
2799 IdAllocator* id_allocator =
2800 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2801 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032802 } else {
2803 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082804 }
[email protected]06c8b082011-01-05 18:00:362805 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:082806 }
2807 bound_renderbuffer_ = info;
2808 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562809}
2810
[email protected]051b1372010-04-12 02:42:082811void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032812 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082813 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032814 if (client_id != 0) {
2815 info = GetTextureInfo(client_id);
2816 if (!info) {
2817 // It's a new id so make a texture info for it.
2818 glGenTextures(1, &service_id);
2819 CreateTextureInfo(client_id, service_id);
2820 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:102821 IdAllocator* id_allocator =
2822 group_->GetIdAllocator(id_namespaces::kTextures);
2823 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032824 }
2825 } else {
2826 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082827 }
[email protected]ae51d192010-04-27 00:48:032828
[email protected]1958e0e2010-04-22 05:17:152829 // Check the texture exists
2830 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032831 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292832 SetGLError(GL_INVALID_OPERATION,
2833 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152834 return;
2835 }
2836 if (info->target() == 0) {
2837 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472838 }
[email protected]ae51d192010-04-27 00:48:032839 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502840 TextureUnit& unit = texture_units_[active_texture_unit_];
2841 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472842 switch (target) {
2843 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502844 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472845 break;
2846 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502847 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472848 break;
2849 default:
2850 NOTREACHED(); // Validation should prevent us getting here.
2851 break;
2852 }
2853}
2854
[email protected]07f54fcc2009-12-22 02:46:302855void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082856 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:122857 if (index != 0 ||
2858 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:242859 glDisableVertexAttribArray(index);
2860 }
[email protected]07f54fcc2009-12-22 02:46:302861 } else {
[email protected]8eee29c2010-04-29 03:38:292862 SetGLError(GL_INVALID_VALUE,
2863 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302864 }
2865}
2866
2867void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082868 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302869 glEnableVertexAttribArray(index);
2870 } else {
[email protected]8eee29c2010-04-29 03:38:292871 SetGLError(GL_INVALID_VALUE,
2872 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302873 }
2874}
2875
[email protected]a93bb842010-02-16 23:03:472876void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502877 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]915a59a12010-09-30 21:29:112878 if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) {
[email protected]8eee29c2010-04-29 03:38:292879 SetGLError(GL_INVALID_OPERATION,
2880 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472881 return;
2882 }
[email protected]59f3ca02011-03-26 22:24:192883 // Workaround for Mac driver bug. In the large scheme of things setting
2884 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
2885 // hit so there's probably no need to make this conditional.
2886 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
[email protected]a93bb842010-02-16 23:03:472887 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:192888 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:472889}
2890
[email protected]b273e432010-04-12 17:23:582891bool GLES2DecoderImpl::GetHelper(
2892 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582893 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152894 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2895 switch (pname) {
[email protected]b273e432010-04-12 17:23:582896 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2897 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102898 if (params) {
[email protected]5094b0f2010-11-09 19:45:242899 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:102900 }
[email protected]b273e432010-04-12 17:23:582901 return true;
2902 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2903 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102904 if (params) {
[email protected]5094b0f2010-11-09 19:45:242905 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:102906 }
[email protected]b273e432010-04-12 17:23:582907 return true;
2908 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2909 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102910 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482911 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102912 }
[email protected]b273e432010-04-12 17:23:582913 return true;
2914 case GL_MAX_VARYING_VECTORS:
2915 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102916 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482917 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102918 }
[email protected]b273e432010-04-12 17:23:582919 return true;
2920 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2921 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102922 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482923 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102924 }
[email protected]b273e432010-04-12 17:23:582925 return true;
[email protected]5094b0f2010-11-09 19:45:242926 case GL_MAX_VIEWPORT_DIMS:
2927 if (offscreen_target_frame_buffer_.get()) {
2928 *num_written = 2;
2929 if (params) {
2930 params[0] = renderbuffer_manager()->max_renderbuffer_size();
2931 params[1] = renderbuffer_manager()->max_renderbuffer_size();
2932 }
2933 return true;
2934 }
[email protected]b9363b22010-06-09 22:06:152935 }
2936 }
2937 switch (pname) {
[email protected]656dcaad2010-05-07 17:18:372938 case GL_COMPRESSED_TEXTURE_FORMATS:
2939 *num_written = 0;
2940 // We don't support compressed textures.
2941 return true;
[email protected]b273e432010-04-12 17:23:582942 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
2943 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102944 if (params) {
2945 *params = 0; // We don't support compressed textures.
2946 }
[email protected]b273e432010-04-12 17:23:582947 return true;
2948 case GL_NUM_SHADER_BINARY_FORMATS:
2949 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102950 if (params) {
2951 *params = 0; // We don't support binary shader formats.
2952 }
[email protected]b273e432010-04-12 17:23:582953 return true;
2954 case GL_SHADER_BINARY_FORMATS:
2955 *num_written = 0;
2956 return true; // We don't support binary shader format.s
2957 case GL_SHADER_COMPILER:
2958 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102959 if (params) {
2960 *params = GL_TRUE;
2961 }
[email protected]b273e432010-04-12 17:23:582962 return true;
[email protected]6b8cf1a2010-05-06 16:13:582963 case GL_ARRAY_BUFFER_BINDING:
2964 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102965 if (params) {
2966 if (bound_array_buffer_) {
2967 GLuint client_id = 0;
2968 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
2969 &client_id);
2970 *params = client_id;
2971 } else {
2972 *params = 0;
2973 }
[email protected]6b8cf1a2010-05-06 16:13:582974 }
2975 return true;
2976 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
2977 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102978 if (params) {
2979 if (bound_element_array_buffer_) {
2980 GLuint client_id = 0;
2981 buffer_manager()->GetClientId(
2982 bound_element_array_buffer_->service_id(),
2983 &client_id);
2984 *params = client_id;
2985 } else {
2986 *params = 0;
2987 }
[email protected]6b8cf1a2010-05-06 16:13:582988 }
2989 return true;
2990 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:302991 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:582992 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102993 if (params) {
[email protected]8e3e0662010-08-23 18:46:302994 if (bound_draw_framebuffer_) {
[email protected]4e8a5b122010-05-08 22:00:102995 GLuint client_id = 0;
2996 framebuffer_manager()->GetClientId(
[email protected]8e3e0662010-08-23 18:46:302997 bound_draw_framebuffer_->service_id(), &client_id);
2998 *params = client_id;
2999 } else {
3000 *params = 0;
3001 }
3002 }
3003 return true;
3004 case GL_READ_FRAMEBUFFER_BINDING:
3005 *num_written = 1;
3006 if (params) {
3007 if (bound_read_framebuffer_) {
3008 GLuint client_id = 0;
3009 framebuffer_manager()->GetClientId(
3010 bound_read_framebuffer_->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103011 *params = client_id;
3012 } else {
3013 *params = 0;
3014 }
[email protected]6b8cf1a2010-05-06 16:13:583015 }
3016 return true;
3017 case GL_RENDERBUFFER_BINDING:
3018 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103019 if (params) {
3020 if (bound_renderbuffer_) {
3021 GLuint client_id = 0;
3022 renderbuffer_manager()->GetClientId(
3023 bound_renderbuffer_->service_id(), &client_id);
3024 *params = client_id;
3025 } else {
3026 *params = 0;
3027 }
[email protected]6b8cf1a2010-05-06 16:13:583028 }
3029 return true;
3030 case GL_CURRENT_PROGRAM:
3031 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103032 if (params) {
3033 if (current_program_) {
3034 GLuint client_id = 0;
3035 program_manager()->GetClientId(
3036 current_program_->service_id(), &client_id);
3037 *params = client_id;
3038 } else {
3039 *params = 0;
3040 }
[email protected]6b8cf1a2010-05-06 16:13:583041 }
3042 return true;
[email protected]4e8a5b122010-05-08 22:00:103043 case GL_TEXTURE_BINDING_2D:
3044 *num_written = 1;
3045 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583046 TextureUnit& unit = texture_units_[active_texture_unit_];
3047 if (unit.bound_texture_2d) {
3048 GLuint client_id = 0;
3049 texture_manager()->GetClientId(
3050 unit.bound_texture_2d->service_id(), &client_id);
3051 *params = client_id;
3052 } else {
3053 *params = 0;
3054 }
[email protected]6b8cf1a2010-05-06 16:13:583055 }
[email protected]4e8a5b122010-05-08 22:00:103056 return true;
3057 case GL_TEXTURE_BINDING_CUBE_MAP:
3058 *num_written = 1;
3059 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583060 TextureUnit& unit = texture_units_[active_texture_unit_];
3061 if (unit.bound_texture_cube_map) {
3062 GLuint client_id = 0;
3063 texture_manager()->GetClientId(
3064 unit.bound_texture_cube_map->service_id(), &client_id);
3065 *params = client_id;
3066 } else {
3067 *params = 0;
3068 }
[email protected]6b8cf1a2010-05-06 16:13:583069 }
[email protected]4e8a5b122010-05-08 22:00:103070 return true;
[email protected]b273e432010-04-12 17:23:583071 default:
[email protected]4e8a5b122010-05-08 22:00:103072 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533073 return false;
[email protected]b273e432010-04-12 17:23:583074 }
3075}
3076
[email protected]4e8a5b122010-05-08 22:00:103077bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3078 GLenum pname, GLsizei* num_values) {
3079 return GetHelper(pname, NULL, num_values);
3080}
3081
[email protected]b273e432010-04-12 17:23:583082void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3083 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103084 GLsizei num_written = 0;
3085 if (GetHelper(pname, NULL, &num_written)) {
3086 scoped_array<GLint> values(new GLint[num_written]);
3087 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583088 for (GLsizei ii = 0; ii < num_written; ++ii) {
3089 params[ii] = static_cast<GLboolean>(values[ii]);
3090 }
3091 } else {
3092 glGetBooleanv(pname, params);
3093 }
3094}
3095
3096void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3097 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103098 GLsizei num_written = 0;
3099 if (GetHelper(pname, NULL, &num_written)) {
3100 scoped_array<GLint> values(new GLint[num_written]);
3101 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583102 for (GLsizei ii = 0; ii < num_written; ++ii) {
3103 params[ii] = static_cast<GLfloat>(values[ii]);
3104 }
3105 } else {
3106 glGetFloatv(pname, params);
3107 }
3108}
3109
3110void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3111 DCHECK(params);
3112 GLsizei num_written;
3113 if (!GetHelper(pname, params, &num_written)) {
3114 glGetIntegerv(pname, params);
3115 }
3116}
3117
[email protected]a0c3e972010-04-21 00:49:133118void GLES2DecoderImpl::DoGetProgramiv(
3119 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583120 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3121 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133122 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133123 return;
3124 }
3125 info->GetProgramiv(pname, params);
3126}
3127
[email protected]558847a2010-03-24 07:02:543128error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3129 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:583130 GLuint program = static_cast<GLuint>(c.program);
3131 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3132 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033133 if (!info) {
[email protected]558847a2010-03-24 07:02:543134 return error::kNoError;
3135 }
3136 GLuint index = static_cast<GLuint>(c.index);
3137 uint32 name_size = c.data_size;
3138 const char* name = GetSharedMemoryAs<const char*>(
3139 c.name_shm_id, c.name_shm_offset, name_size);
3140 if (name == NULL) {
3141 return error::kOutOfBounds;
3142 }
3143 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033144 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543145 return error::kNoError;
3146}
3147
3148error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3149 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583150 GLuint program = static_cast<GLuint>(c.program);
3151 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3152 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033153 if (!info) {
[email protected]558847a2010-03-24 07:02:543154 return error::kNoError;
3155 }
3156 GLuint index = static_cast<GLuint>(c.index);
3157 uint32 name_size = c.data_size;
3158 const char* name = GetImmediateDataAs<const char*>(
3159 c, name_size, immediate_data_size);
3160 if (name == NULL) {
3161 return error::kOutOfBounds;
3162 }
3163 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033164 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543165 return error::kNoError;
3166}
3167
3168error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3169 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583170 GLuint program = static_cast<GLuint>(c.program);
3171 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3172 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033173 if (!info) {
[email protected]558847a2010-03-24 07:02:543174 return error::kNoError;
3175 }
3176 GLuint index = static_cast<GLuint>(c.index);
3177 Bucket* bucket = GetBucket(c.name_bucket_id);
3178 if (!bucket || bucket->size() == 0) {
3179 return error::kInvalidArguments;
3180 }
3181 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183182 if (!bucket->GetAsString(&name_str)) {
3183 return error::kInvalidArguments;
3184 }
[email protected]ae51d192010-04-27 00:48:033185 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543186 return error::kNoError;
3187}
3188
[email protected]f7a64ee2010-02-01 22:24:143189error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463190 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033191 GLuint client_id = c.shader;
3192 if (client_id) {
3193 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3194 if (info) {
[email protected]ca488e12010-12-13 20:06:143195 if (!info->IsDeleted()) {
3196 glDeleteShader(info->service_id());
3197 shader_manager()->MarkAsDeleted(info);
3198 }
[email protected]ae51d192010-04-27 00:48:033199 } else {
[email protected]8eee29c2010-04-29 03:38:293200 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033201 }
[email protected]96449d2c2009-11-25 00:01:323202 }
[email protected]f7a64ee2010-02-01 22:24:143203 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323204}
3205
[email protected]f7a64ee2010-02-01 22:24:143206error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463207 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033208 GLuint client_id = c.program;
3209 if (client_id) {
3210 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3211 if (info) {
[email protected]ca488e12010-12-13 20:06:143212 if (!info->IsDeleted()) {
3213 glDeleteProgram(info->service_id());
3214 program_manager()->MarkAsDeleted(shader_manager(), info);
3215 }
[email protected]ae51d192010-04-27 00:48:033216 } else {
[email protected]8eee29c2010-04-29 03:38:293217 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033218 }
[email protected]96449d2c2009-11-25 00:01:323219 }
[email protected]f7a64ee2010-02-01 22:24:143220 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323221}
3222
[email protected]269200b12010-11-18 22:53:063223void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103224 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3225 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3226 for (GLsizei ii = 0; ii < n; ++ii) {
3227 id_allocator->FreeID(ids[ii]);
3228 }
3229}
3230
[email protected]269200b12010-11-18 22:53:063231error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3232 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103233 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3234 GLsizei n = static_cast<GLsizei>(c.n);
3235 uint32 data_size;
3236 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3237 return error::kOutOfBounds;
3238 }
3239 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3240 c.ids_shm_id, c.ids_shm_offset, data_size);
3241 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063242 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103243 return error::kNoError;
3244 }
3245 if (ids == NULL) {
3246 return error::kOutOfBounds;
3247 }
[email protected]269200b12010-11-18 22:53:063248 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103249 return error::kNoError;
3250}
3251
[email protected]269200b12010-11-18 22:53:063252void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103253 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
3254 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3255 if (id_offset == 0) {
3256 for (GLsizei ii = 0; ii < n; ++ii) {
3257 ids[ii] = id_allocator->AllocateID();
3258 }
3259 } else {
3260 for (GLsizei ii = 0; ii < n; ++ii) {
3261 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3262 id_offset = ids[ii] + 1;
3263 }
3264 }
3265}
3266
[email protected]269200b12010-11-18 22:53:063267error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3268 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103269 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3270 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3271 GLsizei n = static_cast<GLsizei>(c.n);
3272 uint32 data_size;
3273 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3274 return error::kOutOfBounds;
3275 }
3276 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3277 c.ids_shm_id, c.ids_shm_offset, data_size);
3278 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063279 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103280 return error::kNoError;
3281 }
3282 if (ids == NULL) {
3283 return error::kOutOfBounds;
3284 }
[email protected]269200b12010-11-18 22:53:063285 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103286 return error::kNoError;
3287}
3288
[email protected]269200b12010-11-18 22:53:063289void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103290 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3291 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3292 for (GLsizei ii = 0; ii < n; ++ii) {
3293 if (!id_allocator->MarkAsUsed(ids[ii])) {
3294 for (GLsizei jj = 0; jj < ii; ++jj) {
3295 id_allocator->FreeID(ids[jj]);
3296 }
3297 SetGLError(
3298 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063299 "RegisterSharedIdsCHROMIUM: attempt to register "
3300 "id that already exists");
[email protected]066849e32010-05-03 19:14:103301 return;
3302 }
3303 }
3304}
3305
[email protected]269200b12010-11-18 22:53:063306error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3307 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103308 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3309 GLsizei n = static_cast<GLsizei>(c.n);
3310 uint32 data_size;
3311 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3312 return error::kOutOfBounds;
3313 }
3314 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3315 c.ids_shm_id, c.ids_shm_offset, data_size);
3316 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063317 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103318 return error::kNoError;
3319 }
3320 if (ids == NULL) {
3321 return error::kOutOfBounds;
3322 }
[email protected]269200b12010-11-18 22:53:063323 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103324 return error::kNoError;
3325}
3326
[email protected]3a03a8f2011-03-19 00:51:273327void GLES2DecoderImpl::DoClear(GLbitfield mask) {
3328 if (CheckFramebufferComplete("glClear")) {
3329 glClear(mask);
3330 }
3331}
3332
[email protected]07f54fcc2009-12-22 02:46:303333void GLES2DecoderImpl::DoDrawArrays(
3334 GLenum mode, GLint first, GLsizei count) {
[email protected]3a03a8f2011-03-19 00:51:273335 if (!CheckFramebufferComplete("glDrawArrays")) {
3336 return;
3337 }
[email protected]d81e8c52010-06-07 17:58:323338 // We have to check this here because the prototype for glDrawArrays
3339 // is GLint not GLsizei.
3340 if (first < 0) {
[email protected]7601c3f2010-12-22 00:41:203341 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
[email protected]d81e8c52010-06-07 17:58:323342 return;
3343 }
[email protected]6c788fb72010-08-26 02:16:313344
3345 if (count == 0) {
3346 return;
3347 }
3348
[email protected]8fbedc02010-11-18 18:43:403349 GLuint max_vertex_accessed = first + count - 1;
3350 if (IsDrawValid(max_vertex_accessed)) {
3351 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
3352 bool simulated_fixed_attribs = false;
3353 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
3354 bool textures_set = SetBlackTextureForNonRenderableTextures();
3355 glDrawArrays(mode, first, count);
3356 if (textures_set) {
3357 RestoreStateForNonRenderableTextures();
3358 }
3359 if (simulated_fixed_attribs) {
3360 RestoreStateForSimulatedFixedAttribs();
3361 }
[email protected]3916c97e2010-02-25 03:20:503362 }
[email protected]b1122982010-05-17 23:04:243363 if (simulated_attrib_0) {
3364 RestoreStateForSimulatedAttrib0();
3365 }
[email protected]07f54fcc2009-12-22 02:46:303366 }
3367}
3368
[email protected]36cef8ce2010-03-16 07:34:453369void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3370 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033371 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303372 FramebufferManager::FramebufferInfo* framebuffer_info =
3373 GetFramebufferInfoForTarget(target);
3374 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293375 SetGLError(GL_INVALID_OPERATION,
3376 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453377 return;
3378 }
[email protected]ae51d192010-04-27 00:48:033379 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283380 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033381 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283382 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033383 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293384 SetGLError(GL_INVALID_OPERATION,
3385 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033386 return;
3387 }
3388 service_id = info->service_id();
3389 }
[email protected]9edc6b22010-12-23 02:00:263390 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033391 glFramebufferRenderbufferEXT(
3392 target, attachment, renderbuffertarget, service_id);
[email protected]9edc6b22010-12-23 02:00:263393 GLenum error = glGetError();
3394 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303395 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]9edc6b22010-12-23 02:00:263396 if (service_id == 0 ||
3397 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3398 if (info) {
3399 ClearUnclearedRenderbuffers(target, framebuffer_info);
3400 }
[email protected]3a2e7c7b2010-08-06 01:12:283401 }
3402 }
3403}
3404
3405void GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
3406 switch (cap) {
3407 case GL_SCISSOR_TEST:
3408 enable_scissor_test_ = enabled;
3409 break;
3410 default:
3411 break;
3412 }
3413}
3414
3415void GLES2DecoderImpl::DoDisable(GLenum cap) {
3416 SetCapabilityState(cap, false);
3417 glDisable(cap);
3418}
3419
3420void GLES2DecoderImpl::DoEnable(GLenum cap) {
3421 SetCapabilityState(cap, true);
3422 glEnable(cap);
3423}
3424
3425void GLES2DecoderImpl::DoClearColor(
3426 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
3427 clear_red_ = red;
3428 clear_green_ = green;
3429 clear_blue_ = blue;
3430 clear_alpha_ = alpha;
3431 glClearColor(red, green, blue, alpha);
3432}
3433
3434void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
3435 clear_depth_ = depth;
3436 glClearDepth(depth);
3437}
3438
3439void GLES2DecoderImpl::DoClearStencil(GLint s) {
3440 clear_stencil_ = s;
3441 glClearStencil(s);
3442}
3443
3444void GLES2DecoderImpl::DoColorMask(
3445 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
3446 mask_red_ = red;
3447 mask_green_ = green;
3448 mask_blue_ = blue;
3449 mask_alpha_ = alpha;
3450 glColorMask(red, green, blue, alpha);
3451}
3452
3453void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
3454 mask_depth_ = depth;
3455 glDepthMask(depth);
3456}
3457
3458void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
3459 mask_stencil_front_ = mask;
3460 mask_stencil_back_ = mask;
3461 glStencilMask(mask);
3462}
3463
3464void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
3465 if (face == GL_FRONT) {
3466 mask_stencil_front_ = mask;
3467 } else {
3468 mask_stencil_back_ = mask;
3469 }
3470 glStencilMaskSeparate(face, mask);
3471}
3472
3473// NOTE: There's an assumption here that Texture attachments
3474// are cleared because they are textures so we only need to clear
3475// the renderbuffers.
3476void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
[email protected]8e3e0662010-08-23 18:46:303477 GLenum target, FramebufferManager::FramebufferInfo* info) {
3478 if (target == GL_READ_FRAMEBUFFER_EXT) {
3479 // TODO(gman): bind this to the DRAW point, clear then bind back to READ
3480 }
[email protected]3a2e7c7b2010-08-06 01:12:283481 GLbitfield clear_bits = 0;
3482 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
3483 glClearColor(0, 0, 0, 0);
3484 glColorMask(true, true, true, true);
3485 clear_bits |= GL_COLOR_BUFFER_BIT;
3486 }
3487
3488 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
3489 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3490 glClearStencil(0);
3491 glStencilMask(-1);
3492 clear_bits |= GL_STENCIL_BUFFER_BIT;
3493 }
3494
3495 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
3496 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3497 glClearDepth(1.0f);
3498 glDepthMask(true);
3499 clear_bits |= GL_DEPTH_BUFFER_BIT;
3500 }
3501
3502 glDisable(GL_SCISSOR_TEST);
3503 glClear(clear_bits);
3504
3505 info->MarkAttachedRenderbuffersAsCleared();
3506
[email protected]c007aa02010-09-02 22:22:403507 RestoreClearState();
3508
3509 if (target == GL_READ_FRAMEBUFFER_EXT) {
3510 // TODO(gman): rebind draw.
3511 }
3512}
3513
3514void GLES2DecoderImpl::RestoreClearState() {
[email protected]3a2e7c7b2010-08-06 01:12:283515 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
3516 glColorMask(mask_red_, mask_green_, mask_blue_, mask_alpha_);
3517 glClearStencil(clear_stencil_);
3518 glStencilMaskSeparate(GL_FRONT, mask_stencil_front_);
3519 glStencilMaskSeparate(GL_BACK, mask_stencil_back_);
3520 glClearDepth(clear_depth_);
3521 glDepthMask(mask_depth_);
3522 if (enable_scissor_test_) {
3523 glEnable(GL_SCISSOR_TEST);
3524 }
[email protected]36cef8ce2010-03-16 07:34:453525}
3526
3527GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]8e3e0662010-08-23 18:46:303528 FramebufferManager::FramebufferInfo* info =
3529 GetFramebufferInfoForTarget(target);
3530 if (!info) {
[email protected]36cef8ce2010-03-16 07:34:453531 return GL_FRAMEBUFFER_COMPLETE;
3532 }
3533 return glCheckFramebufferStatusEXT(target);
3534}
3535
3536void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033537 GLenum target, GLenum attachment, GLenum textarget,
3538 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303539 FramebufferManager::FramebufferInfo* framebuffer_info =
3540 GetFramebufferInfoForTarget(target);
3541 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293542 SetGLError(GL_INVALID_OPERATION,
3543 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453544 return;
3545 }
[email protected]ae51d192010-04-27 00:48:033546 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283547 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033548 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283549 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033550 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293551 SetGLError(GL_INVALID_OPERATION,
3552 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033553 return;
3554 }
3555 service_id = info->service_id();
3556 }
[email protected]9edc6b22010-12-23 02:00:263557 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033558 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]9edc6b22010-12-23 02:00:263559 GLenum error = glGetError();
3560 if (error == GL_NO_ERROR) {
3561 framebuffer_info->AttachTexture(attachment, info, textarget, level);
3562 if (service_id != 0 &&
3563 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3564 ClearUnclearedRenderbuffers(target, framebuffer_info);
3565 }
[email protected]3a2e7c7b2010-08-06 01:12:283566 }
[email protected]36cef8ce2010-03-16 07:34:453567}
3568
3569void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3570 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303571 FramebufferManager::FramebufferInfo* framebuffer_info =
3572 GetFramebufferInfoForTarget(target);
3573 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293574 SetGLError(GL_INVALID_OPERATION,
3575 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453576 return;
3577 }
3578 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573579 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3580 GLint type = 0;
3581 GLuint client_id = 0;
3582 glGetFramebufferAttachmentParameterivEXT(
3583 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3584 switch (type) {
3585 case GL_RENDERBUFFER: {
3586 renderbuffer_manager()->GetClientId(*params, &client_id);
3587 break;
3588 }
3589 case GL_TEXTURE: {
3590 texture_manager()->GetClientId(*params, &client_id);
3591 break;
3592 }
3593 default:
3594 break;
3595 }
3596 *params = client_id;
3597 }
[email protected]36cef8ce2010-03-16 07:34:453598}
3599
3600void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
3601 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:083602 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293603 SetGLError(GL_INVALID_OPERATION,
3604 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453605 return;
3606 }
[email protected]3a03a8f2011-03-19 00:51:273607 switch (pname) {
3608 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]b71f52c2010-06-18 22:20:203609 *params = bound_renderbuffer_->internal_format();
[email protected]3a03a8f2011-03-19 00:51:273610 break;
3611 case GL_RENDERBUFFER_WIDTH:
3612 *params = bound_renderbuffer_->width();
3613 break;
3614 case GL_RENDERBUFFER_HEIGHT:
3615 *params = bound_renderbuffer_->height();
3616 break;
3617 default:
3618 glGetRenderbufferParameterivEXT(target, pname, params);
3619 break;
[email protected]b71f52c2010-06-18 22:20:203620 }
[email protected]36cef8ce2010-03-16 07:34:453621}
3622
[email protected]8e3e0662010-08-23 18:46:303623void GLES2DecoderImpl::DoBlitFramebufferEXT(
3624 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3625 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3626 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:393627 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303628 SetGLError(GL_INVALID_OPERATION,
3629 "glBlitFramebufferEXT: function not available");
3630 }
[email protected]5094b0f2010-11-09 19:45:243631 if (IsAngle()) {
3632 glBlitFramebufferANGLE(
3633 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3634 } else {
3635 glBlitFramebufferEXT(
3636 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3637 }
[email protected]8e3e0662010-08-23 18:46:303638}
3639
3640void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
3641 GLenum target, GLsizei samples, GLenum internalformat,
3642 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:393643 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303644 SetGLError(GL_INVALID_OPERATION,
3645 "glRenderbufferStorageMultisampleEXT: function not available");
3646 return;
3647 }
[email protected]8e3e0662010-08-23 18:46:303648
[email protected]9edc6b22010-12-23 02:00:263649 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:303650 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263651 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:303652 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263653 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:303654 break;
3655 case GL_RGBA4:
3656 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263657 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:303658 break;
3659 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263660 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:303661 break;
3662 }
3663 }
3664
[email protected]9edc6b22010-12-23 02:00:263665 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:083666 if (IsAngle()) {
3667 glRenderbufferStorageMultisampleANGLE(
3668 target, samples, impl_format, width, height);
3669 } else {
3670 glRenderbufferStorageMultisampleEXT(
3671 target, samples, impl_format, width, height);
3672 }
[email protected]9edc6b22010-12-23 02:00:263673 GLenum error = glGetError();
3674 if (error == GL_NO_ERROR) {
3675 bound_renderbuffer_->SetInfo(samples, internalformat, width, height);
3676 }
[email protected]8e3e0662010-08-23 18:46:303677}
3678
[email protected]36cef8ce2010-03-16 07:34:453679void GLES2DecoderImpl::DoRenderbufferStorage(
3680 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:083681 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293682 SetGLError(GL_INVALID_OPERATION,
3683 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453684 return;
3685 }
[email protected]876f6fee2010-08-02 23:10:323686
[email protected]9edc6b22010-12-23 02:00:263687 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:323688 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263689 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:323690 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263691 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:323692 break;
3693 case GL_RGBA4:
3694 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263695 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:323696 break;
3697 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263698 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:323699 break;
3700 }
[email protected]b71f52c2010-06-18 22:20:203701 }
[email protected]876f6fee2010-08-02 23:10:323702
[email protected]9edc6b22010-12-23 02:00:263703 CopyRealGLErrorsToWrapper();
3704 glRenderbufferStorageEXT(target, impl_format, width, height);
3705 GLenum error = glGetError();
3706 if (error == GL_NO_ERROR) {
3707 bound_renderbuffer_->SetInfo(0, internalformat, width, height);
3708 }
[email protected]36cef8ce2010-03-16 07:34:453709}
3710
[email protected]07f54fcc2009-12-22 02:46:303711void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]6b8cf1a2010-05-06 16:13:583712 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3713 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:473714 if (!info) {
[email protected]a93bb842010-02-16 23:03:473715 return;
3716 }
[email protected]05afda12011-01-20 00:17:343717
[email protected]d685a682011-04-29 16:19:573718 info->Link();
[email protected]07f54fcc2009-12-22 02:46:303719};
3720
[email protected]3916c97e2010-02-25 03:20:503721void GLES2DecoderImpl::DoTexParameterf(
3722 GLenum target, GLenum pname, GLfloat param) {
3723 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:303724 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293725 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243726 return;
[email protected]07f54fcc2009-12-22 02:46:303727 }
[email protected]cbb22e42011-05-12 23:36:243728
3729 if (!texture_manager()->SetParameter(
3730 feature_info_, info, pname, static_cast<GLint>(param))) {
3731 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
3732 return;
3733 }
3734 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:303735}
3736
[email protected]3916c97e2010-02-25 03:20:503737void GLES2DecoderImpl::DoTexParameteri(
3738 GLenum target, GLenum pname, GLint param) {
3739 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3740 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293741 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243742 return;
[email protected]3916c97e2010-02-25 03:20:503743 }
[email protected]cbb22e42011-05-12 23:36:243744
3745 if (!texture_manager()->SetParameter(feature_info_, info, pname, param)) {
3746 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
3747 return;
3748 }
3749 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:503750}
3751
3752void GLES2DecoderImpl::DoTexParameterfv(
3753 GLenum target, GLenum pname, const GLfloat* params) {
3754 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3755 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293756 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243757 return;
[email protected]3916c97e2010-02-25 03:20:503758 }
[email protected]cbb22e42011-05-12 23:36:243759
3760 if (!texture_manager()->SetParameter(
3761 feature_info_, info, pname, static_cast<GLint>(params[0]))) {
3762 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
3763 return;
3764 }
3765 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503766}
3767
3768void GLES2DecoderImpl::DoTexParameteriv(
3769 GLenum target, GLenum pname, const GLint* params) {
3770 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3771 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293772 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243773 return;
[email protected]3916c97e2010-02-25 03:20:503774 }
[email protected]cbb22e42011-05-12 23:36:243775
3776 if (!texture_manager()->SetParameter(feature_info_, info, pname, *params)) {
3777 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
3778 return;
3779 }
3780 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503781}
3782
[email protected]939e7362010-05-13 20:49:103783bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:143784 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:103785 // The program does not exist.
3786 SetGLError(GL_INVALID_OPERATION,
3787 (std::string(function_name) + ": no program in use").c_str());
3788 return false;
3789 }
[email protected]ca488e12010-12-13 20:06:143790 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:103791 SetGLError(GL_INVALID_OPERATION,
3792 (std::string(function_name) + ": program not linked").c_str());
3793 return false;
3794 }
3795 return true;
3796}
3797
3798bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
3799 GLint location, const char* function_name) {
3800 if (!CheckCurrentProgram(function_name)) {
3801 return false;
3802 }
3803 return location != -1;
3804}
3805
[email protected]43c2f1f2011-03-25 18:35:363806bool GLES2DecoderImpl::PrepForSetUniformByLocation(
3807 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
3808 DCHECK(type);
3809 DCHECK(count);
[email protected]939e7362010-05-13 20:49:103810 if (!CheckCurrentProgramForUniform(location, function_name)) {
3811 return false;
3812 }
[email protected]43c2f1f2011-03-25 18:35:363813 GLint array_index = -1;
3814 const ProgramManager::ProgramInfo::UniformInfo* info =
3815 current_program_->GetUniformInfoByLocation(location, &array_index);
3816 if (!info) {
[email protected]939e7362010-05-13 20:49:103817 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:363818 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:103819 return false;
3820 }
[email protected]43c2f1f2011-03-25 18:35:363821 if (*count > 1 && !info->is_array) {
3822 SetGLError(
3823 GL_INVALID_OPERATION,
3824 (std::string(function_name) + ": count > 1 for non-array").c_str());
3825 return false;
3826 }
3827 *count = std::min(info->size - array_index, *count);
3828 if (*count <= 0) {
3829 return false;
3830 }
3831 *type = info->type;
[email protected]939e7362010-05-13 20:49:103832 return true;
3833}
3834
[email protected]939e7362010-05-13 20:49:103835void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
3836 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:503837 return;
3838 }
3839 current_program_->SetSamplers(location, 1, &v0);
3840 glUniform1i(location, v0);
3841}
3842
3843void GLES2DecoderImpl::DoUniform1iv(
3844 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:103845 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:503846 return;
3847 }
[email protected]43c2f1f2011-03-25 18:35:363848 GLenum type = 0;
3849 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
3850 return;
3851 }
3852 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE) {
3853 current_program_->SetSamplers(location, count, value);
3854 }
[email protected]3916c97e2010-02-25 03:20:503855 glUniform1iv(location, count, value);
3856}
3857
[email protected]939e7362010-05-13 20:49:103858void GLES2DecoderImpl::DoUniform1fv(
3859 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363860 GLenum type = 0;
3861 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103862 return;
3863 }
3864 if (type == GL_BOOL) {
3865 scoped_array<GLint> temp(new GLint[count]);
3866 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:533867 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103868 }
3869 DoUniform1iv(location, count, temp.get());
3870 } else {
3871 glUniform1fv(location, count, value);
3872 }
3873}
3874
3875void GLES2DecoderImpl::DoUniform2fv(
3876 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363877 GLenum type = 0;
3878 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103879 return;
3880 }
3881 if (type == GL_BOOL_VEC2) {
3882 GLsizei num_values = count * 2;
3883 scoped_array<GLint> temp(new GLint[num_values]);
3884 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533885 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103886 }
3887 glUniform2iv(location, count, temp.get());
3888 } else {
3889 glUniform2fv(location, count, value);
3890 }
3891}
3892
3893void GLES2DecoderImpl::DoUniform3fv(
3894 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363895 GLenum type = 0;
3896 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103897 return;
3898 }
3899 if (type == GL_BOOL_VEC3) {
3900 GLsizei num_values = count * 3;
3901 scoped_array<GLint> temp(new GLint[num_values]);
3902 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533903 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103904 }
3905 glUniform3iv(location, count, temp.get());
3906 } else {
3907 glUniform3fv(location, count, value);
3908 }
3909}
3910
3911void GLES2DecoderImpl::DoUniform4fv(
3912 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363913 GLenum type = 0;
3914 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103915 return;
3916 }
3917 if (type == GL_BOOL_VEC4) {
3918 GLsizei num_values = count * 4;
3919 scoped_array<GLint> temp(new GLint[num_values]);
3920 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533921 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103922 }
3923 glUniform4iv(location, count, temp.get());
3924 } else {
3925 glUniform4fv(location, count, value);
3926 }
3927}
3928
[email protected]43c2f1f2011-03-25 18:35:363929void GLES2DecoderImpl::DoUniform2iv(
3930 GLint location, GLsizei count, const GLint* value) {
3931 GLenum type = 0;
3932 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
3933 return;
3934 }
3935 glUniform2iv(location, count, value);
3936}
3937
3938void GLES2DecoderImpl::DoUniform3iv(
3939 GLint location, GLsizei count, const GLint* value) {
3940 GLenum type = 0;
3941 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
3942 return;
3943 }
3944 glUniform3iv(location, count, value);
3945}
3946
3947void GLES2DecoderImpl::DoUniform4iv(
3948 GLint location, GLsizei count, const GLint* value) {
3949 GLenum type = 0;
3950 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
3951 return;
3952 }
3953 glUniform4iv(location, count, value);
3954}
3955
3956void GLES2DecoderImpl::DoUniformMatrix2fv(
3957 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
3958 GLenum type = 0;
3959 if (!PrepForSetUniformByLocation(
3960 location, "glUniformMatrix2fv", &type, &count)) {
3961 return;
3962 }
3963 glUniformMatrix2fv (location, count, transpose, value);
3964}
3965
3966void GLES2DecoderImpl::DoUniformMatrix3fv(
3967 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
3968 GLenum type = 0;
3969 if (!PrepForSetUniformByLocation(
3970 location, "glUniformMatrix3fv", &type, &count)) {
3971 return;
3972 }
3973 glUniformMatrix3fv (location, count, transpose, value);
3974}
3975
3976void GLES2DecoderImpl::DoUniformMatrix4fv(
3977 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
3978 GLenum type = 0;
3979 if (!PrepForSetUniformByLocation(
3980 location, "glUniformMatrix4fv", &type, &count)) {
3981 return;
3982 }
3983 glUniformMatrix4fv (location, count, transpose, value);
3984}
3985
[email protected]3916c97e2010-02-25 03:20:503986void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:033987 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:503988 ProgramManager::ProgramInfo* info = NULL;
3989 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:583990 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:503991 if (!info) {
[email protected]ae51d192010-04-27 00:48:033992 return;
3993 }
3994 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:503995 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:293996 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:503997 return;
3998 }
[email protected]ae51d192010-04-27 00:48:033999 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504000 }
[email protected]ca488e12010-12-13 20:06:144001 if (current_program_) {
4002 program_manager()->UnuseProgram(shader_manager(), current_program_);
4003 }
[email protected]3916c97e2010-02-25 03:20:504004 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144005 if (current_program_) {
4006 program_manager()->UseProgram(current_program_);
4007 }
[email protected]ae51d192010-04-27 00:48:034008 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504009}
4010
[email protected]96449d2c2009-11-25 00:01:324011GLenum GLES2DecoderImpl::GetGLError() {
4012 // Check the GL error first, then our wrapped error.
4013 GLenum error = glGetError();
4014 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374015 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324016 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294017 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324018 break;
4019 }
4020 }
4021 }
4022
4023 if (error != GL_NO_ERROR) {
4024 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294025 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324026 }
4027 return error;
4028}
4029
[email protected]8eee29c2010-04-29 03:38:294030void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4031 if (msg) {
4032 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:014033 LOG(ERROR) << last_error_;
[email protected]8eee29c2010-04-29 03:38:294034 }
[email protected]ddd968b82010-03-02 00:44:294035 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324036}
4037
[email protected]07f54fcc2009-12-22 02:46:304038void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4039 GLenum error;
4040 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294041 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304042 }
4043}
4044
[email protected]6217d392010-03-25 22:08:354045void GLES2DecoderImpl::ClearRealGLErrors() {
4046 GLenum error;
4047 while ((error = glGetError()) != GL_NO_ERROR) {
4048 NOTREACHED() << "GL error " << error << " was unhandled.";
4049 }
4050}
4051
[email protected]ef526492010-06-02 23:12:254052bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504053 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254054 // Only check if there are some unrenderable textures.
4055 if (!texture_manager()->HaveUnrenderableTextures()) {
4056 return false;
4057 }
4058 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504059 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4060 current_program_->sampler_indices();
4061 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4062 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4063 current_program_->GetUniformInfo(sampler_indices[ii]);
4064 DCHECK(uniform_info);
4065 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4066 GLuint texture_unit_index = uniform_info->texture_units[jj];
4067 if (texture_unit_index < group_->max_texture_units()) {
4068 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4069 TextureManager::TextureInfo* texture_info =
4070 uniform_info->type == GL_SAMPLER_2D ?
4071 texture_unit.bound_texture_2d :
4072 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114073 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]ef526492010-06-02 23:12:254074 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504075 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4076 glBindTexture(
4077 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
4078 GL_TEXTURE_CUBE_MAP,
[email protected]00f893d2010-08-24 18:55:494079 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504080 }
4081 }
4082 // else: should this be an error?
4083 }
4084 }
[email protected]ef526492010-06-02 23:12:254085 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504086}
4087
4088void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4089 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504090 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4091 current_program_->sampler_indices();
4092 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4093 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4094 current_program_->GetUniformInfo(sampler_indices[ii]);
4095 DCHECK(uniform_info);
4096 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4097 GLuint texture_unit_index = uniform_info->texture_units[jj];
4098 if (texture_unit_index < group_->max_texture_units()) {
4099 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4100 TextureManager::TextureInfo* texture_info =
4101 uniform_info->type == GL_SAMPLER_2D ?
4102 texture_unit.bound_texture_2d :
4103 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114104 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]3916c97e2010-02-25 03:20:504105 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4106 // Get the texture info that was previously bound here.
4107 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4108 texture_unit.bound_texture_2d :
4109 texture_unit.bound_texture_cube_map;
4110 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034111 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504112 }
4113 }
4114 }
4115 }
4116 // Set the active texture back to whatever the user had it as.
4117 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304118}
4119
4120bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034121 // NOTE: We specifically do not check current_program->IsValid() because
4122 // it could never be invalid since glUseProgram would have failed. While
4123 // glLinkProgram could later mark the program as invalid the previous
4124 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144125 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504126 // The program does not exist.
4127 // But GL says no ERROR.
4128 return false;
4129 }
[email protected]f39f4b3f2010-05-12 17:04:084130 // Validate all attribs currently enabled. If they are used by the current
4131 // program then check that they have enough elements to handle the draw call.
4132 // If they are not used by the current program check that they have a buffer
4133 // assigned.
4134 const VertexAttribManager::VertexAttribInfoList& infos =
4135 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4136 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404137 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084138 const VertexAttribManager::VertexAttribInfo* info = *it;
4139 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4140 current_program_->GetAttribInfoByLocation(info->index());
4141 if (attrib_info) {
4142 // This attrib is used in the current program.
4143 if (!info->CanAccess(max_vertex_accessed)) {
4144 SetGLError(GL_INVALID_OPERATION,
4145 "glDrawXXX: attempt to access out of range vertices");
4146 return false;
4147 }
4148 } else {
4149 // This attrib is not used in the current program.
4150 if (!info->buffer() || info->buffer()->IsDeleted()) {
4151 SetGLError(
4152 GL_INVALID_OPERATION,
4153 "glDrawXXX: attempt to render with no buffer attached to enabled "
4154 "attrib");
4155 return false;
4156 }
[email protected]1d32bc82010-01-13 22:06:464157 }
[email protected]07f54fcc2009-12-22 02:46:304158 }
[email protected]3916c97e2010-02-25 03:20:504159 return true;
[email protected]b1122982010-05-17 23:04:244160}
4161
4162bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
[email protected]876f6fee2010-08-02 23:10:324163 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4164 return false;
4165
[email protected]b1122982010-05-17 23:04:244166 const VertexAttribManager::VertexAttribInfo* info =
4167 vertex_attrib_manager_.GetVertexAttribInfo(0);
4168 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494169 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4170 if (info->enabled() && attrib_0_used) {
[email protected]b1122982010-05-17 23:04:244171 return false;
4172 }
4173
4174 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4175
4176 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4177
4178 // Make a buffer with a single repeated vec4 value enough to
4179 // simulate the constant value that is supposed to be here.
4180 // This is required to emulate GLES2 on GL.
4181 GLsizei num_vertices = max_vertex_accessed + 1;
4182 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
[email protected]fc753442011-02-04 19:49:494183 if (size_needed > attrib_0_size_) {
4184 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4185 // TODO(gman): check for error here?
4186 attrib_0_buffer_matches_value_ = false;
4187 }
4188 if (attrib_0_used &&
4189 (!attrib_0_buffer_matches_value_ ||
4190 (info->value().v[0] != attrib_0_value_.v[0] ||
4191 info->value().v[1] != attrib_0_value_.v[1] ||
4192 info->value().v[2] != attrib_0_value_.v[2] ||
4193 info->value().v[3] != attrib_0_value_.v[3]))) {
4194 std::vector<Vec4> temp(num_vertices, info->value());
4195 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4196 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244197 attrib_0_value_ = info->value();
4198 attrib_0_size_ = size_needed;
4199 }
4200
4201 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4202
4203 return true;
[email protected]b1122982010-05-17 23:04:244204}
4205
4206void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4207 const VertexAttribManager::VertexAttribInfo* info =
4208 vertex_attrib_manager_.GetVertexAttribInfo(0);
4209 const void* ptr = reinterpret_cast<const void*>(info->offset());
4210 BufferManager::BufferInfo* buffer_info = info->buffer();
4211 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4212 glVertexAttribPointer(
4213 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4214 ptr);
4215 glBindBuffer(GL_ARRAY_BUFFER,
4216 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4217}
[email protected]07f54fcc2009-12-22 02:46:304218
[email protected]8fbedc02010-11-18 18:43:404219bool GLES2DecoderImpl::SimulateFixedAttribs(
4220 GLuint max_vertex_accessed, bool* simulated) {
4221 DCHECK(simulated);
4222 *simulated = false;
4223 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4224 return true;
4225
4226 if (!vertex_attrib_manager_.HaveFixedAttribs()) {
4227 return true;
4228 }
4229
4230 // NOTE: we could be smart and try to check if a buffer is used
4231 // twice in 2 different attribs, find the overlapping parts and therefore
4232 // duplicate the minimum amount of data but this whole code path is not meant
4233 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4234 // tests so we just add to the buffer attrib used.
4235
4236 // Compute the number of elements needed.
4237 int num_vertices = max_vertex_accessed + 1;
4238 int elements_needed = 0;
4239 const VertexAttribManager::VertexAttribInfoList& infos =
4240 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4241 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4242 infos.begin(); it != infos.end(); ++it) {
4243 const VertexAttribManager::VertexAttribInfo* info = *it;
4244 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4245 current_program_->GetAttribInfoByLocation(info->index());
4246 if (attrib_info &&
4247 info->CanAccess(max_vertex_accessed) &&
4248 info->type() == GL_FIXED) {
4249 int elements_used = 0;
4250 if (!SafeMultiply(
4251 static_cast<int>(num_vertices),
4252 info->size(), &elements_used) ||
4253 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4254 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4255 return false;
4256 }
4257 }
4258 }
4259
4260 const int kSizeOfFloat = sizeof(float); // NOLINT
4261 int size_needed = 0;
4262 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed)) {
4263 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4264 return false;
4265 }
4266
4267
4268 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
4269 if (size_needed > fixed_attrib_buffer_size_) {
4270 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4271 }
4272
4273 // Copy the elements and convert to float
4274 GLintptr offset = 0;
4275 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4276 infos.begin(); it != infos.end(); ++it) {
4277 const VertexAttribManager::VertexAttribInfo* info = *it;
4278 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4279 current_program_->GetAttribInfoByLocation(info->index());
4280 if (attrib_info &&
4281 info->CanAccess(max_vertex_accessed) &&
4282 info->type() == GL_FIXED) {
4283 int num_elements = info->size() * kSizeOfFloat;
4284 int size = num_elements * num_vertices;
4285 scoped_array<float> data(new float[size]);
4286 const int32* src = reinterpret_cast<const int32 *>(
4287 info->buffer()->GetRange(info->offset(), size));
4288 const int32* end = src + num_elements;
4289 float* dst = data.get();
4290 while (src != end) {
4291 *dst++ = static_cast<float>(*src++) / 65536.0f;
4292 }
4293 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
4294 glVertexAttribPointer(
4295 info->index(), info->size(), GL_FLOAT, false, 0,
4296 reinterpret_cast<GLvoid*>(offset));
4297 offset += size;
4298 }
4299 }
4300 *simulated = true;
4301 return true;
4302}
4303
4304void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
4305 // There's no need to call glVertexAttribPointer because we shadow all the
4306 // settings and passing GL_FIXED to it will not work.
4307 glBindBuffer(GL_ARRAY_BUFFER,
4308 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4309}
4310
[email protected]f7a64ee2010-02-01 22:24:144311error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:194312 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:504313 if (!bound_element_array_buffer_ ||
4314 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:294315 SetGLError(GL_INVALID_OPERATION,
4316 "glDrawElements: No element array buffer bound");
4317 return error::kNoError;
4318 }
4319
4320 GLenum mode = c.mode;
4321 GLsizei count = c.count;
4322 GLenum type = c.type;
4323 int32 offset = c.index_offset;
4324 if (count < 0) {
4325 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
4326 return error::kNoError;
4327 }
4328 if (offset < 0) {
4329 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
4330 return error::kNoError;
4331 }
[email protected]9438b012010-06-15 22:55:054332 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:294333 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
4334 return error::kNoError;
4335 }
[email protected]9438b012010-06-15 22:55:054336 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294337 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
4338 return error::kNoError;
4339 }
4340
[email protected]3a03a8f2011-03-19 00:51:274341 if (!CheckFramebufferComplete("glDrawElements")) {
4342 return error::kNoError;
4343 }
4344
[email protected]6c788fb72010-08-26 02:16:314345 if (count == 0) {
4346 return error::kNoError;
4347 }
4348
[email protected]8eee29c2010-04-29 03:38:294349 GLuint max_vertex_accessed;
4350 if (!bound_element_array_buffer_->GetMaxValueForRange(
4351 offset, count, type, &max_vertex_accessed)) {
4352 SetGLError(GL_INVALID_OPERATION,
4353 "glDrawElements: range out of bounds for buffer");
4354 return error::kNoError;
4355 }
4356
4357 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:244358 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]8fbedc02010-11-18 18:43:404359 bool simulated_fixed_attribs = false;
4360 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4361 bool textures_set = SetBlackTextureForNonRenderableTextures();
4362 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
4363 glDrawElements(mode, count, type, indices);
4364 if (textures_set) {
4365 RestoreStateForNonRenderableTextures();
4366 }
4367 if (simulated_fixed_attribs) {
4368 RestoreStateForSimulatedFixedAttribs();
4369 }
[email protected]ba3176a2009-12-16 18:19:464370 }
[email protected]b1122982010-05-17 23:04:244371 if (simulated_attrib_0) {
4372 RestoreStateForSimulatedAttrib0();
4373 }
[email protected]96449d2c2009-11-25 00:01:324374 }
[email protected]f7a64ee2010-02-01 22:24:144375 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324376}
4377
[email protected]269200b12010-11-18 22:53:064378GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:234379 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
4380 GLuint max_vertex_accessed = 0;
4381 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:294382 if (!info) {
[email protected]ae51d192010-04-27 00:48:034383 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294384 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064385 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:234386 } else {
4387 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:034388 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:064389 SetGLError(
4390 GL_INVALID_OPERATION,
4391 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:234392 }
4393 }
4394 return max_vertex_accessed;
4395}
4396
[email protected]96449d2c2009-11-25 00:01:324397// Calls glShaderSource for the various versions of the ShaderSource command.
4398// Assumes that data / data_size points to a piece of memory that is in range
4399// of whatever context it came from (shared memory, immediate memory, bucket
4400// memory.)
[email protected]45bf5152010-02-12 00:11:314401error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034402 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:584403 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4404 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:314405 if (!info) {
[email protected]45bf5152010-02-12 00:11:314406 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324407 }
[email protected]45bf5152010-02-12 00:11:314408 // Note: We don't actually call glShaderSource here. We wait until
4409 // the call to glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524410 info->Update(std::string(data, data + data_size).c_str());
[email protected]f7a64ee2010-02-01 22:24:144411 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324412}
4413
[email protected]f7a64ee2010-02-01 22:24:144414error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:194415 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:324416 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314417 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:324418 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:464419 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144420 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324421 }
[email protected]ae51d192010-04-27 00:48:034422 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:324423}
4424
[email protected]f7a64ee2010-02-01 22:24:144425error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:194426 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:324427 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314428 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:304429 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464430 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144431 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324432 }
[email protected]ae51d192010-04-27 00:48:034433 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:314434}
4435
[email protected]558847a2010-03-24 07:02:544436error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
4437 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:544438 Bucket* bucket = GetBucket(c.data_bucket_id);
4439 if (!bucket || bucket->size() == 0) {
4440 return error::kInvalidArguments;
4441 }
4442 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034443 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:544444 bucket->size() - 1);
4445}
4446
[email protected]ae51d192010-04-27 00:48:034447void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584448 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4449 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:314450 if (!info) {
[email protected]45bf5152010-02-12 00:11:314451 return;
4452 }
[email protected]de17df392010-04-23 21:09:414453 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
4454 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524455 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:344456 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:184457 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:344458 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:454459 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:234460
[email protected]a550584e2010-09-17 18:01:454461 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:344462 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:184463 return;
4464 }
[email protected]a550584e2010-09-17 18:01:454465 shader_src = translator->translated_shader();
[email protected]de17df392010-04-23 21:09:414466 }
[email protected]de17df392010-04-23 21:09:414467
[email protected]ae51d192010-04-27 00:48:034468 glShaderSource(info->service_id(), 1, &shader_src, NULL);
4469 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:414470 GLint status = GL_FALSE;
4471 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
4472 if (status) {
[email protected]f57bb282010-11-12 00:51:344473 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:414474 } else {
[email protected]d9977d42010-09-01 20:27:024475 // We cannot reach here if we are using the shader translator.
4476 // All invalid shaders must be rejected by the translator.
4477 // All translated shaders must compile.
4478 LOG_IF(ERROR, use_shader_translator_)
4479 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:334480 GLint max_len = 0;
4481 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
4482 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:414483 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:334484 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
4485 DCHECK(max_len == 0 || len < max_len);
4486 DCHECK(len ==0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:524487 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:414488 }
[email protected]45bf5152010-02-12 00:11:314489};
4490
[email protected]ddd968b82010-03-02 00:44:294491void GLES2DecoderImpl::DoGetShaderiv(
4492 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:584493 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4494 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:294495 if (!info) {
[email protected]ddd968b82010-03-02 00:44:294496 return;
4497 }
[email protected]8f1ccdac2010-05-19 21:01:484498 switch (pname) {
4499 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524500 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:484501 return;
4502 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:414503 *params = info->IsValid();
4504 return;
[email protected]8f1ccdac2010-05-19 21:01:484505 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524506 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:414507 return;
[email protected]8f1ccdac2010-05-19 21:01:484508 default:
4509 break;
[email protected]ddd968b82010-03-02 00:44:294510 }
[email protected]8f1ccdac2010-05-19 21:01:484511 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:294512}
4513
[email protected]ae51d192010-04-27 00:48:034514error::Error GLES2DecoderImpl::HandleGetShaderSource(
4515 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
4516 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:034517 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4518 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:584519 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4520 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:524521 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:294522 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:294523 return error::kNoError;
4524 }
[email protected]df6cf1ad2011-01-29 01:20:524525 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:034526 return error::kNoError;
4527}
4528
4529error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
4530 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
4531 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:584532 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4533 Bucket* bucket = CreateBucket(bucket_id);
4534 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4535 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524536 if (!info || !info->log_info()) {
4537 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034538 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:314539 }
[email protected]df6cf1ad2011-01-29 01:20:524540 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034541 return error::kNoError;
4542}
4543
4544error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
4545 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
4546 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:584547 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4548 Bucket* bucket = CreateBucket(bucket_id);
4549 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4550 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524551 if (!info || !info->log_info()) {
[email protected]6b8cf1a2010-05-06 16:13:584552 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034553 return error::kNoError;
4554 }
[email protected]df6cf1ad2011-01-29 01:20:524555 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034556 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324557}
4558
[email protected]1958e0e2010-04-22 05:17:154559bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364560 const BufferManager::BufferInfo* info = GetBufferInfo(client_id);
4561 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154562}
4563
4564bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364565 const FramebufferManager::FramebufferInfo* info =
4566 GetFramebufferInfo(client_id);
4567 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154568}
4569
4570bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364571 // IsProgram is true for programs as soon as they are created, until they are
4572 // deleted and no longer in use.
[email protected]ae51d192010-04-27 00:48:034573 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154574}
4575
4576bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364577 const RenderbufferManager::RenderbufferInfo* info =
4578 GetRenderbufferInfo(client_id);
4579 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154580}
4581
4582bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364583 // IsShader is true for shaders as soon as they are created, until they
4584 // are deleted and not attached to any programs.
[email protected]ae51d192010-04-27 00:48:034585 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154586}
4587
4588bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364589 const TextureManager::TextureInfo* info = GetTextureInfo(client_id);
4590 return info && info->IsValid();
[email protected]ae51d192010-04-27 00:48:034591}
4592
4593void GLES2DecoderImpl::DoAttachShader(
4594 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584595 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4596 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034597 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034598 return;
[email protected]1958e0e2010-04-22 05:17:154599 }
[email protected]6b8cf1a2010-05-06 16:13:584600 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4601 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034602 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034603 return;
4604 }
[email protected]ca488e12010-12-13 20:06:144605 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:314606 SetGLError(GL_INVALID_OPERATION,
4607 "glAttachShader: can not attach more than"
4608 " one shader of the same type.");
4609 return;
4610 }
[email protected]ae51d192010-04-27 00:48:034611 glAttachShader(program_info->service_id(), shader_info->service_id());
4612}
4613
4614void GLES2DecoderImpl::DoDetachShader(
4615 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584616 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4617 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034618 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034619 return;
4620 }
[email protected]6b8cf1a2010-05-06 16:13:584621 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4622 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034623 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034624 return;
4625 }
[email protected]9a0ccd42011-03-16 23:58:224626 if (!program_info->DetachShader(shader_manager(), shader_info)) {
4627 SetGLError(GL_INVALID_OPERATION,
4628 "glDetachShader: shader not attached to program");
4629 return;
4630 }
[email protected]ae51d192010-04-27 00:48:034631 glDetachShader(program_info->service_id(), shader_info->service_id());
4632}
4633
4634void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584635 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4636 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:034637 if (!info) {
[email protected]ae51d192010-04-27 00:48:034638 return;
4639 }
[email protected]d685a682011-04-29 16:19:574640 info->Validate();
[email protected]1958e0e2010-04-22 05:17:154641}
4642
[email protected]b1122982010-05-17 23:04:244643void GLES2DecoderImpl::DoGetVertexAttribfv(
4644 GLuint index, GLenum pname, GLfloat* params) {
4645 VertexAttribManager::VertexAttribInfo* info =
4646 vertex_attrib_manager_.GetVertexAttribInfo(index);
4647 if (!info) {
4648 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
4649 return;
4650 }
4651 switch (pname) {
4652 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4653 BufferManager::BufferInfo* buffer = info->buffer();
4654 if (buffer && !buffer->IsDeleted()) {
4655 GLuint client_id;
4656 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4657 *params = static_cast<GLfloat>(client_id);
4658 }
4659 break;
4660 }
4661 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4662 *params = static_cast<GLfloat>(info->enabled());
4663 break;
4664 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4665 *params = static_cast<GLfloat>(info->size());
4666 break;
4667 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4668 *params = static_cast<GLfloat>(info->gl_stride());
4669 break;
4670 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4671 *params = static_cast<GLfloat>(info->type());
4672 break;
4673 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4674 *params = static_cast<GLfloat>(info->normalized());
4675 break;
4676 case GL_CURRENT_VERTEX_ATTRIB:
4677 params[0] = info->value().v[0];
4678 params[1] = info->value().v[1];
4679 params[2] = info->value().v[2];
4680 params[3] = info->value().v[3];
4681 break;
4682 default:
4683 NOTREACHED();
4684 break;
4685 }
4686}
4687
4688void GLES2DecoderImpl::DoGetVertexAttribiv(
4689 GLuint index, GLenum pname, GLint* params) {
4690 VertexAttribManager::VertexAttribInfo* info =
4691 vertex_attrib_manager_.GetVertexAttribInfo(index);
4692 if (!info) {
4693 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
4694 return;
4695 }
4696 switch (pname) {
4697 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4698 BufferManager::BufferInfo* buffer = info->buffer();
4699 if (buffer && !buffer->IsDeleted()) {
4700 GLuint client_id;
4701 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4702 *params = client_id;
4703 }
4704 break;
4705 }
4706 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4707 *params = info->enabled();
4708 break;
4709 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4710 *params = info->size();
4711 break;
4712 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4713 *params = info->gl_stride();
4714 break;
4715 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4716 *params = info->type();
4717 break;
4718 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4719 *params = static_cast<GLint>(info->normalized());
4720 break;
4721 case GL_CURRENT_VERTEX_ATTRIB:
4722 params[0] = static_cast<GLint>(info->value().v[0]);
4723 params[1] = static_cast<GLint>(info->value().v[1]);
4724 params[2] = static_cast<GLint>(info->value().v[2]);
4725 params[3] = static_cast<GLint>(info->value().v[3]);
4726 break;
4727 default:
4728 NOTREACHED();
4729 break;
4730 }
4731}
4732
4733void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
4734 VertexAttribManager::VertexAttribInfo* info =
4735 vertex_attrib_manager_.GetVertexAttribInfo(index);
4736 if (!info) {
4737 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
4738 return;
4739 }
4740 VertexAttribManager::VertexAttribInfo::Vec4 value;
4741 value.v[0] = v0;
4742 value.v[1] = 0.0f;
4743 value.v[2] = 0.0f;
4744 value.v[3] = 1.0f;
4745 info->set_value(value);
4746 glVertexAttrib1f(index, v0);
4747}
4748
4749void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
4750 VertexAttribManager::VertexAttribInfo* info =
4751 vertex_attrib_manager_.GetVertexAttribInfo(index);
4752 if (!info) {
4753 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
4754 return;
4755 }
4756 VertexAttribManager::VertexAttribInfo::Vec4 value;
4757 value.v[0] = v0;
4758 value.v[1] = v1;
4759 value.v[2] = 0.0f;
4760 value.v[3] = 1.0f;
4761 info->set_value(value);
4762 glVertexAttrib2f(index, v0, v1);
4763}
4764
4765void GLES2DecoderImpl::DoVertexAttrib3f(
4766 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
4767 VertexAttribManager::VertexAttribInfo* info =
4768 vertex_attrib_manager_.GetVertexAttribInfo(index);
4769 if (!info) {
4770 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
4771 return;
4772 }
4773 VertexAttribManager::VertexAttribInfo::Vec4 value;
4774 value.v[0] = v0;
4775 value.v[1] = v1;
4776 value.v[2] = v2;
4777 value.v[3] = 1.0f;
4778 info->set_value(value);
4779 glVertexAttrib3f(index, v0, v1, v2);
4780}
4781
4782void GLES2DecoderImpl::DoVertexAttrib4f(
4783 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
4784 VertexAttribManager::VertexAttribInfo* info =
4785 vertex_attrib_manager_.GetVertexAttribInfo(index);
4786 if (!info) {
4787 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
4788 return;
4789 }
4790 VertexAttribManager::VertexAttribInfo::Vec4 value;
4791 value.v[0] = v0;
4792 value.v[1] = v1;
4793 value.v[2] = v2;
4794 value.v[3] = v3;
4795 info->set_value(value);
4796 glVertexAttrib4f(index, v0, v1, v2, v3);
4797}
4798
4799void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
4800 VertexAttribManager::VertexAttribInfo* info =
4801 vertex_attrib_manager_.GetVertexAttribInfo(index);
4802 if (!info) {
4803 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
4804 return;
4805 }
4806 VertexAttribManager::VertexAttribInfo::Vec4 value;
4807 value.v[0] = v[0];
4808 value.v[1] = 0.0f;
4809 value.v[2] = 0.0f;
4810 value.v[3] = 1.0f;
4811 info->set_value(value);
4812 glVertexAttrib1fv(index, v);
4813}
4814
4815void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
4816 VertexAttribManager::VertexAttribInfo* info =
4817 vertex_attrib_manager_.GetVertexAttribInfo(index);
4818 if (!info) {
4819 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
4820 return;
4821 }
4822 VertexAttribManager::VertexAttribInfo::Vec4 value;
4823 value.v[0] = v[0];
4824 value.v[1] = v[1];
4825 value.v[2] = 0.0f;
4826 value.v[3] = 1.0f;
4827 info->set_value(value);
4828 glVertexAttrib2fv(index, v);
4829}
4830
4831void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
4832 VertexAttribManager::VertexAttribInfo* info =
4833 vertex_attrib_manager_.GetVertexAttribInfo(index);
4834 if (!info) {
4835 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
4836 return;
4837 }
4838 VertexAttribManager::VertexAttribInfo::Vec4 value;
4839 value.v[0] = v[0];
4840 value.v[1] = v[1];
4841 value.v[2] = v[2];
4842 value.v[3] = 1.0f;
4843 info->set_value(value);
4844 glVertexAttrib3fv(index, v);
4845}
4846
4847void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
4848 VertexAttribManager::VertexAttribInfo* info =
4849 vertex_attrib_manager_.GetVertexAttribInfo(index);
4850 if (!info) {
4851 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
4852 return;
4853 }
4854 VertexAttribManager::VertexAttribInfo::Vec4 value;
4855 value.v[0] = v[0];
4856 value.v[1] = v[1];
4857 value.v[2] = v[2];
4858 value.v[3] = v[3];
4859 info->set_value(value);
4860 glVertexAttrib4fv(index, v);
4861}
4862
[email protected]f7a64ee2010-02-01 22:24:144863error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:194864 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:294865 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
4866 SetGLError(GL_INVALID_VALUE,
4867 "glVertexAttribPointer: no array buffer bound");
4868 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324869 }
[email protected]8eee29c2010-04-29 03:38:294870
4871 GLuint indx = c.indx;
4872 GLint size = c.size;
4873 GLenum type = c.type;
4874 GLboolean normalized = c.normalized;
4875 GLsizei stride = c.stride;
4876 GLsizei offset = c.offset;
4877 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:054878 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294879 SetGLError(GL_INVALID_ENUM,
4880 "glVertexAttribPointer: type GL_INVALID_ENUM");
4881 return error::kNoError;
4882 }
[email protected]9438b012010-06-15 22:55:054883 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:314884 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:294885 "glVertexAttribPointer: size GL_INVALID_VALUE");
4886 return error::kNoError;
4887 }
4888 if (indx >= group_->max_vertex_attribs()) {
4889 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
4890 return error::kNoError;
4891 }
4892 if (stride < 0) {
4893 SetGLError(GL_INVALID_VALUE,
4894 "glVertexAttribPointer: stride < 0");
4895 return error::kNoError;
4896 }
4897 if (stride > 255) {
4898 SetGLError(GL_INVALID_VALUE,
4899 "glVertexAttribPointer: stride > 255");
4900 return error::kNoError;
4901 }
4902 if (offset < 0) {
4903 SetGLError(GL_INVALID_VALUE,
4904 "glVertexAttribPointer: offset < 0");
4905 return error::kNoError;
4906 }
4907 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:314908 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:294909 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:314910 SetGLError(GL_INVALID_OPERATION,
4911 "glVertexAttribPointer: offset not valid for type");
4912 return error::kNoError;
4913 }
4914 if (stride % component_size > 0) {
4915 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:294916 "glVertexAttribPointer: stride not valid for type");
4917 return error::kNoError;
4918 }
[email protected]8fbedc02010-11-18 18:43:404919 vertex_attrib_manager_.SetAttribInfo(
4920 indx,
[email protected]8eee29c2010-04-29 03:38:294921 bound_array_buffer_,
4922 size,
4923 type,
[email protected]b1122982010-05-17 23:04:244924 normalized,
4925 stride,
4926 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:294927 offset);
[email protected]8fbedc02010-11-18 18:43:404928 if (type != GL_FIXED) {
4929 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
4930 }
[email protected]f7a64ee2010-02-01 22:24:144931 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324932}
4933
[email protected]f7a64ee2010-02-01 22:24:144934error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:194935 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:314936 GLint x = c.x;
4937 GLint y = c.y;
4938 GLsizei width = c.width;
4939 GLsizei height = c.height;
4940 GLenum format = c.format;
4941 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:564942 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:294943 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:564944 return error::kNoError;
4945 }
[email protected]a51788e2010-02-24 21:54:254946 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:184947 uint32 pixels_size;
4948 if (!GLES2Util::ComputeImageDataSize(
4949 width, height, format, type, pack_alignment_, &pixels_size)) {
4950 return error::kOutOfBounds;
4951 }
[email protected]612d2f82009-12-08 20:49:314952 void* pixels = GetSharedMemoryAs<void*>(
4953 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:254954 Result* result = GetSharedMemoryAs<Result*>(
4955 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4956 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:144957 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464958 }
[email protected]a51788e2010-02-24 21:54:254959
[email protected]9438b012010-06-15 22:55:054960 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:294961 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
4962 return error::kNoError;
4963 }
[email protected]9438b012010-06-15 22:55:054964 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294965 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:124966 return error::kNoError;
4967 }
[email protected]57f223832010-03-19 01:57:564968 if (width == 0 || height == 0) {
4969 return error::kNoError;
4970 }
4971
4972 CopyRealGLErrorsToWrapper();
4973
[email protected]c0701082011-04-20 00:34:524974 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]34ff8b0c2010-10-01 20:06:024975
[email protected]57f223832010-03-19 01:57:564976 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:304977 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:564978
4979 GLint max_x;
4980 GLint max_y;
4981 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:294982 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:144983 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:314984 }
[email protected]57f223832010-03-19 01:57:564985
[email protected]d37231fa2010-04-09 21:16:024986 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:564987 // The user requested an out of range area. Get the results 1 line
4988 // at a time.
4989 uint32 temp_size;
4990 if (!GLES2Util::ComputeImageDataSize(
4991 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:294992 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564993 return error::kNoError;
4994 }
4995 GLsizei unpadded_row_size = temp_size;
4996 if (!GLES2Util::ComputeImageDataSize(
4997 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:294998 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564999 return error::kNoError;
5000 }
5001 GLsizei padded_row_size = temp_size - unpadded_row_size;
5002 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:295003 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565004 return error::kNoError;
5005 }
5006
5007 GLint dest_x_offset = std::max(-x, 0);
5008 uint32 dest_row_offset;
5009 if (!GLES2Util::ComputeImageDataSize(
5010 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:295011 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565012 return error::kNoError;
5013 }
5014
5015 // Copy each row into the larger dest rect.
5016 int8* dst = static_cast<int8*>(pixels);
5017 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:025018 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:565019 GLint read_width = read_end_x - read_x;
5020 for (GLint yy = 0; yy < height; ++yy) {
5021 GLint ry = y + yy;
5022
5023 // Clear the row.
5024 memset(dst, 0, unpadded_row_size);
5025
5026 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025027 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565028 glReadPixels(
5029 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5030 }
5031 dst += padded_row_size;
5032 }
5033 } else {
5034 glReadPixels(x, y, width, height, format, type, pixels);
5035 }
[email protected]a51788e2010-02-24 21:54:255036 GLenum error = glGetError();
5037 if (error == GL_NO_ERROR) {
5038 *result = true;
[email protected]4848b9f82011-03-10 18:37:565039
5040 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5041 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5042 if ((channels_exist & 0x0008) == 0) {
5043 // Set the alpha to 255 because some drivers are buggy in this regard.
5044 uint32 temp_size;
5045 if (!GLES2Util::ComputeImageDataSize(
5046 width, 1, format, type, pack_alignment_, &temp_size)) {
5047 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5048 return error::kNoError;
5049 }
5050 GLsizei unpadded_row_size = temp_size;
5051 if (!GLES2Util::ComputeImageDataSize(
5052 width, 2, format, type, pack_alignment_, &temp_size)) {
5053 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5054 return error::kNoError;
5055 }
5056 GLsizei padded_row_size = temp_size - unpadded_row_size;
5057 if (padded_row_size < 0 || unpadded_row_size < 0) {
5058 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5059 return error::kNoError;
5060 }
5061 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5062 // of this implementation.
5063 if (type != GL_UNSIGNED_BYTE) {
5064 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5065 return error::kNoError;
5066 }
5067 switch (format) {
5068 case GL_RGBA:
5069 case GL_ALPHA: {
5070 int offset = (format == GL_ALPHA) ? 0 : 3;
5071 int step = (format == GL_ALPHA) ? 1 : 4;
5072 uint8* dst = static_cast<uint8*>(pixels) + offset;
5073 for (GLint yy = 0; yy < height; ++yy) {
5074 uint8* end = dst + unpadded_row_size;
5075 for (uint8* d = dst; d < end; d += step) {
5076 *d = 255;
5077 }
5078 dst += padded_row_size;
5079 }
5080 break;
5081 }
5082 default:
5083 break;
5084 }
5085 }
[email protected]a51788e2010-02-24 21:54:255086 } else {
[email protected]8eee29c2010-04-29 03:38:295087 SetGLError(error, NULL);
[email protected]a51788e2010-02-24 21:54:255088 }
[email protected]4848b9f82011-03-10 18:37:565089
[email protected]f7a64ee2010-02-01 22:24:145090 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325091}
5092
[email protected]f7a64ee2010-02-01 22:24:145093error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195094 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5095 GLenum pname = c.pname;
5096 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055097 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295098 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125099 return error::kNoError;
5100 }
[email protected]9438b012010-06-15 22:55:055101 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:295102 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:145103 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195104 }
5105 glPixelStorei(pname, param);
5106 switch (pname) {
5107 case GL_PACK_ALIGNMENT:
5108 pack_alignment_ = param;
5109 break;
5110 case GL_UNPACK_ALIGNMENT:
5111 unpack_alignment_ = param;
5112 break;
5113 default:
5114 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:375115 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:195116 break;
5117 }
[email protected]f7a64ee2010-02-01 22:24:145118 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195119}
5120
[email protected]558847a2010-03-24 07:02:545121error::Error GLES2DecoderImpl::GetAttribLocationHelper(
5122 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5123 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585124 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5125 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:035126 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145127 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195128 }
[email protected]ae51d192010-04-27 00:48:035129 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295130 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255131 return error::kNoError;
5132 }
[email protected]b9849abf2009-11-25 19:13:195133 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545134 location_shm_id, location_shm_offset, sizeof(GLint));
5135 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145136 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195137 }
[email protected]558847a2010-03-24 07:02:545138 // Require the client to init this incase the context is lost and we are no
5139 // longer executing commands.
5140 if (*location != -1) {
5141 return error::kGenericError;
5142 }
[email protected]0bfd9882010-02-05 23:02:255143 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145144 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195145}
5146
[email protected]558847a2010-03-24 07:02:545147error::Error GLES2DecoderImpl::HandleGetAttribLocation(
5148 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
5149 uint32 name_size = c.data_size;
5150 const char* name = GetSharedMemoryAs<const char*>(
5151 c.name_shm_id, c.name_shm_offset, name_size);
5152 if (!name) {
5153 return error::kOutOfBounds;
5154 }
5155 String name_str(name, name_size);
5156 return GetAttribLocationHelper(
5157 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5158}
5159
[email protected]f7a64ee2010-02-01 22:24:145160error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195161 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:545162 uint32 name_size = c.data_size;
5163 const char* name = GetImmediateDataAs<const char*>(
5164 c, name_size, immediate_data_size);
5165 if (!name) {
5166 return error::kOutOfBounds;
5167 }
5168 String name_str(name, name_size);
5169 return GetAttribLocationHelper(
5170 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5171}
5172
5173error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
5174 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
5175 Bucket* bucket = GetBucket(c.name_bucket_id);
5176 if (!bucket) {
5177 return error::kInvalidArguments;
5178 }
5179 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185180 if (!bucket->GetAsString(&name_str)) {
5181 return error::kInvalidArguments;
5182 }
[email protected]558847a2010-03-24 07:02:545183 return GetAttribLocationHelper(
5184 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5185}
5186
5187error::Error GLES2DecoderImpl::GetUniformLocationHelper(
5188 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5189 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585190 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5191 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:035192 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145193 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195194 }
[email protected]ae51d192010-04-27 00:48:035195 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295196 SetGLError(GL_INVALID_OPERATION,
5197 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255198 return error::kNoError;
5199 }
[email protected]b9849abf2009-11-25 19:13:195200 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545201 location_shm_id, location_shm_offset, sizeof(GLint));
5202 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145203 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195204 }
[email protected]558847a2010-03-24 07:02:545205 // Require the client to init this incase the context is lost an we are no
5206 // longer executing commands.
5207 if (*location != -1) {
5208 return error::kGenericError;
5209 }
5210 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145211 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195212}
5213
[email protected]f7a64ee2010-02-01 22:24:145214error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:195215 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:195216 uint32 name_size = c.data_size;
5217 const char* name = GetSharedMemoryAs<const char*>(
5218 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:545219 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145220 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195221 }
5222 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545223 return GetUniformLocationHelper(
5224 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195225}
5226
[email protected]f7a64ee2010-02-01 22:24:145227error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195228 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:195229 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:305230 const char* name = GetImmediateDataAs<const char*>(
5231 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:545232 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145233 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195234 }
5235 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545236 return GetUniformLocationHelper(
5237 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5238}
5239
5240error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
5241 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
5242 Bucket* bucket = GetBucket(c.name_bucket_id);
5243 if (!bucket) {
5244 return error::kInvalidArguments;
5245 }
5246 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185247 if (!bucket->GetAsString(&name_str)) {
5248 return error::kInvalidArguments;
5249 }
[email protected]558847a2010-03-24 07:02:545250 return GetUniformLocationHelper(
5251 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195252}
5253
[email protected]ddd968b82010-03-02 00:44:295254error::Error GLES2DecoderImpl::HandleGetString(
5255 uint32 immediate_data_size, const gles2::GetString& c) {
5256 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:055257 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:295258 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:295259 return error::kNoError;
5260 }
[email protected]1958e0e2010-04-22 05:17:155261 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
5262 const char* str = NULL;
5263 switch (name) {
5264 case GL_VERSION:
5265 str = "OpenGL ES 2.0 Chromium";
5266 break;
5267 case GL_SHADING_LANGUAGE_VERSION:
5268 str = "OpenGL ES GLSL ES 1.0 Chromium";
5269 break;
5270 case GL_EXTENSIONS:
[email protected]915a59a12010-09-30 21:29:115271 str = feature_info_->extensions().c_str();
[email protected]1958e0e2010-04-22 05:17:155272 break;
5273 default:
5274 str = gl_str;
5275 break;
5276 }
[email protected]ddd968b82010-03-02 00:44:295277 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:155278 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:295279 return error::kNoError;
5280}
5281
[email protected]0c86dbf2010-03-05 08:14:115282void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:155283 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:055284 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295285 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
5286 return;
5287 }
[email protected]9438b012010-06-15 22:55:055288 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:295289 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:115290 return;
[email protected]3b6ec202010-03-05 05:16:235291 }
5292 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:295293 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:285294 return;
[email protected]3b6ec202010-03-05 05:16:235295 }
5296 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
5297 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295298 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285299 return;
[email protected]3b6ec202010-03-05 05:16:235300 }
5301 // Clear the buffer to 0 if no initial data was passed in.
5302 scoped_array<int8> zero;
5303 if (!data) {
5304 zero.reset(new int8[size]);
5305 memset(zero.get(), 0, size);
5306 data = zero.get();
5307 }
5308 CopyRealGLErrorsToWrapper();
5309 glBufferData(target, size, data, usage);
5310 GLenum error = glGetError();
5311 if (error != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:295312 SetGLError(error, NULL);
[email protected]3b6ec202010-03-05 05:16:235313 } else {
[email protected]4e8a5b122010-05-08 22:00:105314 buffer_manager()->SetSize(info, size);
[email protected]0c86dbf2010-03-05 08:14:115315 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:235316 }
[email protected]0c86dbf2010-03-05 08:14:115317}
5318
5319error::Error GLES2DecoderImpl::HandleBufferData(
5320 uint32 immediate_data_size, const gles2::BufferData& c) {
5321 GLenum target = static_cast<GLenum>(c.target);
5322 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
5323 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5324 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5325 GLenum usage = static_cast<GLenum>(c.usage);
5326 const void* data = NULL;
5327 if (data_shm_id != 0 || data_shm_offset != 0) {
5328 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
5329 if (!data) {
5330 return error::kOutOfBounds;
5331 }
5332 }
5333 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:145334 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195335}
5336
[email protected]f7a64ee2010-02-01 22:24:145337error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:195338 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
5339 GLenum target = static_cast<GLenum>(c.target);
5340 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:305341 const void* data = GetImmediateDataAs<const void*>(
5342 c, size, immediate_data_size);
5343 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145344 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:305345 }
[email protected]b9849abf2009-11-25 19:13:195346 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:115347 DoBufferData(target, size, data, usage);
5348 return error::kNoError;
5349}
5350
5351void GLES2DecoderImpl::DoBufferSubData(
5352 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:505353 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475354 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295355 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285356 return;
[email protected]a93bb842010-02-16 23:03:475357 }
[email protected]0c86dbf2010-03-05 08:14:115358 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:295359 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]07f54fcc2009-12-22 02:46:305360 } else {
[email protected]0c86dbf2010-03-05 08:14:115361 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:305362 }
[email protected]b9849abf2009-11-25 19:13:195363}
5364
[email protected]a93bb842010-02-16 23:03:475365error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
5366 GLenum target,
5367 GLint level,
5368 GLenum internal_format,
5369 GLsizei width,
5370 GLsizei height,
5371 GLint border,
5372 GLsizei image_size,
5373 const void* data) {
[email protected]a93bb842010-02-16 23:03:475374 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:055375 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295376 SetGLError(GL_INVALID_ENUM,
5377 "glCompressedTexImage2D: target GL_INVALID_ENUM");
5378 return error::kNoError;
5379 }
[email protected]9438b012010-06-15 22:55:055380 if (!validators_->compressed_texture_format.IsValid(
5381 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295382 SetGLError(GL_INVALID_ENUM,
5383 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:475384 return error::kNoError;
5385 }
[email protected]915a59a12010-09-30 21:29:115386 if (!texture_manager()->ValidForTarget(
5387 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475388 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295389 SetGLError(GL_INVALID_VALUE,
5390 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475391 return error::kNoError;
5392 }
[email protected]3916c97e2010-02-25 03:20:505393 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475394 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295395 SetGLError(GL_INVALID_VALUE,
5396 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:475397 return error::kNoError;
5398 }
5399 scoped_array<int8> zero;
5400 if (!data) {
5401 zero.reset(new int8[image_size]);
5402 memset(zero.get(), 0, image_size);
5403 data = zero.get();
5404 }
[email protected]cadde4a2010-07-31 17:10:435405 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475406 glCompressedTexImage2D(
5407 target, level, internal_format, width, height, border, image_size, data);
[email protected]cadde4a2010-07-31 17:10:435408 GLenum error = glGetError();
5409 if (error == GL_NO_ERROR) {
5410 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115411 feature_info_,
[email protected]cadde4a2010-07-31 17:10:435412 info, target, level, internal_format, width, height, 1, border, 0, 0);
5413 }
[email protected]a93bb842010-02-16 23:03:475414 return error::kNoError;
5415}
5416
[email protected]f7a64ee2010-02-01 22:24:145417error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195418 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
5419 GLenum target = static_cast<GLenum>(c.target);
5420 GLint level = static_cast<GLint>(c.level);
5421 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5422 GLsizei width = static_cast<GLsizei>(c.width);
5423 GLsizei height = static_cast<GLsizei>(c.height);
5424 GLint border = static_cast<GLint>(c.border);
5425 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
5426 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5427 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5428 const void* data = NULL;
5429 if (data_shm_id != 0 || data_shm_offset != 0) {
5430 data = GetSharedMemoryAs<const void*>(
5431 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:465432 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145433 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195434 }
5435 }
[email protected]a93bb842010-02-16 23:03:475436 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195437 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:195438}
5439
[email protected]f7a64ee2010-02-01 22:24:145440error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195441 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
5442 GLenum target = static_cast<GLenum>(c.target);
5443 GLint level = static_cast<GLint>(c.level);
5444 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5445 GLsizei width = static_cast<GLsizei>(c.width);
5446 GLsizei height = static_cast<GLsizei>(c.height);
5447 GLint border = static_cast<GLint>(c.border);
5448 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:305449 const void* data = GetImmediateDataAs<const void*>(
5450 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465451 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145452 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465453 }
[email protected]a93bb842010-02-16 23:03:475454 return DoCompressedTexImage2D(
5455 target, level, internal_format, width, height, border, image_size, data);
5456}
5457
[email protected]b6140d02010-05-17 14:47:165458error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
5459 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
5460 GLenum target = static_cast<GLenum>(c.target);
5461 GLint level = static_cast<GLint>(c.level);
5462 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5463 GLsizei width = static_cast<GLsizei>(c.width);
5464 GLsizei height = static_cast<GLsizei>(c.height);
5465 GLint border = static_cast<GLint>(c.border);
5466 Bucket* bucket = GetBucket(c.bucket_id);
5467 return DoCompressedTexImage2D(
5468 target, level, internal_format, width, height, border,
5469 bucket->size(), bucket->GetData(0, bucket->size()));
5470}
5471
5472error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
5473 uint32 immediate_data_size,
5474 const gles2::CompressedTexSubImage2DBucket& c) {
5475 GLenum target = static_cast<GLenum>(c.target);
5476 GLint level = static_cast<GLint>(c.level);
5477 GLint xoffset = static_cast<GLint>(c.xoffset);
5478 GLint yoffset = static_cast<GLint>(c.yoffset);
5479 GLsizei width = static_cast<GLsizei>(c.width);
5480 GLsizei height = static_cast<GLsizei>(c.height);
5481 GLenum format = static_cast<GLenum>(c.format);
5482 Bucket* bucket = GetBucket(c.bucket_id);
5483 uint32 data_size = bucket->size();
5484 GLsizei imageSize = data_size;
5485 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:055486 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:165487 SetGLError(
5488 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
5489 return error::kNoError;
5490 }
[email protected]9438b012010-06-15 22:55:055491 if (!validators_->compressed_texture_format.IsValid(format)) {
5492 SetGLError(GL_INVALID_ENUM,
5493 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
5494 return error::kNoError;
5495 }
[email protected]b6140d02010-05-17 14:47:165496 if (width < 0) {
5497 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
5498 return error::kNoError;
5499 }
5500 if (height < 0) {
5501 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
5502 return error::kNoError;
5503 }
5504 if (imageSize < 0) {
5505 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
5506 return error::kNoError;
5507 }
[email protected]cadde4a2010-07-31 17:10:435508 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:165509 target, level, xoffset, yoffset, width, height, format, imageSize, data);
5510 return error::kNoError;
5511}
5512
[email protected]a93bb842010-02-16 23:03:475513error::Error GLES2DecoderImpl::DoTexImage2D(
5514 GLenum target,
5515 GLint level,
5516 GLenum internal_format,
5517 GLsizei width,
5518 GLsizei height,
5519 GLint border,
5520 GLenum format,
5521 GLenum type,
5522 const void* pixels,
5523 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:055524 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295525 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
5526 return error::kNoError;
5527 }
[email protected]9438b012010-06-15 22:55:055528 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295529 SetGLError(GL_INVALID_ENUM,
5530 "glTexImage2D: internal_format GL_INVALID_ENUM");
5531 return error::kNoError;
5532 }
[email protected]9438b012010-06-15 22:55:055533 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295534 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
5535 return error::kNoError;
5536 }
[email protected]9438b012010-06-15 22:55:055537 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295538 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145539 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195540 }
[email protected]7b92c412010-07-20 17:48:255541 if (format != internal_format) {
5542 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
5543 return error::kNoError;
5544 }
[email protected]915a59a12010-09-30 21:29:115545 if (!texture_manager()->ValidForTarget(
5546 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475547 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295548 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475549 return error::kNoError;
5550 }
[email protected]3916c97e2010-02-25 03:20:505551 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475552 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295553 SetGLError(GL_INVALID_OPERATION,
5554 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:475555 return error::kNoError;
5556 }
5557 scoped_array<int8> zero;
5558 if (!pixels) {
5559 zero.reset(new int8[pixels_size]);
5560 memset(zero.get(), 0, pixels_size);
5561 pixels = zero.get();
5562 }
[email protected]876f6fee2010-08-02 23:10:325563
[email protected]f5719fb2010-08-04 18:27:185564 GLenum gl_internal_format = internal_format;
[email protected]876f6fee2010-08-02 23:10:325565 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
5566 if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
[email protected]f5719fb2010-08-04 18:27:185567 gl_internal_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:325568 } else if (type == GL_FLOAT) {
5569 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:185570 gl_internal_format = GL_RGBA32F_ARB;
[email protected]876f6fee2010-08-02 23:10:325571 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:185572 gl_internal_format = GL_RGB32F_ARB;
[email protected]876f6fee2010-08-02 23:10:325573 }
5574 } else if (type == GL_HALF_FLOAT_OES) {
5575 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:185576 gl_internal_format = GL_RGBA16F_ARB;
[email protected]876f6fee2010-08-02 23:10:325577 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:185578 gl_internal_format = GL_RGB16F_ARB;
[email protected]876f6fee2010-08-02 23:10:325579 }
[email protected]7b92c412010-07-20 17:48:255580 }
[email protected]7488d962010-07-16 02:41:585581 }
[email protected]876f6fee2010-08-02 23:10:325582
[email protected]cadde4a2010-07-31 17:10:435583 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475584 glTexImage2D(
[email protected]f5719fb2010-08-04 18:27:185585 target, level, gl_internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475586 pixels);
[email protected]cadde4a2010-07-31 17:10:435587 GLenum error = glGetError();
5588 if (error == GL_NO_ERROR) {
[email protected]915a59a12010-09-30 21:29:115589 texture_manager()->SetLevelInfo(feature_info_, info,
[email protected]cadde4a2010-07-31 17:10:435590 target, level, internal_format, width, height, 1, border, format, type);
[email protected]b493ee622011-04-13 23:52:005591 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:435592 }
[email protected]f7a64ee2010-02-01 22:24:145593 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195594}
5595
[email protected]f7a64ee2010-02-01 22:24:145596error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195597 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:585598 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:005599 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:195600 GLenum target = static_cast<GLenum>(c.target);
5601 GLint level = static_cast<GLint>(c.level);
5602 GLint internal_format = static_cast<GLint>(c.internalformat);
5603 GLsizei width = static_cast<GLsizei>(c.width);
5604 GLsizei height = static_cast<GLsizei>(c.height);
5605 GLint border = static_cast<GLint>(c.border);
5606 GLenum format = static_cast<GLenum>(c.format);
5607 GLenum type = static_cast<GLenum>(c.type);
5608 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
5609 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:185610 uint32 pixels_size;
5611 if (!GLES2Util::ComputeImageDataSize(
5612 width, height, format, type, unpack_alignment_, &pixels_size)) {
5613 return error::kOutOfBounds;
5614 }
[email protected]b9849abf2009-11-25 19:13:195615 const void* pixels = NULL;
5616 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
5617 pixels = GetSharedMemoryAs<const void*>(
5618 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:465619 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145620 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195621 }
5622 }
[email protected]a93bb842010-02-16 23:03:475623 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195624 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475625 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:195626}
5627
[email protected]f7a64ee2010-02-01 22:24:145628error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195629 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
5630 GLenum target = static_cast<GLenum>(c.target);
5631 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:465632 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:195633 GLsizei width = static_cast<GLsizei>(c.width);
5634 GLsizei height = static_cast<GLsizei>(c.height);
5635 GLint border = static_cast<GLint>(c.border);
5636 GLenum format = static_cast<GLenum>(c.format);
5637 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:185638 uint32 size;
5639 if (!GLES2Util::ComputeImageDataSize(
5640 width, height, format, type, unpack_alignment_, &size)) {
5641 return error::kOutOfBounds;
5642 }
[email protected]07f54fcc2009-12-22 02:46:305643 const void* pixels = GetImmediateDataAs<const void*>(
5644 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465645 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145646 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465647 }
[email protected]a93bb842010-02-16 23:03:475648 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:465649 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475650 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:145651 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325652}
5653
[email protected]cadde4a2010-07-31 17:10:435654void GLES2DecoderImpl::DoCompressedTexSubImage2D(
5655 GLenum target,
5656 GLint level,
5657 GLint xoffset,
5658 GLint yoffset,
5659 GLsizei width,
5660 GLsizei height,
5661 GLenum format,
5662 GLsizei image_size,
5663 const void * data) {
5664 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5665 if (!info) {
5666 SetGLError(GL_INVALID_OPERATION,
5667 "glCompressedTexSubImage2D: unknown texture for target");
5668 return;
5669 }
5670 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:525671 GLenum internal_format = 0;
5672 if (!info->GetLevelType(target, level, &type, &internal_format)) {
5673 SetGLError(
5674 GL_INVALID_OPERATION,
5675 "glCompressdTexSubImage2D: level does not exist.");
5676 return;
5677 }
5678 if (internal_format != format) {
5679 SetGLError(
5680 GL_INVALID_OPERATION,
5681 "glCompressdTexSubImage2D: format does not match internal format.");
5682 return;
5683 }
5684 if (!info->ValidForTexture(
5685 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:435686 SetGLError(GL_INVALID_VALUE,
5687 "glCompressdTexSubImage2D: bad dimensions.");
5688 return;
5689 }
5690 glCompressedTexSubImage2D(
5691 target, level, xoffset, yoffset, width, height, format, image_size, data);
5692}
5693
[email protected]6e288612010-12-21 20:45:035694static void Clip(
5695 GLint start, GLint range, GLint sourceRange,
5696 GLint* out_start, GLint* out_range) {
5697 DCHECK(out_start);
5698 DCHECK(out_range);
5699 if (start < 0) {
5700 range += start;
5701 start = 0;
5702 }
5703 GLint end = start + range;
5704 if (end > sourceRange) {
5705 range -= end - sourceRange;
5706 }
5707 *out_start = start;
5708 *out_range = range;
5709}
5710
5711
[email protected]cadde4a2010-07-31 17:10:435712void GLES2DecoderImpl::DoCopyTexImage2D(
5713 GLenum target,
5714 GLint level,
5715 GLenum internal_format,
5716 GLint x,
5717 GLint y,
5718 GLsizei width,
5719 GLsizei height,
5720 GLint border) {
5721 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5722 if (!info) {
5723 SetGLError(GL_INVALID_OPERATION,
5724 "glCopyTexImage2D: unknown texture for target");
5725 return;
5726 }
[email protected]915a59a12010-09-30 21:29:115727 if (!texture_manager()->ValidForTarget(
5728 feature_info_, target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:185729 border != 0) {
5730 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
5731 return;
5732 }
5733
[email protected]9edc6b22010-12-23 02:00:265734 // Check we have compatible formats.
5735 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5736 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5737 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
5738
5739 if ((channels_needed & channels_exist) != channels_needed) {
5740 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
5741 return;
5742 }
5743
[email protected]cadde4a2010-07-31 17:10:435744 CopyRealGLErrorsToWrapper();
[email protected]c0701082011-04-20 00:34:525745 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]6e288612010-12-21 20:45:035746 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:265747
5748 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:035749 GLint copyX = 0;
5750 GLint copyY = 0;
5751 GLint copyWidth = 0;
5752 GLint copyHeight = 0;
5753 Clip(x, width, size.width(), &copyX, &copyWidth);
5754 Clip(y, height, size.height(), &copyY, &copyHeight);
5755
5756 if (copyX != x ||
5757 copyY != y ||
5758 copyWidth != width ||
5759 copyHeight != height) {
5760 // some part was clipped so clear the texture.
5761 uint32 pixels_size = 0;
5762 if (!GLES2Util::ComputeImageDataSize(
5763 width, height, internal_format, GL_UNSIGNED_BYTE,
5764 unpack_alignment_, &pixels_size)) {
5765 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions too large");
5766 return;
5767 }
5768 scoped_array<char> zero(new char[pixels_size]);
5769 memset(zero.get(), 0, pixels_size);
5770 glTexImage2D(target, level, internal_format, width, height, 0,
5771 internal_format, GL_UNSIGNED_BYTE, zero.get());
5772 if (copyHeight > 0 && copyWidth > 0) {
5773 GLint dx = copyX - x;
5774 GLint dy = copyY - y;
5775 GLint destX = dx;
5776 GLint destY = dy;
5777 glCopyTexSubImage2D(target, level,
5778 destX, destY, copyX, copyY,
5779 copyWidth, copyHeight);
5780 }
5781 } else {
5782 glCopyTexImage2D(target, level, internal_format,
5783 copyX, copyY, copyWidth, copyHeight, border);
5784 }
[email protected]cadde4a2010-07-31 17:10:435785 GLenum error = glGetError();
5786 if (error == GL_NO_ERROR) {
5787 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115788 feature_info_, info, target, level, internal_format, width, height, 1,
5789 border, internal_format, GL_UNSIGNED_BYTE);
[email protected]cadde4a2010-07-31 17:10:435790 }
5791}
5792
5793void GLES2DecoderImpl::DoCopyTexSubImage2D(
5794 GLenum target,
5795 GLint level,
5796 GLint xoffset,
5797 GLint yoffset,
5798 GLint x,
5799 GLint y,
5800 GLsizei width,
5801 GLsizei height) {
5802 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5803 if (!info) {
5804 SetGLError(GL_INVALID_OPERATION,
5805 "glCopyTexSubImage2D: unknown texture for target");
5806 return;
5807 }
5808 GLenum type = 0;
5809 GLenum format = 0;
5810 if (!info->GetLevelType(target, level, &type, &format) ||
5811 !info->ValidForTexture(
5812 target, level, xoffset, yoffset, width, height, format, type)) {
5813 SetGLError(GL_INVALID_VALUE,
5814 "glCopyTexSubImage2D: bad dimensions.");
5815 return;
5816 }
[email protected]9edc6b22010-12-23 02:00:265817
5818 // Check we have compatible formats.
5819 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5820 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5821 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
5822
5823 if ((channels_needed & channels_exist) != channels_needed) {
5824 SetGLError(
5825 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
5826 return;
5827 }
5828
[email protected]c0701082011-04-20 00:34:525829 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]6e288612010-12-21 20:45:035830 gfx::Size size = GetBoundReadFrameBufferSize();
5831 GLint copyX = 0;
5832 GLint copyY = 0;
5833 GLint copyWidth = 0;
5834 GLint copyHeight = 0;
5835 Clip(x, width, size.width(), &copyX, &copyWidth);
5836 Clip(y, height, size.height(), &copyY, &copyHeight);
5837 if (copyX != x ||
5838 copyY != y ||
5839 copyWidth != width ||
5840 copyHeight != height) {
5841 // some part was clipped so clear the texture.
5842 uint32 pixels_size = 0;
5843 if (!GLES2Util::ComputeImageDataSize(
5844 width, height, format, type, unpack_alignment_, &pixels_size)) {
5845 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
5846 return;
5847 }
5848 scoped_array<char> zero(new char[pixels_size]);
5849 memset(zero.get(), 0, pixels_size);
5850 glTexSubImage2D(
5851 target, level, xoffset, yoffset, width, height,
5852 format, type, zero.get());
5853 }
5854 if (copyHeight > 0 && copyWidth > 0) {
5855 GLint dx = copyX - x;
5856 GLint dy = copyY - y;
5857 GLint destX = xoffset + dx;
5858 GLint destY = yoffset + dy;
5859 glCopyTexSubImage2D(target, level,
5860 destX, destY, copyX, copyY,
5861 copyWidth, copyHeight);
5862 }
[email protected]cadde4a2010-07-31 17:10:435863}
5864
5865void GLES2DecoderImpl::DoTexSubImage2D(
5866 GLenum target,
5867 GLint level,
5868 GLint xoffset,
5869 GLint yoffset,
5870 GLsizei width,
5871 GLsizei height,
5872 GLenum format,
5873 GLenum type,
5874 const void * data) {
5875 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5876 if (!info) {
5877 SetGLError(GL_INVALID_OPERATION,
5878 "glTexSubImage2D: unknown texture for target");
5879 return;
5880 }
[email protected]df6cf1ad2011-01-29 01:20:525881 GLenum current_type = 0;
5882 GLenum internal_format = 0;
5883 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
5884 SetGLError(
5885 GL_INVALID_OPERATION,
5886 "glTexSubImage2D: level does not exist.");
5887 return;
5888 }
5889 if (format != internal_format) {
5890 SetGLError(GL_INVALID_OPERATION,
5891 "glTexSubImage2D: format does not match internal format.");
5892 return;
5893 }
5894 if (type != current_type) {
5895 SetGLError(GL_INVALID_OPERATION,
5896 "glTexSubImage2D: type does not match type of texture.");
5897 return;
5898 }
5899
[email protected]cadde4a2010-07-31 17:10:435900 if (!info->ValidForTexture(
5901 target, level, xoffset, yoffset, width, height, format, type)) {
5902 SetGLError(GL_INVALID_VALUE,
5903 "glTexSubImage2D: bad dimensions.");
5904 return;
5905 }
5906 glTexSubImage2D(
5907 target, level, xoffset, yoffset, width, height, format, type, data);
5908}
5909
[email protected]b493ee622011-04-13 23:52:005910error::Error GLES2DecoderImpl::HandleTexSubImage2D(
5911 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:585912 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:005913 GLboolean internal = static_cast<GLboolean>(c.internal);
5914 if (internal == GL_TRUE && tex_image_2d_failed_)
5915 return error::kNoError;
5916
5917 GLenum target = static_cast<GLenum>(c.target);
5918 GLint level = static_cast<GLint>(c.level);
5919 GLint xoffset = static_cast<GLint>(c.xoffset);
5920 GLint yoffset = static_cast<GLint>(c.yoffset);
5921 GLsizei width = static_cast<GLsizei>(c.width);
5922 GLsizei height = static_cast<GLsizei>(c.height);
5923 GLenum format = static_cast<GLenum>(c.format);
5924 GLenum type = static_cast<GLenum>(c.type);
5925 uint32 data_size;
5926 if (!GLES2Util::ComputeImageDataSize(
5927 width, height, format, type, unpack_alignment_, &data_size)) {
5928 return error::kOutOfBounds;
5929 }
5930 const void* pixels = GetSharedMemoryAs<const void*>(
5931 c.pixels_shm_id, c.pixels_shm_offset, data_size);
5932 if (!validators_->texture_target.IsValid(target)) {
5933 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
5934 return error::kNoError;
5935 }
5936 if (width < 0) {
5937 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
5938 return error::kNoError;
5939 }
5940 if (height < 0) {
5941 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
5942 return error::kNoError;
5943 }
5944 if (!validators_->texture_format.IsValid(format)) {
5945 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
5946 return error::kNoError;
5947 }
5948 if (!validators_->pixel_type.IsValid(type)) {
5949 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
5950 return error::kNoError;
5951 }
5952 if (pixels == NULL) {
5953 return error::kOutOfBounds;
5954 }
5955 DoTexSubImage2D(
5956 target, level, xoffset, yoffset, width, height, format, type, pixels);
5957 return error::kNoError;
5958}
5959
5960error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
5961 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
5962 GLboolean internal = static_cast<GLboolean>(c.internal);
5963 if (internal == GL_TRUE && tex_image_2d_failed_)
5964 return error::kNoError;
5965
5966 GLenum target = static_cast<GLenum>(c.target);
5967 GLint level = static_cast<GLint>(c.level);
5968 GLint xoffset = static_cast<GLint>(c.xoffset);
5969 GLint yoffset = static_cast<GLint>(c.yoffset);
5970 GLsizei width = static_cast<GLsizei>(c.width);
5971 GLsizei height = static_cast<GLsizei>(c.height);
5972 GLenum format = static_cast<GLenum>(c.format);
5973 GLenum type = static_cast<GLenum>(c.type);
5974 uint32 data_size;
5975 if (!GLES2Util::ComputeImageDataSize(
5976 width, height, format, type, unpack_alignment_, &data_size)) {
5977 return error::kOutOfBounds;
5978 }
5979 const void* pixels = GetImmediateDataAs<const void*>(
5980 c, data_size, immediate_data_size);
5981 if (!validators_->texture_target.IsValid(target)) {
5982 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
5983 return error::kNoError;
5984 }
5985 if (width < 0) {
5986 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
5987 return error::kNoError;
5988 }
5989 if (height < 0) {
5990 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
5991 return error::kNoError;
5992 }
5993 if (!validators_->texture_format.IsValid(format)) {
5994 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
5995 return error::kNoError;
5996 }
5997 if (!validators_->pixel_type.IsValid(type)) {
5998 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
5999 return error::kNoError;
6000 }
6001 if (pixels == NULL) {
6002 return error::kOutOfBounds;
6003 }
6004 DoTexSubImage2D(
6005 target, level, xoffset, yoffset, width, height, format, type, pixels);
6006 return error::kNoError;
6007}
6008
[email protected]f7a64ee2010-02-01 22:24:146009error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:196010 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:366011 GLuint index = static_cast<GLuint>(c.index);
6012 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:256013 typedef gles2::GetVertexAttribPointerv::Result Result;
6014 Result* result = GetSharedMemoryAs<Result*>(
6015 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:366016 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:146017 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:366018 }
[email protected]07d0cc82010-02-17 04:51:406019 // Check that the client initialized the result.
6020 if (result->size != 0) {
6021 return error::kInvalidArguments;
6022 }
[email protected]9438b012010-06-15 22:55:056023 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296024 SetGLError(GL_INVALID_ENUM,
6025 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146026 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366027 }
[email protected]3916c97e2010-02-25 03:20:506028 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:296029 SetGLError(GL_INVALID_VALUE,
6030 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:146031 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366032 }
[email protected]0bfd9882010-02-05 23:02:256033 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:086034 *result->GetData() =
6035 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:146036 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326037}
6038
[email protected]f7b85372010-02-03 01:11:376039bool GLES2DecoderImpl::GetUniformSetup(
6040 GLuint program, GLint location,
6041 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:106042 error::Error* error, GLuint* service_id, void** result_pointer,
6043 GLenum* result_type) {
6044 DCHECK(error);
6045 DCHECK(service_id);
6046 DCHECK(result_pointer);
6047 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:376048 *error = error::kNoError;
6049 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:256050 SizedResult<GLint>* result;
6051 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6052 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
6053 if (!result) {
[email protected]f7b85372010-02-03 01:11:376054 *error = error::kOutOfBounds;
6055 return false;
6056 }
[email protected]0bfd9882010-02-05 23:02:256057 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:376058 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:256059 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:586060 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6061 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:376062 if (!info) {
[email protected]ae51d192010-04-27 00:48:036063 return false;
6064 }
6065 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:376066 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:296067 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:376068 return false;
6069 }
[email protected]ae51d192010-04-27 00:48:036070 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:366071 GLint array_index = -1;
6072 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6073 info->GetUniformInfoByLocation(location, &array_index);
6074 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:376075 // No such location.
[email protected]8eee29c2010-04-29 03:38:296076 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:376077 return false;
6078 }
[email protected]43c2f1f2011-03-25 18:35:366079 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:506080 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:376081 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:296082 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:376083 return false;
6084 }
[email protected]0bfd9882010-02-05 23:02:256085 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6086 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
6087 if (!result) {
[email protected]f7b85372010-02-03 01:11:376088 *error = error::kOutOfBounds;
6089 return false;
6090 }
[email protected]0bfd9882010-02-05 23:02:256091 result->size = size;
[email protected]939e7362010-05-13 20:49:106092 *result_type = type;
[email protected]f7b85372010-02-03 01:11:376093 return true;
6094}
6095
[email protected]f7a64ee2010-02-01 22:24:146096error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:196097 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:376098 GLuint program = c.program;
6099 GLint location = c.location;
6100 GLuint service_id;
[email protected]939e7362010-05-13 20:49:106101 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376102 Error error;
[email protected]0bfd9882010-02-05 23:02:256103 void* result;
[email protected]f7b85372010-02-03 01:11:376104 if (GetUniformSetup(
6105 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106106 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:256107 glGetUniformiv(
6108 service_id, location,
6109 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:376110 }
6111 return error;
[email protected]96449d2c2009-11-25 00:01:326112}
6113
[email protected]f7a64ee2010-02-01 22:24:146114error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:196115 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:376116 GLuint program = c.program;
6117 GLint location = c.location;
6118 GLuint service_id;
6119 Error error;
[email protected]0bfd9882010-02-05 23:02:256120 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:106121 Result* result;
6122 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376123 if (GetUniformSetup(
6124 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106125 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
6126 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
6127 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
6128 GLsizei num_values = result->GetNumResults();
6129 scoped_array<GLint> temp(new GLint[num_values]);
6130 glGetUniformiv(service_id, location, temp.get());
6131 GLfloat* dst = result->GetData();
6132 for (GLsizei ii = 0; ii < num_values; ++ii) {
6133 dst[ii] = (temp[ii] != 0);
6134 }
6135 } else {
6136 glGetUniformfv(service_id, location, result->GetData());
6137 }
[email protected]f7b85372010-02-03 01:11:376138 }
6139 return error;
[email protected]96449d2c2009-11-25 00:01:326140}
6141
[email protected]f7a64ee2010-02-01 22:24:146142error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:196143 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:256144 GLenum shader_type = static_cast<GLenum>(c.shadertype);
6145 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
6146 typedef gles2::GetShaderPrecisionFormat::Result Result;
6147 Result* result = GetSharedMemoryAs<Result*>(
6148 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6149 if (!result) {
6150 return error::kOutOfBounds;
6151 }
[email protected]07d0cc82010-02-17 04:51:406152 // Check that the client initialized the result.
6153 if (result->success != 0) {
6154 return error::kInvalidArguments;
6155 }
[email protected]9438b012010-06-15 22:55:056156 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:296157 SetGLError(GL_INVALID_ENUM,
6158 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
6159 return error::kNoError;
6160 }
[email protected]9438b012010-06-15 22:55:056161 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:296162 SetGLError(GL_INVALID_ENUM,
6163 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
6164 return error::kNoError;
6165 }
6166
6167 result->success = 1; // true
6168 switch (precision_type) {
6169 case GL_LOW_INT:
6170 case GL_MEDIUM_INT:
6171 case GL_HIGH_INT:
6172 result->min_range = -31;
6173 result->max_range = 31;
6174 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:106175 break;
[email protected]8eee29c2010-04-29 03:38:296176 case GL_LOW_FLOAT:
6177 case GL_MEDIUM_FLOAT:
6178 case GL_HIGH_FLOAT:
6179 result->min_range = -62;
6180 result->max_range = 62;
6181 result->precision = -16;
6182 break;
6183 default:
6184 NOTREACHED();
6185 break;
[email protected]0bfd9882010-02-05 23:02:256186 }
[email protected]f7a64ee2010-02-01 22:24:146187 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326188}
6189
[email protected]f7a64ee2010-02-01 22:24:146190error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:196191 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:256192 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:586193 GLuint program = static_cast<GLuint>(c.program);
6194 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6195 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:036196 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256197 return error::kNoError;
6198 }
6199 typedef gles2::GetAttachedShaders::Result Result;
6200 uint32 max_count = Result::ComputeMaxResults(result_size);
6201 Result* result = GetSharedMemoryAs<Result*>(
6202 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
6203 if (!result) {
6204 return error::kOutOfBounds;
6205 }
[email protected]07d0cc82010-02-17 04:51:406206 // Check that the client initialized the result.
6207 if (result->size != 0) {
6208 return error::kInvalidArguments;
6209 }
[email protected]0bfd9882010-02-05 23:02:256210 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:036211 glGetAttachedShaders(
6212 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:256213 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:036214 if (!shader_manager()->GetClientId(result->GetData()[ii],
6215 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:256216 NOTREACHED();
6217 return error::kGenericError;
6218 }
6219 }
6220 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:146221 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326222}
6223
[email protected]f7a64ee2010-02-01 22:24:146224error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:196225 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:256226 GLuint program = c.program;
6227 GLuint index = c.index;
6228 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256229 typedef gles2::GetActiveUniform::Result Result;
6230 Result* result = GetSharedMemoryAs<Result*>(
6231 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6232 if (!result) {
6233 return error::kOutOfBounds;
6234 }
[email protected]07d0cc82010-02-17 04:51:406235 // Check that the client initialized the result.
6236 if (result->success != 0) {
6237 return error::kInvalidArguments;
6238 }
[email protected]6b8cf1a2010-05-06 16:13:586239 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6240 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:036241 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256242 return error::kNoError;
6243 }
6244 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6245 info->GetUniformInfo(index);
6246 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:296247 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:256248 return error::kNoError;
6249 }
6250 result->success = 1; // true.
6251 result->size = uniform_info->size;
6252 result->type = uniform_info->type;
6253 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296254 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146255 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326256}
6257
[email protected]f7a64ee2010-02-01 22:24:146258error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:196259 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:256260 GLuint program = c.program;
6261 GLuint index = c.index;
6262 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256263 typedef gles2::GetActiveAttrib::Result Result;
6264 Result* result = GetSharedMemoryAs<Result*>(
6265 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6266 if (!result) {
6267 return error::kOutOfBounds;
6268 }
[email protected]07d0cc82010-02-17 04:51:406269 // Check that the client initialized the result.
6270 if (result->success != 0) {
6271 return error::kInvalidArguments;
6272 }
[email protected]6b8cf1a2010-05-06 16:13:586273 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6274 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:036275 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256276 return error::kNoError;
6277 }
6278 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
6279 info->GetAttribInfo(index);
6280 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:296281 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:256282 return error::kNoError;
6283 }
6284 result->success = 1; // true.
6285 result->size = attrib_info->size;
6286 result->type = attrib_info->type;
6287 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296288 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146289 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326290}
6291
[email protected]b273e432010-04-12 17:23:586292error::Error GLES2DecoderImpl::HandleShaderBinary(
6293 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
6294#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:296295 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:586296 return error::kNoError;
6297#else
6298 GLsizei n = static_cast<GLsizei>(c.n);
6299 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:296300 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:586301 return error::kNoError;
6302 }
6303 GLsizei length = static_cast<GLsizei>(c.length);
6304 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:296305 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:586306 return error::kNoError;
6307 }
6308 uint32 data_size;
6309 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
6310 return error::kOutOfBounds;
6311 }
6312 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
6313 c.shaders_shm_id, c.shaders_shm_offset, data_size);
6314 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
6315 const void* binary = GetSharedMemoryAs<const void*>(
6316 c.binary_shm_id, c.binary_shm_offset, length);
6317 if (shaders == NULL || binary == NULL) {
6318 return error::kOutOfBounds;
6319 }
6320 scoped_array<GLuint> service_ids(new GLuint[n]);
6321 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:036322 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
6323 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296324 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:586325 return error::kNoError;
6326 }
[email protected]ae51d192010-04-27 00:48:036327 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:586328 }
6329 // TODO(gman): call glShaderBinary
6330 return error::kNoError;
6331#endif
6332}
6333
[email protected]6217d392010-03-25 22:08:356334error::Error GLES2DecoderImpl::HandleSwapBuffers(
6335 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:496336 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
6337 int this_frame_number = frame_number_++;
6338 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
6339 "offscreen", is_offscreen,
6340 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:356341 // If offscreen then don't actually SwapBuffers to the display. Just copy
6342 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:496343 if (is_offscreen) {
[email protected]6217d392010-03-25 22:08:356344 ScopedGLErrorSuppressor suppressor(this);
6345
6346 // First check to see if a deferred offscreen render buffer resize is
6347 // pending.
[email protected]d0498742010-09-20 20:27:016348 if (!UpdateOffscreenFrameBufferSize()) {
6349 LOG(ERROR) << "Context lost because reallocation of offscreen FBO "
6350 << "failed.";
[email protected]6217d392010-03-25 22:08:356351 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016352 }
[email protected]6217d392010-03-25 22:08:356353
[email protected]34ff8b0c2010-10-01 20:06:026354 if (IsOffscreenBufferMultisampled()) {
6355 // For multisampled buffers, bind the resolved frame buffer so that
6356 // callbacks can call ReadPixels or CopyTexImage2D.
[email protected]c0701082011-04-20 00:34:526357 ScopedResolvedFrameBufferBinder binder(this, true);
[email protected]34ff8b0c2010-10-01 20:06:026358 if (swap_buffers_callback_.get()) {
6359 swap_buffers_callback_->Run();
6360 }
[email protected]89d6ed02011-04-20 00:23:236361 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:486362 } else {
[email protected]0c8c9d22010-06-25 17:36:396363 ScopedFrameBufferBinder binder(this,
6364 offscreen_target_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:406365
[email protected]b86b14982010-10-11 18:45:486366 if (parent_) {
6367 // Copy the target frame buffer to the saved offscreen texture.
6368 offscreen_saved_color_texture_->Copy(
6369 offscreen_saved_color_texture_->size());
6370
[email protected]a3ded6d2010-10-19 06:44:396371 // Ensure the side effects of the copy are visible to the parent
6372 // context. There is no need to do this for ANGLE because it uses a
6373 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:486374 if (!IsAngle())
6375 glFlush();
6376 }
6377
6378 // Run the callback with |binder| in scope, so that the callback can call
6379 // ReadPixels or CopyTexImage2D.
6380 if (swap_buffers_callback_.get()) {
6381 swap_buffers_callback_->Run();
6382 }
[email protected]89d6ed02011-04-20 00:23:236383 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:396384 }
[email protected]6217d392010-03-25 22:08:356385 } else {
[email protected]64ace852011-05-19 21:49:496386 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]d0498742010-09-20 20:27:016387 if (!context_->SwapBuffers()) {
6388 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:026389 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016390 }
[email protected]6217d392010-03-25 22:08:356391 }
6392
6393 if (swap_buffers_callback_.get()) {
6394 swap_buffers_callback_->Run();
6395 }
6396
[email protected]89d6ed02011-04-20 00:23:236397 return error::kNoError;
[email protected]6217d392010-03-25 22:08:356398}
6399
[email protected]1e6f58d2011-03-24 00:00:406400error::Error GLES2DecoderImpl::HandleSetLatchCHROMIUM(
6401 uint32 immediate_data_size, const gles2::SetLatchCHROMIUM& c) {
[email protected]366ae242011-05-10 02:23:586402 TRACE_EVENT0("gpu", "SetLatch");
[email protected]ce9eea602011-04-12 20:09:576403 // Ensure the side effects of previous commands are visible to other contexts.
6404 // There is no need to do this for ANGLE because it uses a
6405 // single D3D device for all contexts.
6406 if (!IsAngle())
6407 glFlush();
6408
6409 int32 shm_id = gpu::kLatchSharedMemoryId;
[email protected]1e6f58d2011-03-24 00:00:406410 uint32 latch_id = c.latch_id;
6411 uint32 shm_offset = 0;
6412 base::subtle::Atomic32* latch;
6413 if (!SafeMultiplyUint32(latch_id, sizeof(*latch), &shm_offset)) {
6414 return error::kOutOfBounds;
6415 }
6416 latch = GetSharedMemoryAs<base::subtle::Atomic32*>(
6417 shm_id, shm_offset, sizeof(*latch));
6418 if (!latch) {
6419 return error::kOutOfBounds;
6420 }
[email protected]80c49752011-04-18 23:55:106421 base::subtle::NoBarrier_Store(latch, 1);
6422 if (!latch_callback_.is_null())
6423 latch_callback_.Run(true);
[email protected]1e6f58d2011-03-24 00:00:406424 return error::kNoError;
6425}
6426
6427error::Error GLES2DecoderImpl::HandleWaitLatchCHROMIUM(
6428 uint32 immediate_data_size, const gles2::WaitLatchCHROMIUM& c) {
[email protected]366ae242011-05-10 02:23:586429 TRACE_EVENT0("gpu", "WaitLatch");
[email protected]ce9eea602011-04-12 20:09:576430 int32 shm_id = gpu::kLatchSharedMemoryId;
[email protected]1e6f58d2011-03-24 00:00:406431 uint32 latch_id = c.latch_id;
6432 uint32 shm_offset = 0;
6433 base::subtle::Atomic32* latch;
6434 if (!SafeMultiplyUint32(latch_id, sizeof(*latch), &shm_offset)) {
6435 return error::kOutOfBounds;
6436 }
6437 latch = GetSharedMemoryAs<base::subtle::Atomic32*>(
6438 shm_id, shm_offset, sizeof(*latch));
6439 if (!latch) {
6440 return error::kOutOfBounds;
6441 }
6442
6443 base::subtle::Atomic32 old =
6444 base::subtle::NoBarrier_CompareAndSwap(latch, 1, 0);
[email protected]80c49752011-04-18 23:55:106445 if (old == 0) {
6446 if (!latch_callback_.is_null())
6447 latch_callback_.Run(false);
6448 return error::kWaiting;
6449 } else {
6450 return error::kNoError;
6451 }
[email protected]1e6f58d2011-03-24 00:00:406452}
6453
[email protected]269200b12010-11-18 22:53:066454error::Error GLES2DecoderImpl::HandleCommandBufferEnableCHROMIUM(
6455 uint32 immediate_data_size, const gles2::CommandBufferEnableCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:186456 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]269200b12010-11-18 22:53:066457 typedef gles2::CommandBufferEnableCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:186458 Result* result = GetSharedMemoryAs<Result*>(
6459 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6460 if (!result) {
6461 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:106462 }
[email protected]b1d2dcb2010-05-17 19:24:186463 // Check that the client initialized the result.
6464 if (*result != 0) {
6465 return error::kInvalidArguments;
6466 }
6467 std::string feature_str;
6468 if (!bucket->GetAsString(&feature_str)) {
6469 return error::kInvalidArguments;
6470 }
6471
6472 // TODO(gman): make this some kind of table to function pointer thingy.
6473 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
6474 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]8fbedc02010-11-18 18:43:406475 } else if (feature_str.compare(PEPPER3D_SUPPORT_FIXED_ATTRIBS) == 0) {
6476 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
6477 // TODO(gman): decide how to remove the need for this const_cast.
6478 // I could make validators_ non const but that seems bad as this is the only
6479 // place it is needed. I could make some special friend class of validators
6480 // just to allow this to set them. That seems silly. I could refactor this
6481 // code to use the extension mechanism or the initialization attributes to
6482 // turn this feature on. Given that the only real point of this is to make
6483 // the conformance tests pass and given that there is lots of real work that
6484 // needs to be done it seems like refactoring for one to one of those
6485 // methods is a very low priority.
6486 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]b1d2dcb2010-05-17 19:24:186487 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
6488 use_shader_translator_ = false;
6489 } else {
6490 return error::kNoError;
6491 }
6492
6493 *result = 1; // true.
6494 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:106495}
6496
[email protected]c2f8c8402010-12-06 18:07:246497error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
6498 uint32 immediate_data_size,
6499 const gles2::GetRequestableExtensionsCHROMIUM& c) {
6500 Bucket* bucket = CreateBucket(c.bucket_id);
6501 scoped_ptr<FeatureInfo> info(new FeatureInfo());
[email protected]c410da802011-03-14 19:17:416502 info->Initialize(disallowed_extensions_, NULL);
[email protected]c2f8c8402010-12-06 18:07:246503 bucket->SetFromString(info->extensions().c_str());
6504 return error::kNoError;
6505}
6506
6507error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
6508 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
6509 Bucket* bucket = GetBucket(c.bucket_id);
6510 std::string feature_str;
6511 if (!bucket->GetAsString(&feature_str)) {
6512 return error::kInvalidArguments;
6513 }
6514
6515 bool std_derivatives_enabled =
6516 feature_info_->feature_flags().oes_standard_derivatives;
6517 bool webglsl_enabled =
6518 feature_info_->feature_flags().chromium_webglsl;
6519
6520 feature_info_->AddFeatures(feature_str.c_str());
6521
6522 // If we just enabled a feature which affects the shader translator,
6523 // we may need to re-initialize it.
6524 if (std_derivatives_enabled !=
6525 feature_info_->feature_flags().oes_standard_derivatives ||
6526 webglsl_enabled !=
6527 feature_info_->feature_flags().chromium_webglsl) {
6528 InitializeShaderTranslator();
6529 }
6530
6531 return error::kNoError;
6532}
6533
[email protected]96449d2c2009-11-25 00:01:326534// Include the auto-generated part of this file. We split this because it means
6535// we can easily edit the non-auto generated parts right here in this file
6536// instead of having to edit some template or the code generator.
6537#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
6538
6539} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:256540} // namespace gpu