blob: dec7c34f7940842a4e934029103da577c623072a [file] [log] [blame]
[email protected]4874aae2011-03-18 01:19:561// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]96449d2c2009-11-25 00:01:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]8a837bb2010-01-05 00:21:245#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
[email protected]74470702010-01-06 18:51:166
7#include <stdio.h>
8
[email protected]1aef98132010-02-23 18:00:079#include <algorithm>
[email protected]f39f4b3f2010-05-12 17:04:0810#include <list>
[email protected]96449d2c2009-11-25 00:01:3211#include <map>
[email protected]f39f4b3f2010-05-12 17:04:0812#include <string>
13#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0614
[email protected]1e6f58d2011-03-24 00:00:4015#include "base/atomicops.h"
[email protected]00eb49a2010-08-12 20:46:5716#include "base/at_exit.h"
[email protected]2041cf342010-02-19 03:15:5917#include "base/callback.h"
[email protected]3b63f8f42011-03-28 01:54:1518#include "base/memory/scoped_ptr.h"
19#include "base/memory/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0220#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3221#define GLES2_GPU_SERVICE 1
22#include "gpu/command_buffer/common/gles2_cmd_format.h"
23#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1024#include "gpu/command_buffer/common/id_allocator.h"
[email protected]366ae242011-05-10 02:23:5825#include "gpu/command_buffer/common/trace_event.h"
[email protected]3916c97e2010-02-25 03:20:5026#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3227#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5028#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1129#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5830#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3231#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4632#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4733#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5834#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4735#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4536#include "gpu/command_buffer/service/shader_translator.h"
[email protected]fbe20372011-06-01 01:46:3837#include "gpu/command_buffer/service/surface_manager.h"
[email protected]a93bb842010-02-16 23:03:4738#include "gpu/command_buffer/service/texture_manager.h"
[email protected]4e8a5b122010-05-08 22:00:1039#include "gpu/GLES2/gles2_command_buffer.h"
[email protected]5ae0b282011-03-28 19:24:4940#include "ui/gfx/gl/gl_context.h"
41#include "ui/gfx/gl/gl_implementation.h"
[email protected]f62a5ab2011-05-23 20:34:1542#include "ui/gfx/gl/gl_surface.h"
[email protected]de17df392010-04-23 21:09:4143
[email protected]6217d392010-03-25 22:08:3544#if !defined(GL_DEPTH24_STENCIL8)
45#define GL_DEPTH24_STENCIL8 0x88F0
46#endif
47
[email protected]a7a27ace2009-12-12 00:11:2548namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3249namespace gles2 {
50
[email protected]6217d392010-03-25 22:08:3551class GLES2DecoderImpl;
52
[email protected]07f54fcc2009-12-22 02:46:3053// Check that certain assumptions the code makes are true. There are places in
54// the code where shared memory is passed direclty to GL. Example, glUniformiv,
55// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
56// a few others) are 32bits. If they are not 32bits the code will have to change
57// to call those GL functions with service side memory and then copy the results
58// to shared memory, converting the sizes.
59COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
60 GLint_not_same_size_as_uint32);
61COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
62 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3763COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
64 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3065
[email protected]43f28f832010-02-03 02:28:4866// TODO(kbr): the use of this anonymous namespace core dumps the
67// linker on Mac OS X 10.6 when the symbol ordering file is used
68// namespace {
[email protected]96449d2c2009-11-25 00:01:3269
70// Returns the address of the first byte after a struct.
71template <typename T>
72const void* AddressAfterStruct(const T& pod) {
73 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
74}
75
[email protected]07f54fcc2009-12-22 02:46:3076// Returns the address of the frst byte after the struct or NULL if size >
77// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3278template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3079RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
80 uint32 size,
81 uint32 immediate_data_size) {
82 return (size <= immediate_data_size) ?
83 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
84 NULL;
[email protected]96449d2c2009-11-25 00:01:3285}
86
[email protected]07f54fcc2009-12-22 02:46:3087// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1888bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3289 GLuint count,
90 size_t size,
[email protected]a76b0052010-03-05 00:33:1891 unsigned int elements_per_unit,
92 uint32* dst) {
93 uint32 value;
94 if (!SafeMultiplyUint32(count, size, &value)) {
95 return false;
96 }
97 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
98 return false;
99 }
100 *dst = value;
101 return true;
[email protected]96449d2c2009-11-25 00:01:32102}
103
104// A struct to hold info about each command.
105struct CommandInfo {
106 int arg_flags; // How to handle the arguments for this command
107 int arg_count; // How many arguments are expected for this command.
108};
109
110// A table of CommandInfo for all the commands.
111const CommandInfo g_command_info[] = {
112 #define GLES2_CMD_OP(name) { \
113 name::kArgFlags, \
114 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
115
116 GLES2_COMMAND_LIST(GLES2_CMD_OP)
117
118 #undef GLES2_CMD_OP
119};
120
[email protected]34ff8b0c2010-10-01 20:06:02121static bool IsAngle() {
122#if defined(OS_WIN)
123 return gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
124#else
125 return false;
126#endif
127}
128
[email protected]6217d392010-03-25 22:08:35129// This class prevents any GL errors that occur when it is in scope from
130// being reported to the client.
131class ScopedGLErrorSuppressor {
132 public:
133 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
134 ~ScopedGLErrorSuppressor();
135 private:
136 GLES2DecoderImpl* decoder_;
137 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
138};
139
140// Temporarily changes a decoder's bound 2D texture and restore it when this
141// object goes out of scope. Also temporarily switches to using active texture
142// unit zero in case the client has changed that to something invalid.
143class ScopedTexture2DBinder {
144 public:
145 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
146 ~ScopedTexture2DBinder();
147
148 private:
149 GLES2DecoderImpl* decoder_;
150 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
151};
152
153// Temporarily changes a decoder's bound render buffer and restore it when this
154// object goes out of scope.
155class ScopedRenderBufferBinder {
156 public:
157 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
158 ~ScopedRenderBufferBinder();
159
160 private:
161 GLES2DecoderImpl* decoder_;
162 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
163};
164
165// Temporarily changes a decoder's bound frame buffer and restore it when this
166// object goes out of scope.
167class ScopedFrameBufferBinder {
168 public:
169 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
170 ~ScopedFrameBufferBinder();
171
172 private:
173 GLES2DecoderImpl* decoder_;
174 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
175};
176
[email protected]34ff8b0c2010-10-01 20:06:02177// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52178// the multisampled offscreen render buffer if that buffer is multisampled, and,
179// if it is bound or enforce_internal_framebuffer is true.
[email protected]34ff8b0c2010-10-01 20:06:02180class ScopedResolvedFrameBufferBinder {
181 public:
[email protected]c0701082011-04-20 00:34:52182 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
183 bool enforce_internal_framebuffer);
[email protected]34ff8b0c2010-10-01 20:06:02184 ~ScopedResolvedFrameBufferBinder();
185
186 private:
187 GLES2DecoderImpl* decoder_;
188 bool resolve_and_bind_;
189 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
190};
191
[email protected]6217d392010-03-25 22:08:35192// Encapsulates an OpenGL texture.
193class Texture {
194 public:
195 explicit Texture(GLES2DecoderImpl* decoder);
196 ~Texture();
197
198 // Create a new render texture.
199 void Create();
200
201 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02202 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35203
204 // Copy the contents of the currently bound frame buffer.
205 void Copy(const gfx::Size& size);
206
207 // Destroy the render texture. This must be explicitly called before
208 // destroying this object.
209 void Destroy();
210
[email protected]97872062010-11-03 19:07:05211 // Invalidate the texture. This can be used when a context is lost and it is
212 // not possible to make it current in order to free the resource.
213 void Invalidate();
214
[email protected]6217d392010-03-25 22:08:35215 GLuint id() const {
216 return id_;
217 }
218
[email protected]d37231fa2010-04-09 21:16:02219 gfx::Size size() const {
220 return size_;
221 }
222
[email protected]6217d392010-03-25 22:08:35223 private:
224 GLES2DecoderImpl* decoder_;
225 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02226 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35227 DISALLOW_COPY_AND_ASSIGN(Texture);
228};
229
230// Encapsulates an OpenGL render buffer of any format.
231class RenderBuffer {
232 public:
233 explicit RenderBuffer(GLES2DecoderImpl* decoder);
234 ~RenderBuffer();
235
236 // Create a new render buffer.
237 void Create();
238
239 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02240 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35241
242 // Destroy the render buffer. This must be explicitly called before destroying
243 // this object.
244 void Destroy();
245
[email protected]97872062010-11-03 19:07:05246 // Invalidate the render buffer. This can be used when a context is lost and
247 // it is not possible to make it current in order to free the resource.
248 void Invalidate();
249
[email protected]6217d392010-03-25 22:08:35250 GLuint id() const {
251 return id_;
252 }
253
254 private:
255 GLES2DecoderImpl* decoder_;
256 GLuint id_;
257 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
258};
259
260// Encapsulates an OpenGL frame buffer.
261class FrameBuffer {
262 public:
263 explicit FrameBuffer(GLES2DecoderImpl* decoder);
264 ~FrameBuffer();
265
266 // Create a new frame buffer.
267 void Create();
268
269 // Attach a color render buffer to a frame buffer.
270 void AttachRenderTexture(Texture* texture);
271
[email protected]b9363b22010-06-09 22:06:15272 // Attach a render buffer to a frame buffer. Note that this unbinds any
273 // currently bound frame buffer.
274 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35275
276 // Clear the given attached buffers.
277 void Clear(GLbitfield buffers);
278
279 // Destroy the frame buffer. This must be explicitly called before destroying
280 // this object.
281 void Destroy();
282
[email protected]97872062010-11-03 19:07:05283 // Invalidate the frame buffer. This can be used when a context is lost and it
284 // is not possible to make it current in order to free the resource.
285 void Invalidate();
286
[email protected]6217d392010-03-25 22:08:35287 // See glCheckFramebufferStatusEXT.
288 GLenum CheckStatus();
289
290 GLuint id() const {
291 return id_;
292 }
293
294 private:
295 GLES2DecoderImpl* decoder_;
296 GLuint id_;
297 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
298};
[email protected]34ff8b0c2010-10-01 20:06:02299
300class ContextCreationAttribParser {
301 public:
302 ContextCreationAttribParser();
303 bool Parse(const std::vector<int32>& attribs);
304
305 // -1 if invalid or unspecified.
306 int32 alpha_size_;
307 int32 blue_size_;
308 int32 green_size_;
309 int32 red_size_;
310 int32 depth_size_;
311 int32 stencil_size_;
312 int32 samples_;
313 int32 sample_buffers_;
314};
315
316ContextCreationAttribParser::ContextCreationAttribParser()
317 : alpha_size_(-1),
318 blue_size_(-1),
319 green_size_(-1),
320 red_size_(-1),
321 depth_size_(-1),
322 stencil_size_(-1),
323 samples_(-1),
324 sample_buffers_(-1) {
325}
326
327bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
328 // From <EGL/egl.h>.
329 const int32 EGL_ALPHA_SIZE = 0x3021;
330 const int32 EGL_BLUE_SIZE = 0x3022;
331 const int32 EGL_GREEN_SIZE = 0x3023;
332 const int32 EGL_RED_SIZE = 0x3024;
333 const int32 EGL_DEPTH_SIZE = 0x3025;
334 const int32 EGL_STENCIL_SIZE = 0x3026;
335 const int32 EGL_SAMPLES = 0x3031;
336 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
337 const int32 EGL_NONE = 0x3038;
338
339 for (size_t i = 0; i < attribs.size(); i += 2) {
340 const int32 attrib = attribs[i];
341 if (i + 1 >= attribs.size()) {
342 if (attrib == EGL_NONE)
343 return true;
344
345 DLOG(ERROR) << "Missing value after context creation attribute: "
346 << attrib;
347 return false;
348 }
349
350 const int32 value = attribs[i+1];
351 switch (attrib) {
352 case EGL_ALPHA_SIZE:
353 alpha_size_ = value;
354 break;
355 case EGL_BLUE_SIZE:
356 blue_size_ = value;
357 break;
358 case EGL_GREEN_SIZE:
359 green_size_ = value;
360 break;
361 case EGL_RED_SIZE:
362 red_size_ = value;
363 break;
364 case EGL_DEPTH_SIZE:
365 depth_size_ = value;
366 break;
367 case EGL_STENCIL_SIZE:
368 stencil_size_ = value;
369 break;
370 case EGL_SAMPLES:
371 samples_ = value;
372 break;
373 case EGL_SAMPLE_BUFFERS:
374 sample_buffers_ = value;
375 break;
376 case EGL_NONE:
377 // Terminate list, even if more attributes.
378 return true;
379 default:
380 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
381 return false;
382 }
383 }
384
385 return true;
386}
387
[email protected]43f28f832010-02-03 02:28:48388// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32389
[email protected]ddb1e5a2010-12-13 20:10:45390bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
391 uint32* service_texture_id) {
392 return false;
393}
394
[email protected]a3ded6d2010-10-19 06:44:39395GLES2Decoder::GLES2Decoder()
396 : debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32397}
398
[email protected]3916c97e2010-02-25 03:20:50399GLES2Decoder::~GLES2Decoder() {
400}
401
[email protected]f39f4b3f2010-05-12 17:04:08402class VertexAttribManager {
[email protected]96449d2c2009-11-25 00:01:32403 public:
[email protected]07f54fcc2009-12-22 02:46:30404 // Info about Vertex Attributes. This is used to track what the user currently
405 // has bound on each Vertex Attribute so that checking can be done at
406 // glDrawXXX time.
407 class VertexAttribInfo {
408 public:
[email protected]f39f4b3f2010-05-12 17:04:08409 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
[email protected]b1122982010-05-17 23:04:24410 struct Vec4 {
411 float v[4];
412 };
[email protected]f39f4b3f2010-05-12 17:04:08413
[email protected]07f54fcc2009-12-22 02:46:30414 VertexAttribInfo()
[email protected]f39f4b3f2010-05-12 17:04:08415 : index_(0),
416 enabled_(false),
417 size_(4),
418 type_(GL_FLOAT),
[email protected]07f54fcc2009-12-22 02:46:30419 offset_(0),
[email protected]b1122982010-05-17 23:04:24420 normalized_(GL_FALSE),
421 gl_stride_(0),
[email protected]f39f4b3f2010-05-12 17:04:08422 real_stride_(16),
423 list_(NULL) {
[email protected]b1122982010-05-17 23:04:24424 value_.v[0] = 0.0f;
425 value_.v[1] = 0.0f;
426 value_.v[2] = 0.0f;
427 value_.v[3] = 1.0f;
[email protected]07f54fcc2009-12-22 02:46:30428 }
[email protected]3916c97e2010-02-25 03:20:50429
[email protected]07f54fcc2009-12-22 02:46:30430 // Returns true if this VertexAttrib can access index.
[email protected]f39f4b3f2010-05-12 17:04:08431 bool CanAccess(GLuint index) const;
[email protected]07f54fcc2009-12-22 02:46:30432
[email protected]3916c97e2010-02-25 03:20:50433 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30434 return buffer_;
435 }
436
[email protected]8bf5a3e2010-01-29 04:21:36437 GLsizei offset() const {
438 return offset_;
439 }
440
[email protected]f39f4b3f2010-05-12 17:04:08441 GLuint index() const {
442 return index_;
443 }
444
[email protected]b1122982010-05-17 23:04:24445 GLint size() const {
446 return size_;
447 }
448
449 GLenum type() const {
450 return type_;
451 }
452
453 GLboolean normalized() const {
454 return normalized_;
455 }
456
457 GLsizei gl_stride() const {
458 return gl_stride_;
459 }
460
[email protected]f39f4b3f2010-05-12 17:04:08461 bool enabled() const {
462 return enabled_;
463 }
464
[email protected]b1122982010-05-17 23:04:24465 void set_value(const Vec4& value) {
466 value_ = value;
467 }
468
469 const Vec4& value() const {
470 return value_;
471 }
472
[email protected]07f54fcc2009-12-22 02:46:30473 private:
[email protected]f39f4b3f2010-05-12 17:04:08474 friend class VertexAttribManager;
475
476 void set_enabled(bool enabled) {
477 enabled_ = enabled;
478 }
479
480 void set_index(GLuint index) {
481 index_ = index;
482 }
483
484 void SetList(VertexAttribInfoList* new_list) {
485 DCHECK(new_list);
486
487 if (list_) {
488 list_->erase(it_);
489 }
490
491 it_ = new_list->insert(new_list->end(), this);
492 list_ = new_list;
493 }
494
[email protected]8fbedc02010-11-18 18:43:40495 void SetInfo(
496 BufferManager::BufferInfo* buffer,
497 GLint size,
498 GLenum type,
499 GLboolean normalized,
500 GLsizei gl_stride,
501 GLsizei real_stride,
502 GLsizei offset) {
503 DCHECK_GT(real_stride, 0);
504 buffer_ = buffer;
505 size_ = size;
506 type_ = type;
507 normalized_ = normalized;
508 gl_stride_ = gl_stride;
509 real_stride_ = real_stride;
510 offset_ = offset;
511 }
512
[email protected]f39f4b3f2010-05-12 17:04:08513 // The index of this attrib.
514 GLuint index_;
515
[email protected]07f54fcc2009-12-22 02:46:30516 // Whether or not this attribute is enabled.
517 bool enabled_;
518
519 // number of components (1, 2, 3, 4)
520 GLint size_;
521
522 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
523 GLenum type_;
524
525 // The offset into the buffer.
526 GLsizei offset_;
527
[email protected]b1122982010-05-17 23:04:24528 GLboolean normalized_;
529
530 // The stride passed to glVertexAttribPointer.
531 GLsizei gl_stride_;
532
[email protected]07f54fcc2009-12-22 02:46:30533 // The stride that will be used to access the buffer. This is the actual
534 // stide, NOT the GL bogus stride. In other words there is never a stride
535 // of 0.
536 GLsizei real_stride_;
537
[email protected]b1122982010-05-17 23:04:24538 // The current value of the attrib.
539 Vec4 value_;
540
[email protected]3916c97e2010-02-25 03:20:50541 // The buffer bound to this attribute.
542 BufferManager::BufferInfo::Ref buffer_;
[email protected]f39f4b3f2010-05-12 17:04:08543
544 // List this info is on.
545 VertexAttribInfoList* list_;
546
547 // Iterator for list this info is on. Enabled/Disabled
548 VertexAttribInfoList::iterator it_;
[email protected]07f54fcc2009-12-22 02:46:30549 };
550
[email protected]f39f4b3f2010-05-12 17:04:08551 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
552
553 VertexAttribManager()
[email protected]8fbedc02010-11-18 18:43:40554 : max_vertex_attribs_(0),
555 num_fixed_attribs_(0) {
[email protected]f39f4b3f2010-05-12 17:04:08556 }
557
558 void Initialize(uint32 num_vertex_attribs);
559
560 bool Enable(GLuint index, bool enable);
561
[email protected]8fbedc02010-11-18 18:43:40562 bool HaveFixedAttribs() const {
563 return num_fixed_attribs_ != 0;
564 }
565
[email protected]f39f4b3f2010-05-12 17:04:08566 const VertexAttribInfoList& GetEnabledVertexAttribInfos() const {
567 return enabled_vertex_attribs_;
568 }
569
570 VertexAttribInfo* GetVertexAttribInfo(GLuint index) {
[email protected]b1122982010-05-17 23:04:24571 if (index < max_vertex_attribs_) {
572 return &vertex_attrib_infos_[index];
573 }
574 return NULL;
[email protected]f39f4b3f2010-05-12 17:04:08575 }
576
[email protected]8fbedc02010-11-18 18:43:40577 void SetAttribInfo(
578 GLuint index,
579 BufferManager::BufferInfo* buffer,
580 GLint size,
581 GLenum type,
582 GLboolean normalized,
583 GLsizei gl_stride,
584 GLsizei real_stride,
585 GLsizei offset) {
586 VertexAttribInfo* info = GetVertexAttribInfo(index);
587 if (info) {
588 if (info->type() == GL_FIXED) {
589 --num_fixed_attribs_;
590 }
591 if (type == GL_FIXED) {
592 ++num_fixed_attribs_;
593 }
594 info->SetInfo(
595 buffer, size, type, normalized, gl_stride, real_stride, offset);
596 }
597 }
598
599
[email protected]f39f4b3f2010-05-12 17:04:08600 private:
601 uint32 max_vertex_attribs_;
602
[email protected]8fbedc02010-11-18 18:43:40603 // number of attribs using type GL_FIXED.
604 int num_fixed_attribs_;
605
[email protected]f39f4b3f2010-05-12 17:04:08606 // Info for each vertex attribute saved so we can check at glDrawXXX time
607 // if it is safe to draw.
608 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
609
610 // Lists for which vertex attribs are enabled, disabled.
611 VertexAttribInfoList enabled_vertex_attribs_;
612 VertexAttribInfoList disabled_vertex_attribs_;
613};
614
615bool VertexAttribManager::VertexAttribInfo::CanAccess(GLuint index) const {
616 if (!enabled_) {
617 return true;
618 }
619
620 if (!buffer_ || buffer_->IsDeleted()) {
621 return false;
622 }
623
624 // The number of elements that can be accessed.
625 GLsizeiptr buffer_size = buffer_->size();
626 if (offset_ > buffer_size || real_stride_ == 0) {
627 return false;
628 }
629
630 uint32 usable_size = buffer_size - offset_;
631 GLuint num_elements = usable_size / real_stride_ +
632 ((usable_size % real_stride_) >=
633 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
634 return index < num_elements;
635}
636
637
638void VertexAttribManager::Initialize(uint32 max_vertex_attribs) {
639 max_vertex_attribs_ = max_vertex_attribs;
640 vertex_attrib_infos_.reset(
641 new VertexAttribInfo[max_vertex_attribs]);
642 for (uint32 vv = 0; vv < max_vertex_attribs; ++vv) {
643 vertex_attrib_infos_[vv].set_index(vv);
644 vertex_attrib_infos_[vv].SetList(&disabled_vertex_attribs_);
645 }
646}
647
648bool VertexAttribManager::Enable(GLuint index, bool enable) {
649 if (index >= max_vertex_attribs_) {
650 return false;
651 }
652 VertexAttribInfo& info = vertex_attrib_infos_[index];
653 if (info.enabled() != enable) {
654 info.set_enabled(enable);
655 info.SetList(enable ? &enabled_vertex_attribs_ : &disabled_vertex_attribs_);
656 }
657 return true;
658}
659
660// This class implements GLES2Decoder so we don't have to expose all the GLES2
661// cmd stuff to outside this class.
662class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
663 public GLES2Decoder {
664 public:
[email protected]fbe20372011-06-01 01:46:38665 explicit GLES2DecoderImpl(SurfaceManager* surface_manager,
666 ContextGroup* group);
[email protected]f39f4b3f2010-05-12 17:04:08667
[email protected]96449d2c2009-11-25 00:01:32668 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14669 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50670 unsigned int arg_count,
671 const void* args);
[email protected]96449d2c2009-11-25 00:01:32672
673 // Overridden from AsyncAPIInterface.
674 virtual const char* GetCommandName(unsigned int command_id) const;
675
676 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38677 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
678 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35679 const gfx::Size& size,
[email protected]c410da802011-03-14 19:17:41680 const DisallowedExtensions& disallowed_extensions,
[email protected]a3ded6d2010-10-19 06:44:39681 const char* allowed_extensions,
[email protected]34ff8b0c2010-10-01 20:06:02682 const std::vector<int32>& attribs,
[email protected]d37231fa2010-04-09 21:16:02683 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35684 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32685 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35686 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]c71caa82010-06-02 23:25:45687 virtual bool UpdateOffscreenFrameBufferSize();
[email protected]eb54a562010-01-20 21:55:18688 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55689 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30690 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15691 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39692 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48693
[email protected]7ff86b92010-11-25 17:50:00694 virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
[email protected]43f28f832010-02-03 02:28:48695 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
[email protected]80c49752011-04-18 23:55:10696 virtual void SetLatchCallback(const base::Callback<void(bool)>& callback);;
[email protected]1318e922010-09-17 22:03:16697 virtual bool GetServiceTextureId(uint32 client_texture_id,
698 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48699
[email protected]8e3e0662010-08-23 18:46:30700 // Restores the current state to the user's settings.
701 void RestoreCurrentFramebufferBindings();
702 void RestoreCurrentRenderbufferBindings();
703 void RestoreCurrentTexture2DBindings();
704
[email protected]96449d2c2009-11-25 00:01:32705 private:
[email protected]6217d392010-03-25 22:08:35706 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02707 friend class ScopedResolvedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35708 friend class RenderBuffer;
709 friend class FrameBuffer;
710
[email protected]3916c97e2010-02-25 03:20:50711 // State associated with each texture unit.
712 struct TextureUnit {
713 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
714
715 // The last target that was bound to this texture unit.
716 GLenum bind_target;
717
718 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
719 TextureManager::TextureInfo::Ref bound_texture_2d;
720
721 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
722 // glBindTexture
723 TextureManager::TextureInfo::Ref bound_texture_cube_map;
724 };
725
[email protected]c2f8c8402010-12-06 18:07:24726 // Initialize or re-initialize the shader translator.
727 bool InitializeShaderTranslator();
728
[email protected]ae51d192010-04-27 00:48:03729 // Helpers for the glGen and glDelete functions.
730 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
731 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
732 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
733 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
734 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
735 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
736 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
737 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47738
[email protected]3916c97e2010-02-25 03:20:50739 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50740 BufferManager* buffer_manager() {
741 return group_->buffer_manager();
742 }
743
[email protected]a25fa872010-03-25 02:57:58744 RenderbufferManager* renderbuffer_manager() {
745 return group_->renderbuffer_manager();
746 }
747
748 FramebufferManager* framebuffer_manager() {
749 return group_->framebuffer_manager();
750 }
751
[email protected]3916c97e2010-02-25 03:20:50752 ProgramManager* program_manager() {
753 return group_->program_manager();
754 }
755
756 ShaderManager* shader_manager() {
757 return group_->shader_manager();
758 }
759
760 TextureManager* texture_manager() {
761 return group_->texture_manager();
762 }
763
[email protected]34ff8b0c2010-10-01 20:06:02764 bool IsOffscreenBufferMultisampled() const {
765 return offscreen_target_samples_ > 1;
766 }
767
[email protected]a93bb842010-02-16 23:03:47768 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03769 TextureManager::TextureInfo* CreateTextureInfo(
770 GLuint client_id, GLuint service_id) {
[email protected]915a59a12010-09-30 21:29:11771 return texture_manager()->CreateTextureInfo(
772 feature_info_, client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47773 }
774
775 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03776 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50777 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03778 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50779 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47780 }
781
782 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03783 void RemoveTextureInfo(GLuint client_id) {
[email protected]915a59a12010-09-30 21:29:11784 texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]3916c97e2010-02-25 03:20:50785 }
[email protected]a93bb842010-02-16 23:03:47786
[email protected]d37231fa2010-04-09 21:16:02787 // Get the size (in pixels) of the currently bound frame buffer (either FBO
788 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30789 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02790
[email protected]9edc6b22010-12-23 02:00:26791 // Get the format of the currently bound frame buffer (either FBO or regular
792 // back buffer)
793 GLenum GetBoundReadFrameBufferInternalFormat();
794
[email protected]a93bb842010-02-16 23:03:47795 // Wrapper for CompressedTexImage2D commands.
796 error::Error DoCompressedTexImage2D(
797 GLenum target,
798 GLint level,
799 GLenum internal_format,
800 GLsizei width,
801 GLsizei height,
802 GLint border,
803 GLsizei image_size,
804 const void* data);
805
[email protected]cadde4a2010-07-31 17:10:43806 // Wrapper for CompressedTexSubImage2D.
807 void DoCompressedTexSubImage2D(
808 GLenum target,
809 GLint level,
810 GLint xoffset,
811 GLint yoffset,
812 GLsizei width,
813 GLsizei height,
814 GLenum format,
815 GLsizei imageSize,
816 const void * data);
817
818 // Wrapper for CopyTexImage2D.
819 void DoCopyTexImage2D(
820 GLenum target,
821 GLint level,
822 GLenum internal_format,
823 GLint x,
824 GLint y,
825 GLsizei width,
826 GLsizei height,
827 GLint border);
828
829 // Wrapper for CopyTexSubImage2D.
830 void DoCopyTexSubImage2D(
831 GLenum target,
832 GLint level,
833 GLint xoffset,
834 GLint yoffset,
835 GLint x,
836 GLint y,
837 GLsizei width,
838 GLsizei height);
839
[email protected]a93bb842010-02-16 23:03:47840 // Wrapper for TexImage2D commands.
841 error::Error DoTexImage2D(
842 GLenum target,
843 GLint level,
844 GLenum internal_format,
845 GLsizei width,
846 GLsizei height,
847 GLint border,
848 GLenum format,
849 GLenum type,
850 const void* pixels,
851 uint32 pixels_size);
852
[email protected]cadde4a2010-07-31 17:10:43853 // Wrapper for TexSubImage2D.
854 void DoTexSubImage2D(
855 GLenum target,
856 GLint level,
857 GLint xoffset,
858 GLint yoffset,
859 GLsizei width,
860 GLsizei height,
861 GLenum format,
862 GLenum type,
863 const void * data);
864
[email protected]a93bb842010-02-16 23:03:47865 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57866 ProgramManager::ProgramInfo* CreateProgramInfo(
867 GLuint client_id, GLuint service_id) {
868 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47869 }
870
[email protected]07f54fcc2009-12-22 02:46:30871 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03872 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14873 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46874 }
[email protected]07f54fcc2009-12-22 02:46:30875
[email protected]6b8cf1a2010-05-06 16:13:58876 // Gets the program info for the given program. If it's not a program
877 // generates a GL error. Returns NULL if not program.
878 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
879 GLuint client_id, const char* function_name) {
880 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
881 if (!info) {
882 if (GetShaderInfo(client_id)) {
883 SetGLError(GL_INVALID_OPERATION,
884 (std::string(function_name) +
885 ": shader passed for program").c_str());
886 } else {
887 SetGLError(GL_INVALID_VALUE,
888 (std::string(function_name) + ": unknown program").c_str());
889 }
890 }
891 return info;
892 }
893
894
[email protected]45bf5152010-02-12 00:11:31895 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57896 ShaderManager::ShaderInfo* CreateShaderInfo(
897 GLuint client_id,
898 GLuint service_id,
899 GLenum shader_type) {
900 return shader_manager()->CreateShaderInfo(
901 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31902 }
903
904 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03905 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14906 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31907 }
908
[email protected]6b8cf1a2010-05-06 16:13:58909 // Gets the shader info for the given shader. If it's not a shader generates a
910 // GL error. Returns NULL if not shader.
911 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
912 GLuint client_id, const char* function_name) {
913 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
914 if (!info) {
915 if (GetProgramInfo(client_id)) {
916 SetGLError(
917 GL_INVALID_OPERATION,
918 (std::string(function_name) +
919 ": program passed for shader").c_str());
920 } else {
921 SetGLError(GL_INVALID_VALUE,
922 (std::string(function_name) + ": unknown shader").c_str());
923 }
924 }
925 return info;
926 }
927
[email protected]a93bb842010-02-16 23:03:47928 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03929 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
930 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47931 }
932
[email protected]07f54fcc2009-12-22 02:46:30933 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03934 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
935 BufferManager::BufferInfo* info =
936 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50937 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46938 }
[email protected]07f54fcc2009-12-22 02:46:30939
[email protected]a93bb842010-02-16 23:03:47940 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
941 // on glDeleteBuffers so we can make sure the user does not try to render
942 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03943 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47944
[email protected]a25fa872010-03-25 02:57:58945 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03946 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
947 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58948 }
949
950 // Gets the framebuffer info for the given framebuffer.
951 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03952 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58953 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03954 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58955 return (info && !info->IsDeleted()) ? info : NULL;
956 }
957
958 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03959 void RemoveFramebufferInfo(GLuint client_id) {
960 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58961 }
962
963 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03964 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
965 return renderbuffer_manager()->CreateRenderbufferInfo(
966 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58967 }
968
969 // Gets the renderbuffer info for the given renderbuffer.
970 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03971 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58972 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03973 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58974 return (info && !info->IsDeleted()) ? info : NULL;
975 }
976
977 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03978 void RemoveRenderbufferInfo(GLuint client_id) {
979 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58980 }
981
[email protected]558847a2010-03-24 07:02:54982 error::Error GetAttribLocationHelper(
983 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
984 const std::string& name_str);
985
986 error::Error GetUniformLocationHelper(
987 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
988 const std::string& name_str);
989
[email protected]3916c97e2010-02-25 03:20:50990 // Helper for glShaderSource.
991 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03992 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30993
[email protected]3a2e7c7b2010-08-06 01:12:28994 // Clears any uncleared render buffers attached to the given frame buffer.
[email protected]8e3e0662010-08-23 18:46:30995 void ClearUnclearedRenderbuffers(
996 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28997
[email protected]c007aa02010-09-02 22:22:40998 // Restore all GL state that affects clearing.
999 void RestoreClearState();
1000
[email protected]3a2e7c7b2010-08-06 01:12:281001 // Remembers the state of some capabilities.
1002 void SetCapabilityState(GLenum cap, bool enabled);
1003
[email protected]3a03a8f2011-03-19 00:51:271004 // Check that the current frame buffer is complete. Generates error if not.
1005 bool CheckFramebufferComplete(const char* func_name);
1006
[email protected]939e7362010-05-13 20:49:101007 // Checks if the current program exists and is valid. If not generates the
1008 // appropriate GL error. Returns true if the current program is in a usable
1009 // state.
1010 bool CheckCurrentProgram(const char* function_name);
1011
1012 // Checks if the current program exists and is valid and that location is not
1013 // -1. If the current program is not valid generates the appropriate GL
1014 // error. Returns true if the current program is in a usable state and
1015 // location is not -1.
1016 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1017
1018 // Gets the type of a uniform for a location in the current program. Sets GL
1019 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:361020 // program is valid and the location exists. Adjusts count so it
1021 // does not overflow the uniform.
1022 bool PrepForSetUniformByLocation(
1023 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:101024
[email protected]b273e432010-04-12 17:23:581025 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1026 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1027
[email protected]96449d2c2009-11-25 00:01:321028 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:031029 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321030
1031 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:031032 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321033
[email protected]3916c97e2010-02-25 03:20:501034 // Wrapper for glActiveTexture
1035 void DoActiveTexture(GLenum texture_unit);
1036
[email protected]ae51d192010-04-27 00:48:031037 // Wrapper for glAttachShader
1038 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1039
[email protected]96449d2c2009-11-25 00:01:321040 // Wrapper for glBindBuffer since we need to track the current targets.
1041 void DoBindBuffer(GLenum target, GLuint buffer);
1042
[email protected]86093972010-03-11 00:13:561043 // Wrapper for glBindFramebuffer since we need to track the current targets.
1044 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1045
1046 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1047 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1048
[email protected]a93bb842010-02-16 23:03:471049 // Wrapper for glBindTexture since we need to track the current targets.
1050 void DoBindTexture(GLenum target, GLuint texture);
1051
[email protected]8e3e0662010-08-23 18:46:301052 // Wrapper for glBlitFramebufferEXT.
1053 void DoBlitFramebufferEXT(
1054 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1055 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1056 GLbitfield mask, GLenum filter);
1057
[email protected]36cef8ce2010-03-16 07:34:451058 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111059 void DoBufferData(
1060 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1061
[email protected]36cef8ce2010-03-16 07:34:451062 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111063 void DoBufferSubData(
1064 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1065
[email protected]36cef8ce2010-03-16 07:34:451066 // Wrapper for glCheckFramebufferStatus
1067 GLenum DoCheckFramebufferStatus(GLenum target);
1068
[email protected]3a03a8f2011-03-19 00:51:271069 // Wrapper for glClear
1070 void DoClear(GLbitfield mask);
1071
[email protected]3a2e7c7b2010-08-06 01:12:281072 // Wrappers for clear and mask settings functions.
1073 void DoClearColor(
1074 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1075 void DoClearDepthf(GLclampf depth);
1076 void DoClearStencil(GLint s);
1077 void DoColorMask(
1078 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1079 void DoDepthMask(GLboolean depth);
1080 void DoStencilMask(GLuint mask);
1081 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1082
[email protected]45bf5152010-02-12 00:11:311083 // Wrapper for glCompileShader.
1084 void DoCompileShader(GLuint shader);
1085
[email protected]269200b12010-11-18 22:53:061086 // Helper for DeleteSharedIdsCHROMIUM commands.
1087 void DoDeleteSharedIdsCHROMIUM(
1088 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101089
[email protected]ae51d192010-04-27 00:48:031090 // Wrapper for glDetachShader
1091 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1092
[email protected]07f54fcc2009-12-22 02:46:301093 // Wrapper for glDrawArrays.
1094 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
1095
[email protected]3a2e7c7b2010-08-06 01:12:281096 // Wrapper for glDisable
1097 void DoDisable(GLenum cap);
1098
[email protected]07f54fcc2009-12-22 02:46:301099 // Wrapper for glDisableVertexAttribArray.
1100 void DoDisableVertexAttribArray(GLuint index);
1101
[email protected]3a2e7c7b2010-08-06 01:12:281102 // Wrapper for glEnable
1103 void DoEnable(GLenum cap);
1104
[email protected]07f54fcc2009-12-22 02:46:301105 // Wrapper for glEnableVertexAttribArray.
1106 void DoEnableVertexAttribArray(GLuint index);
1107
[email protected]36cef8ce2010-03-16 07:34:451108 // Wrapper for glFramebufferRenderbufffer.
1109 void DoFramebufferRenderbuffer(
1110 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1111 GLuint renderbuffer);
1112
1113 // Wrapper for glFramebufferTexture2D.
1114 void DoFramebufferTexture2D(
1115 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1116 GLint level);
1117
[email protected]a93bb842010-02-16 23:03:471118 // Wrapper for glGenerateMipmap
1119 void DoGenerateMipmap(GLenum target);
1120
[email protected]269200b12010-11-18 22:53:061121 // Helper for GenSharedIdsCHROMIUM commands.
1122 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101123 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1124
[email protected]b273e432010-04-12 17:23:581125 // Wrapper for DoGetBooleanv.
1126 void DoGetBooleanv(GLenum pname, GLboolean* params);
1127
1128 // Wrapper for DoGetFloatv.
1129 void DoGetFloatv(GLenum pname, GLfloat* params);
1130
[email protected]36cef8ce2010-03-16 07:34:451131 // Wrapper for glGetFramebufferAttachmentParameteriv.
1132 void DoGetFramebufferAttachmentParameteriv(
1133 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1134
[email protected]a0c3e972010-04-21 00:49:131135 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581136 void DoGetIntegerv(GLenum pname, GLint* params);
1137
[email protected]29a9eb52010-04-13 09:04:231138 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061139 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231140 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1141
[email protected]a0c3e972010-04-21 00:49:131142 // Wrapper for glGetProgramiv.
1143 void DoGetProgramiv(
1144 GLuint program_id, GLenum pname, GLint* params);
1145
[email protected]36cef8ce2010-03-16 07:34:451146 // Wrapper for glRenderbufferParameteriv.
1147 void DoGetRenderbufferParameteriv(
1148 GLenum target, GLenum pname, GLint* params);
1149
[email protected]ddd968b82010-03-02 00:44:291150 // Wrapper for glGetShaderiv
1151 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1152
[email protected]b1122982010-05-17 23:04:241153 // Wrappers for glGetVertexAttrib.
1154 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1155 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1156
[email protected]1958e0e2010-04-22 05:17:151157 // Wrappers for glIsXXX functions.
1158 bool DoIsBuffer(GLuint client_id);
1159 bool DoIsFramebuffer(GLuint client_id);
1160 bool DoIsProgram(GLuint client_id);
1161 bool DoIsRenderbuffer(GLuint client_id);
1162 bool DoIsShader(GLuint client_id);
1163 bool DoIsTexture(GLuint client_id);
1164
[email protected]07f54fcc2009-12-22 02:46:301165 // Wrapper for glLinkProgram
1166 void DoLinkProgram(GLuint program);
1167
[email protected]269200b12010-11-18 22:53:061168 // Helper for RegisterSharedIdsCHROMIUM.
1169 void DoRegisterSharedIdsCHROMIUM(
1170 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101171
[email protected]36cef8ce2010-03-16 07:34:451172 // Wrapper for glRenderbufferStorage.
1173 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031174 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451175
[email protected]8e3e0662010-08-23 18:46:301176 // Wrapper for glRenderbufferStorageMultisampleEXT.
1177 void DoRenderbufferStorageMultisample(
1178 GLenum target, GLsizei samples, GLenum internalformat,
1179 GLsizei width, GLsizei height);
1180
[email protected]b273e432010-04-12 17:23:581181 // Wrapper for glReleaseShaderCompiler.
1182 void DoReleaseShaderCompiler() { }
1183
[email protected]3916c97e2010-02-25 03:20:501184 // Wrappers for glTexParameter functions.
1185 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1186 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1187 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1188 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1189
1190 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1191 // spec only these 2 functions can be used to set sampler uniforms.
1192 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101193 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:361194 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
1195 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
1196 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101197
1198 // Wrappers for glUniformfv because some drivers don't correctly accept
1199 // bool uniforms.
1200 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1201 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1202 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1203 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501204
[email protected]43c2f1f2011-03-25 18:35:361205 void DoUniformMatrix2fv(
1206 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1207 void DoUniformMatrix3fv(
1208 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1209 void DoUniformMatrix4fv(
1210 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1211
[email protected]b1122982010-05-17 23:04:241212 // Wrappers for glVertexAttrib??
1213 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1214 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1215 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1216 void DoVertexAttrib4f(
1217 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1218 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1219 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1220 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1221 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1222
[email protected]07f54fcc2009-12-22 02:46:301223 // Wrapper for glUseProgram
1224 void DoUseProgram(GLuint program);
1225
[email protected]ae51d192010-04-27 00:48:031226 // Wrapper for glValidateProgram.
1227 void DoValidateProgram(GLuint program_client_id);
1228
[email protected]269200b12010-11-18 22:53:061229 void DoCopyTextureToParentTextureCHROMIUM(GLuint client_texture_id,
[email protected]c007aa02010-09-02 22:22:401230 GLuint parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:561231
[email protected]43ecf372010-11-16 19:19:391232 void DoResizeCHROMIUM(GLuint width, GLuint height);
1233
[email protected]fbe20372011-06-01 01:46:381234 void DoSetSurfaceCHROMIUM(GLint surface_id);
1235
[email protected]4e8a5b122010-05-08 22:00:101236 // Gets the number of values that will be returned by glGetXXX. Returns
1237 // false if pname is unknown.
1238 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1239
[email protected]96449d2c2009-11-25 00:01:321240 // Gets the GLError through our wrapper.
1241 GLenum GetGLError();
1242
1243 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:291244 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:321245
[email protected]07f54fcc2009-12-22 02:46:301246 // Copies the real GL errors to the wrapper. This is so we can
1247 // make sure there are no native GL errors before calling some GL function
1248 // so that on return we know any error generated was for that specific
1249 // command.
1250 void CopyRealGLErrorsToWrapper();
1251
[email protected]6217d392010-03-25 22:08:351252 // Clear all real GL errors. This is to prevent the client from seeing any
1253 // errors caused by GL calls that it was not responsible for issuing.
1254 void ClearRealGLErrors();
1255
[email protected]07f54fcc2009-12-22 02:46:301256 // Checks if the current program and vertex attributes are valid for drawing.
1257 bool IsDrawValid(GLuint max_vertex_accessed);
1258
[email protected]b1122982010-05-17 23:04:241259 // Returns true if attrib0 was simulated.
1260 bool SimulateAttrib0(GLuint max_vertex_accessed);
1261 void RestoreStateForSimulatedAttrib0();
1262
[email protected]ef526492010-06-02 23:12:251263 // Returns true if textures were set.
1264 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501265 void RestoreStateForNonRenderableTextures();
1266
[email protected]8fbedc02010-11-18 18:43:401267 // Returns true if GL_FIXED attribs were simulated.
1268 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1269 void RestoreStateForSimulatedFixedAttribs();
1270
[email protected]07f54fcc2009-12-22 02:46:301271 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501272 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301273 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501274 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1275 bound_array_buffer_ : bound_element_array_buffer_;
1276 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301277 }
1278
[email protected]a93bb842010-02-16 23:03:471279 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501280 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1281 TextureUnit& unit = texture_units_[active_texture_unit_];
1282 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471283 switch (target) {
1284 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501285 info = unit.bound_texture_2d;
1286 break;
[email protected]a93bb842010-02-16 23:03:471287 case GL_TEXTURE_CUBE_MAP:
1288 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1289 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1290 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1291 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1292 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1293 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501294 info = unit.bound_texture_cube_map;
1295 break;
[email protected]1aef98132010-02-23 18:00:071296 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1297 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1298 // because |texture_| is used by the FBO rendering mechanism for readback
1299 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471300 default:
1301 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501302 return NULL;
[email protected]a93bb842010-02-16 23:03:471303 }
[email protected]3916c97e2010-02-25 03:20:501304 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471305 }
1306
[email protected]8e3e0662010-08-23 18:46:301307 // Gets the framebuffer info for a particular target.
1308 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1309 GLenum target) {
1310 FramebufferManager::FramebufferInfo* info = NULL;
1311 switch (target) {
1312 case GL_FRAMEBUFFER:
1313 case GL_DRAW_FRAMEBUFFER:
1314 info = bound_draw_framebuffer_;
1315 break;
1316 case GL_READ_FRAMEBUFFER:
1317 info = bound_read_framebuffer_;
1318 break;
1319 default:
1320 NOTREACHED();
1321 break;
1322 }
1323 return (info && !info->IsDeleted()) ? info : NULL;
1324 }
1325
[email protected]f7b85372010-02-03 01:11:371326 // Validates the program and location for a glGetUniform call and returns
1327 // a SizeResult setup to receive the result. Returns true if glGetUniform
1328 // should be called.
1329 bool GetUniformSetup(
1330 GLuint program, GLint location,
1331 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101332 error::Error* error, GLuint* service_id, void** result,
1333 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371334
[email protected]96449d2c2009-11-25 00:01:321335 // Generate a member function prototype for each command in an automated and
1336 // typesafe way.
1337 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141338 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191339 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321340 const gles2::name& args); \
1341
1342 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1343
1344 #undef GLES2_CMD_OP
1345
[email protected]fbe20372011-06-01 01:46:381346 // Maps surface IDs to GLSurface.
1347 gpu::SurfaceManager* surface_manager_;
1348
[email protected]2f2d7042010-04-14 21:45:581349 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381350 scoped_refptr<gfx::GLSurface> surface_;
1351 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021352
[email protected]a3ded6d2010-10-19 06:44:391353 // The ContextGroup for this decoder uses to track resources.
1354 ContextGroup::Ref group_;
1355
[email protected]6217d392010-03-25 22:08:351356 // A parent decoder can access this decoders saved offscreen frame buffer.
1357 // The parent pointer is reset if the parent is destroyed.
1358 base::WeakPtr<GLES2DecoderImpl> parent_;
1359
1360 // Width and height to which an offscreen frame buffer should be resized on
1361 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021362 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351363
[email protected]34ff8b0c2010-10-01 20:06:021364 // Current width and height of the offscreen frame buffer.
1365 gfx::Size offscreen_size_;
1366
[email protected]96449d2c2009-11-25 00:01:321367 // Current GL error bits.
1368 uint32 error_bits_;
1369
[email protected]96449d2c2009-11-25 00:01:321370 // Util to help with GL.
1371 GLES2Util util_;
1372
1373 // pack alignment as last set by glPixelStorei
1374 GLint pack_alignment_;
1375
1376 // unpack alignment as last set by glPixelStorei
1377 GLint unpack_alignment_;
1378
1379 // The currently bound array buffer. If this is 0 it is illegal to call
1380 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501381 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321382
1383 // The currently bound element array buffer. If this is 0 it is illegal
1384 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501385 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301386
[email protected]f39f4b3f2010-05-12 17:04:081387 // Class that manages vertex attribs.
1388 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301389
[email protected]b1122982010-05-17 23:04:241390 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1391 GLuint attrib_0_buffer_id_;
1392
1393 // The value currently in attrib_0.
1394 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1395
[email protected]fc753442011-02-04 19:49:491396 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1397 bool attrib_0_buffer_matches_value_;
1398
[email protected]b1122982010-05-17 23:04:241399 // The size of attrib 0.
1400 GLsizei attrib_0_size_;
1401
[email protected]8fbedc02010-11-18 18:43:401402 // The buffer used to simulate GL_FIXED attribs.
1403 GLuint fixed_attrib_buffer_id_;
1404
1405 // The size of fiixed attrib buffer.
1406 GLsizei fixed_attrib_buffer_size_;
1407
[email protected]3916c97e2010-02-25 03:20:501408 // Current active texture by 0 - n index.
1409 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1410 // be 2.
1411 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301412
[email protected]3916c97e2010-02-25 03:20:501413 // Which textures are bound to texture units through glActiveTexture.
1414 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471415
[email protected]3a2e7c7b2010-08-06 01:12:281416 // state saved for clearing so we can clear render buffers and then
1417 // restore to these values.
1418 GLclampf clear_red_;
1419 GLclampf clear_green_;
1420 GLclampf clear_blue_;
1421 GLclampf clear_alpha_;
1422 GLboolean mask_red_;
1423 GLboolean mask_green_;
1424 GLboolean mask_blue_;
1425 GLboolean mask_alpha_;
1426 GLint clear_stencil_;
1427 GLuint mask_stencil_front_;
1428 GLuint mask_stencil_back_;
1429 GLclampf clear_depth_;
1430 GLboolean mask_depth_;
1431 bool enable_scissor_test_;
1432
[email protected]1d32bc82010-01-13 22:06:461433 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501434 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301435
[email protected]8e3e0662010-08-23 18:46:301436 // The currently bound framebuffers
1437 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1438 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561439
1440 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081441 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561442
[email protected]b9363b22010-06-09 22:06:151443 // The offscreen frame buffer that the client renders to. With EGL, the
1444 // depth and stencil buffers are separate. With regular GL there is a single
1445 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1446 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351447 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1448 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021449 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151450 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1451 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021452 GLenum offscreen_target_color_format_;
1453 GLenum offscreen_target_depth_format_;
1454 GLenum offscreen_target_stencil_format_;
1455 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351456
[email protected]a3a93e7b2010-08-28 00:48:561457 GLuint copy_texture_to_parent_texture_fb_;
1458
[email protected]34ff8b0c2010-10-01 20:06:021459 // The copy that is saved when SwapBuffers is called. It is also
1460 // used as the destination for multi-sample resolves.
1461 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351462 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]97872062010-11-03 19:07:051463 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351464
[email protected]7ff86b92010-11-25 17:50:001465 scoped_ptr<Callback1<gfx::Size>::Type> resize_callback_;
[email protected]43f28f832010-02-03 02:28:481466 scoped_ptr<Callback0::Type> swap_buffers_callback_;
[email protected]80c49752011-04-18 23:55:101467 base::Callback<void(bool)> latch_callback_;
[email protected]43f28f832010-02-03 02:28:481468
[email protected]32fe9aa2011-01-21 23:47:131469 // The format of the back buffer_
1470 GLenum back_buffer_color_format_;
1471
[email protected]8eee29c2010-04-29 03:38:291472 // The last error message set.
1473 std::string last_error_;
1474
[email protected]a3a93e7b2010-08-28 00:48:561475 // The current decoder error.
1476 error::Error current_decoder_error_;
1477
[email protected]b1d2dcb2010-05-17 19:24:181478 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451479 scoped_ptr<ShaderTranslator> vertex_translator_;
1480 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181481
[email protected]c410da802011-03-14 19:17:411482 DisallowedExtensions disallowed_extensions_;
1483
[email protected]915a59a12010-09-30 21:29:111484 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051485 const Validators* validators_;
[email protected]915a59a12010-09-30 21:29:111486 FeatureInfo* feature_info_;
[email protected]9438b012010-06-15 22:55:051487
[email protected]b493ee622011-04-13 23:52:001488 // This indicates all the following texSubImage2D calls that are part of the
1489 // failed texImage2D call should be ignored.
1490 bool tex_image_2d_failed_;
1491
[email protected]65225772011-05-12 21:10:241492 int frame_number_;
1493
[email protected]96449d2c2009-11-25 00:01:321494 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1495};
1496
[email protected]6217d392010-03-25 22:08:351497ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1498 : decoder_(decoder) {
1499 decoder_->CopyRealGLErrorsToWrapper();
1500}
1501
1502ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1503 decoder_->ClearRealGLErrors();
1504}
1505
1506ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1507 GLuint id)
1508 : decoder_(decoder) {
1509 ScopedGLErrorSuppressor suppressor(decoder_);
1510
1511 // TODO(apatrick): Check if there are any other states that need to be reset
1512 // before binding a new texture.
1513 glActiveTexture(GL_TEXTURE0);
1514 glBindTexture(GL_TEXTURE_2D, id);
1515}
1516
1517ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1518 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301519 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351520}
1521
1522ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1523 GLuint id)
1524 : decoder_(decoder) {
1525 ScopedGLErrorSuppressor suppressor(decoder_);
1526 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1527}
1528
1529ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1530 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301531 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351532}
1533
1534ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1535 GLuint id)
1536 : decoder_(decoder) {
1537 ScopedGLErrorSuppressor suppressor(decoder_);
1538 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1539}
1540
1541ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1542 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301543 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351544}
1545
[email protected]34ff8b0c2010-10-01 20:06:021546ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]c0701082011-04-20 00:34:521547 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer)
1548 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021549 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1550 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521551 (!decoder_->bound_read_framebuffer_.get() ||
1552 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021553 if (!resolve_and_bind_)
1554 return;
1555
1556 ScopedGLErrorSuppressor suppressor(decoder_);
1557 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1558 decoder_->offscreen_target_frame_buffer_->id());
1559 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT,
1560 decoder_->offscreen_saved_frame_buffer_->id());
1561 const int width = decoder_->offscreen_size_.width();
1562 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181563 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021564 if (IsAngle()) {
1565 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1566 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1567 } else {
1568 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1569 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1570 }
1571 glBindFramebufferEXT(GL_FRAMEBUFFER,
1572 decoder_->offscreen_saved_frame_buffer_->id());
1573}
1574
1575ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1576 if (!resolve_and_bind_)
1577 return;
1578
1579 ScopedGLErrorSuppressor suppressor(decoder_);
1580 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181581 if (decoder_->enable_scissor_test_) {
1582 glEnable(GL_SCISSOR_TEST);
1583 }
[email protected]34ff8b0c2010-10-01 20:06:021584}
1585
[email protected]6217d392010-03-25 22:08:351586Texture::Texture(GLES2DecoderImpl* decoder)
1587 : decoder_(decoder),
1588 id_(0) {
1589}
1590
1591Texture::~Texture() {
1592 // This does not destroy the render texture because that would require that
1593 // the associated GL context was current. Just check that it was explicitly
1594 // destroyed.
1595 DCHECK_EQ(id_, 0u);
1596}
1597
1598void Texture::Create() {
1599 ScopedGLErrorSuppressor suppressor(decoder_);
1600 Destroy();
1601 glGenTextures(1, &id_);
1602}
1603
[email protected]34ff8b0c2010-10-01 20:06:021604bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351605 DCHECK_NE(id_, 0u);
1606 ScopedGLErrorSuppressor suppressor(decoder_);
1607 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]8c515f82010-11-09 03:40:041608 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1609 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1610 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1611 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351612
1613 glTexImage2D(GL_TEXTURE_2D,
1614 0, // mip level
[email protected]34ff8b0c2010-10-01 20:06:021615 format,
[email protected]6217d392010-03-25 22:08:351616 size.width(),
1617 size.height(),
1618 0, // border
[email protected]34ff8b0c2010-10-01 20:06:021619 format,
[email protected]6217d392010-03-25 22:08:351620 GL_UNSIGNED_BYTE,
1621 NULL);
1622
[email protected]d37231fa2010-04-09 21:16:021623 size_ = size;
1624
[email protected]6217d392010-03-25 22:08:351625 return glGetError() == GL_NO_ERROR;
1626}
1627
1628void Texture::Copy(const gfx::Size& size) {
1629 DCHECK_NE(id_, 0u);
1630 ScopedGLErrorSuppressor suppressor(decoder_);
1631 ScopedTexture2DBinder binder(decoder_, id_);
1632 glCopyTexImage2D(GL_TEXTURE_2D,
1633 0, // level
1634 GL_RGBA,
1635 0, 0,
1636 size.width(),
1637 size.height(),
1638 0); // border
1639}
1640
1641void Texture::Destroy() {
1642 if (id_ != 0) {
1643 ScopedGLErrorSuppressor suppressor(decoder_);
1644 glDeleteTextures(1, &id_);
1645 id_ = 0;
1646 }
1647}
1648
[email protected]97872062010-11-03 19:07:051649void Texture::Invalidate() {
1650 id_ = 0;
1651}
1652
[email protected]6217d392010-03-25 22:08:351653RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1654 : decoder_(decoder),
1655 id_(0) {
1656}
1657
1658RenderBuffer::~RenderBuffer() {
1659 // This does not destroy the render buffer because that would require that
1660 // the associated GL context was current. Just check that it was explicitly
1661 // destroyed.
1662 DCHECK_EQ(id_, 0u);
1663}
1664
1665void RenderBuffer::Create() {
1666 ScopedGLErrorSuppressor suppressor(decoder_);
1667 Destroy();
1668 glGenRenderbuffersEXT(1, &id_);
1669}
1670
[email protected]34ff8b0c2010-10-01 20:06:021671bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1672 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351673 ScopedGLErrorSuppressor suppressor(decoder_);
1674 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021675 if (samples <= 1) {
1676 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1677 format,
1678 size.width(),
1679 size.height());
1680 } else {
1681 if (IsAngle()) {
1682 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1683 samples,
1684 format,
1685 size.width(),
1686 size.height());
1687 } else {
1688 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1689 samples,
1690 format,
1691 size.width(),
1692 size.height());
1693 }
1694 }
[email protected]6217d392010-03-25 22:08:351695 return glGetError() == GL_NO_ERROR;
1696}
1697
1698void RenderBuffer::Destroy() {
1699 if (id_ != 0) {
1700 ScopedGLErrorSuppressor suppressor(decoder_);
1701 glDeleteRenderbuffersEXT(1, &id_);
1702 id_ = 0;
1703 }
1704}
1705
[email protected]97872062010-11-03 19:07:051706void RenderBuffer::Invalidate() {
1707 id_ = 0;
1708}
1709
[email protected]6217d392010-03-25 22:08:351710FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1711 : decoder_(decoder),
1712 id_(0) {
1713}
1714
1715FrameBuffer::~FrameBuffer() {
1716 // This does not destroy the frame buffer because that would require that
1717 // the associated GL context was current. Just check that it was explicitly
1718 // destroyed.
1719 DCHECK_EQ(id_, 0u);
1720}
1721
1722void FrameBuffer::Create() {
1723 ScopedGLErrorSuppressor suppressor(decoder_);
1724 Destroy();
1725 glGenFramebuffersEXT(1, &id_);
1726}
1727
1728void FrameBuffer::AttachRenderTexture(Texture* texture) {
1729 DCHECK_NE(id_, 0u);
1730 ScopedGLErrorSuppressor suppressor(decoder_);
1731 ScopedFrameBufferBinder binder(decoder_, id_);
1732 GLuint attach_id = texture ? texture->id() : 0;
1733 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1734 GL_COLOR_ATTACHMENT0,
1735 GL_TEXTURE_2D,
1736 attach_id,
1737 0);
1738}
1739
[email protected]b9363b22010-06-09 22:06:151740void FrameBuffer::AttachRenderBuffer(GLenum target,
1741 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351742 DCHECK_NE(id_, 0u);
1743 ScopedGLErrorSuppressor suppressor(decoder_);
1744 ScopedFrameBufferBinder binder(decoder_, id_);
1745 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1746 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151747 target,
[email protected]6217d392010-03-25 22:08:351748 GL_RENDERBUFFER,
1749 attach_id);
1750}
1751
1752void FrameBuffer::Clear(GLbitfield buffers) {
1753 ScopedGLErrorSuppressor suppressor(decoder_);
1754 ScopedFrameBufferBinder binder(decoder_, id_);
1755 glClear(buffers);
1756}
1757
1758void FrameBuffer::Destroy() {
1759 if (id_ != 0) {
1760 ScopedGLErrorSuppressor suppressor(decoder_);
1761 glDeleteFramebuffersEXT(1, &id_);
1762 id_ = 0;
1763 }
1764}
1765
[email protected]97872062010-11-03 19:07:051766void FrameBuffer::Invalidate() {
1767 id_ = 0;
1768}
1769
[email protected]6217d392010-03-25 22:08:351770GLenum FrameBuffer::CheckStatus() {
1771 DCHECK_NE(id_, 0u);
1772 ScopedGLErrorSuppressor suppressor(decoder_);
1773 ScopedFrameBufferBinder binder(decoder_, id_);
1774 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1775}
1776
[email protected]fbe20372011-06-01 01:46:381777GLES2Decoder* GLES2Decoder::Create(SurfaceManager* surface_manager,
1778 ContextGroup* group) {
1779 return new GLES2DecoderImpl(surface_manager, group);
[email protected]96449d2c2009-11-25 00:01:321780}
1781
[email protected]fbe20372011-06-01 01:46:381782GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
1783 ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391784 : GLES2Decoder(),
[email protected]fbe20372011-06-01 01:46:381785 surface_manager_(surface_manager),
[email protected]a3ded6d2010-10-19 06:44:391786 group_(ContextGroup::Ref(group ? group : new ContextGroup())),
[email protected]96449d2c2009-11-25 00:01:321787 error_bits_(0),
1788 util_(0), // TODO(gman): Set to actual num compress texture formats.
1789 pack_alignment_(4),
1790 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241791 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491792 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241793 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401794 fixed_attrib_buffer_id_(0),
1795 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501796 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281797 clear_red_(0),
1798 clear_green_(0),
1799 clear_blue_(0),
1800 clear_alpha_(0),
1801 mask_red_(true),
1802 mask_green_(true),
1803 mask_blue_(true),
1804 mask_alpha_(true),
1805 clear_stencil_(0),
1806 mask_stencil_front_(-1),
1807 mask_stencil_back_(-1),
1808 clear_depth_(1.0f),
1809 mask_depth_(true),
1810 enable_scissor_test_(false),
[email protected]34ff8b0c2010-10-01 20:06:021811 offscreen_target_color_format_(0),
1812 offscreen_target_depth_format_(0),
1813 offscreen_target_stencil_format_(0),
1814 offscreen_target_samples_(0),
[email protected]5ea88812011-03-28 10:45:391815 copy_texture_to_parent_texture_fb_(0),
[email protected]97872062010-11-03 19:07:051816 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:131817 back_buffer_color_format_(0),
[email protected]a3a93e7b2010-08-28 00:48:561818 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051819 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111820 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001821 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241822 tex_image_2d_failed_(false),
1823 frame_number_(0) {
[email protected]b1122982010-05-17 23:04:241824 attrib_0_value_.v[0] = 0.0f;
1825 attrib_0_value_.v[1] = 0.0f;
1826 attrib_0_value_.v[2] = 0.0f;
1827 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151828
[email protected]c2f8c8402010-12-06 18:07:241829 // The shader translator is used for WebGL even when running on EGL
1830 // because additional restrictions are needed (like only enabling
1831 // GL_OES_standard_derivatives on demand). It is used for the unit
1832 // tests because
1833 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1834 // empty string to CompileShader and this is not a valid shader.
1835 // TODO(apatrick): fix this test.
1836 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1837 !feature_info_->feature_flags().chromium_webglsl) ||
[email protected]b9363b22010-06-09 22:06:151838 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1839 use_shader_translator_ = false;
1840 }
[email protected]96449d2c2009-11-25 00:01:321841}
1842
[email protected]c410da802011-03-14 19:17:411843bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381844 const scoped_refptr<gfx::GLSurface>& surface,
1845 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411846 const gfx::Size& size,
1847 const DisallowedExtensions& disallowed_extensions,
1848 const char* allowed_extensions,
1849 const std::vector<int32>& attribs,
1850 GLES2Decoder* parent,
1851 uint32 parent_client_texture_id) {
[email protected]4bedba72010-04-20 22:08:541852 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301853 DCHECK(!context_.get());
1854
[email protected]fbe20372011-06-01 01:46:381855 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1856 // context is retired, the decoder should not take an initial surface as
1857 // an argument to this function.
1858 // Maybe create a short lived offscreen GLSurface for the purpose of
1859 // initializing the decoder's GLContext.
1860 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151861
[email protected]66791e382010-07-14 20:48:301862 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381863 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021864
[email protected]6217d392010-03-25 22:08:351865 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021866 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351867 if (parent)
1868 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1869
[email protected]246a70452010-03-05 21:53:501870 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011871 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1872 << "MakeCurrent failed.";
[email protected]246a70452010-03-05 21:53:501873 Destroy();
1874 return false;
[email protected]eb54a562010-01-20 21:55:181875 }
1876
[email protected]c410da802011-03-14 19:17:411877 if (!group_->Initialize(disallowed_extensions, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221878 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391879 << "failed to initialize.";
1880 Destroy();
[email protected]ae1741092010-11-17 19:16:031881 return false;
[email protected]a3ded6d2010-10-19 06:44:391882 }
1883
[email protected]246a70452010-03-05 21:53:501884 CHECK_GL_ERROR();
[email protected]c410da802011-03-14 19:17:411885 disallowed_extensions_ = disallowed_extensions;
[email protected]246a70452010-03-05 21:53:501886
[email protected]f39f4b3f2010-05-12 17:04:081887 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321888
[email protected]32fe9aa2011-01-21 23:47:131889 GLint v = 0;
1890 glGetIntegerv(GL_ALPHA_BITS, &v);
1891 back_buffer_color_format_ = v ? GL_RGBA : GL_RGB;
1892
[email protected]1071e572011-02-09 20:00:121893 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1894 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1895 // OpenGL ES 2.0 does not have this issue.
1896 glEnableVertexAttribArray(0);
1897 }
[email protected]b1122982010-05-17 23:04:241898 glGenBuffersARB(1, &attrib_0_buffer_id_);
1899 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1900 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1901 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401902 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081903
[email protected]246a70452010-03-05 21:53:501904 texture_units_.reset(
1905 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151906 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491907 glActiveTexture(GL_TEXTURE0 + tt);
1908 // Do cube map first because we want the last bind to be 2D.
1909 TextureManager::TextureInfo* info =
[email protected]1958e0e2010-04-22 05:17:151910 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491911 texture_units_[tt].bound_texture_cube_map = info;
1912 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1913 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1914 texture_units_[tt].bound_texture_2d = info;
1915 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151916 }
[email protected]00f893d2010-08-24 18:55:491917 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501918 CHECK_GL_ERROR();
1919
[email protected]f62a5ab2011-05-23 20:34:151920 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:021921 ContextCreationAttribParser attrib_parser;
1922 if (!attrib_parser.Parse(attribs))
1923 return false;
1924
1925 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:541926 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:021927 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
1928 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:431929 // max_sample_count must be initialized to a sane value. If
1930 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
1931 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:021932 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
1933 offscreen_target_samples_ = std::min(attrib_parser.samples_,
1934 max_sample_count);
1935 } else {
1936 offscreen_target_samples_ = 1;
1937 }
1938
1939 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1940 const bool rgb8_supported =
1941 context_->HasExtension("GL_OES_rgb8_rgba8");
1942 // The only available default render buffer formats in GLES2 have very
1943 // little precision. Don't enable multisampling unless 8-bit render
1944 // buffer formats are available--instead fall back to 8-bit textures.
1945 if (rgb8_supported && offscreen_target_samples_ > 1) {
1946 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1947 GL_RGBA8 : GL_RGB8;
1948 } else {
1949 offscreen_target_samples_ = 1;
1950 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1951 GL_RGBA : GL_RGB;
1952 }
1953
1954 // ANGLE only supports packed depth/stencil formats, so use it if it is
1955 // available.
1956 const bool depth24_stencil8_supported =
1957 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271958 VLOG(1) << "GL_OES_packed_depth_stencil "
1959 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:001960 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1961 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021962 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1963 offscreen_target_stencil_format_ = 0;
1964 } else {
1965 // It may be the case that this depth/stencil combination is not
1966 // supported, but this will be checked later by CheckFramebufferStatus.
1967 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1968 GL_DEPTH_COMPONENT16 : 0;
1969 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1970 GL_STENCIL_INDEX8 : 0;
1971 }
1972 } else {
1973 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1974 GL_RGBA : GL_RGB;
1975
1976 // If depth is requested at all, use the packed depth stencil format if
1977 // it's available, as some desktop GL drivers don't support any non-packed
1978 // formats for depth attachments.
1979 const bool depth24_stencil8_supported =
1980 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271981 VLOG(1) << "GL_EXT_packed_depth_stencil "
1982 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:021983
[email protected]71ee3642010-10-14 18:08:001984 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1985 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021986 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1987 offscreen_target_stencil_format_ = 0;
1988 } else {
1989 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1990 GL_DEPTH_COMPONENT : 0;
1991 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1992 GL_STENCIL_INDEX : 0;
1993 }
1994 }
1995
[email protected]97872062010-11-03 19:07:051996 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
1997 GL_RGBA : GL_RGB;
1998
[email protected]6217d392010-03-25 22:08:351999 // Create the target frame buffer. This is the one that the client renders
2000 // directly to.
2001 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2002 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022003 // Due to GLES2 format limitations, either the color texture (for
2004 // non-multisampling) or the color render buffer (for multisampling) will be
2005 // attached to the offscreen frame buffer. The render buffer has more
2006 // limited formats available to it, but the texture can't do multisampling.
2007 if (IsOffscreenBufferMultisampled()) {
2008 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2009 offscreen_target_color_render_buffer_->Create();
2010 } else {
2011 offscreen_target_color_texture_.reset(new Texture(this));
2012 offscreen_target_color_texture_->Create();
2013 }
2014 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152015 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022016 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152017 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352018
2019 // Create the saved offscreen texture. The target frame buffer is copied
2020 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022021 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2022 offscreen_saved_frame_buffer_->Create();
2023 //
[email protected]6217d392010-03-25 22:08:352024 offscreen_saved_color_texture_.reset(new Texture(this));
2025 offscreen_saved_color_texture_->Create();
2026
[email protected]6217d392010-03-25 22:08:352027 // Map the ID of the saved offscreen texture into the parent so that
2028 // it can reference it.
2029 if (parent_) {
2030 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]6217d392010-03-25 22:08:352031 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:032032 parent_->CreateTextureInfo(parent_client_texture_id, service_id);
[email protected]4874aae2011-03-18 01:19:562033 info->SetNotOwned();
[email protected]6217d392010-03-25 22:08:352034 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
2035 }
2036
2037 // Allocate the render buffers at their initial size and check the status
2038 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:022039 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352040 if (!UpdateOffscreenFrameBufferSize()) {
[email protected]d0498742010-09-20 20:27:012041 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352042 Destroy();
2043 return false;
2044 }
2045
2046 // Bind to the new default frame buffer (the offscreen target frame buffer).
2047 // This should now be associated with ID zero.
2048 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]a3a93e7b2010-08-28 00:48:562049
2050 glGenFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:352051 }
2052
[email protected]76a0ee102010-04-07 21:03:042053 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2054 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2055 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372056 // mailing list archives. It also implicitly enables the desktop GL
2057 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2058 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152059 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2060 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372061 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152062 }
[email protected]de17df392010-04-23 21:09:412063
[email protected]c2f8c8402010-12-06 18:07:242064 if (!InitializeShaderTranslator()) {
2065 return false;
[email protected]de17df392010-04-23 21:09:412066 }
[email protected]76a0ee102010-04-07 21:03:042067
[email protected]246a70452010-03-05 21:53:502068 return true;
[email protected]96449d2c2009-11-25 00:01:322069}
2070
[email protected]c2f8c8402010-12-06 18:07:242071bool GLES2DecoderImpl::InitializeShaderTranslator() {
2072 // Re-check the state of use_shader_translator_ each time this is called.
2073 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
2074 feature_info_->feature_flags().chromium_webglsl &&
2075 !use_shader_translator_) {
2076 use_shader_translator_ = true;
2077 }
2078 if (!use_shader_translator_) {
2079 return true;
2080 }
2081 ShBuiltInResources resources;
2082 ShInitBuiltInResources(&resources);
2083 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2084 resources.MaxVertexUniformVectors =
2085 group_->max_vertex_uniform_vectors();
2086 resources.MaxVaryingVectors = group_->max_varying_vectors();
2087 resources.MaxVertexTextureImageUnits =
2088 group_->max_vertex_texture_image_units();
2089 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2090 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2091 resources.MaxFragmentUniformVectors =
2092 group_->max_fragment_uniform_vectors();
2093 resources.MaxDrawBuffers = 1;
2094 resources.OES_standard_derivatives =
2095 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
2096 vertex_translator_.reset(new ShaderTranslator);
2097 ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ?
2098 SH_WEBGL_SPEC : SH_GLES2_SPEC;
2099 bool is_glsl_es =
2100 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
2101 if (!vertex_translator_->Init(
2102 SH_VERTEX_SHADER, shader_spec, &resources, is_glsl_es)) {
2103 LOG(ERROR) << "Could not initialize vertex shader translator.";
2104 Destroy();
2105 return false;
2106 }
2107 fragment_translator_.reset(new ShaderTranslator);
2108 if (!fragment_translator_->Init(
2109 SH_FRAGMENT_SHADER, shader_spec, &resources, is_glsl_es)) {
2110 LOG(ERROR) << "Could not initialize fragment shader translator.";
2111 Destroy();
2112 return false;
2113 }
2114 return true;
2115}
2116
[email protected]ae51d192010-04-27 00:48:032117bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472118 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032119 if (GetBufferInfo(client_ids[ii])) {
2120 return false;
2121 }
2122 }
2123 scoped_array<GLuint> service_ids(new GLuint[n]);
2124 glGenBuffersARB(n, service_ids.get());
2125 for (GLsizei ii = 0; ii < n; ++ii) {
2126 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2127 }
2128 return true;
2129}
2130
2131bool GLES2DecoderImpl::GenFramebuffersHelper(
2132 GLsizei n, const GLuint* client_ids) {
2133 for (GLsizei ii = 0; ii < n; ++ii) {
2134 if (GetFramebufferInfo(client_ids[ii])) {
2135 return false;
2136 }
2137 }
2138 scoped_array<GLuint> service_ids(new GLuint[n]);
2139 glGenFramebuffersEXT(n, service_ids.get());
2140 for (GLsizei ii = 0; ii < n; ++ii) {
2141 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2142 }
2143 return true;
2144}
2145
2146bool GLES2DecoderImpl::GenRenderbuffersHelper(
2147 GLsizei n, const GLuint* client_ids) {
2148 for (GLsizei ii = 0; ii < n; ++ii) {
2149 if (GetRenderbufferInfo(client_ids[ii])) {
2150 return false;
2151 }
2152 }
2153 scoped_array<GLuint> service_ids(new GLuint[n]);
2154 glGenRenderbuffersEXT(n, service_ids.get());
2155 for (GLsizei ii = 0; ii < n; ++ii) {
2156 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2157 }
2158 return true;
2159}
2160
2161bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2162 for (GLsizei ii = 0; ii < n; ++ii) {
2163 if (GetTextureInfo(client_ids[ii])) {
2164 return false;
2165 }
2166 }
2167 scoped_array<GLuint> service_ids(new GLuint[n]);
2168 glGenTextures(n, service_ids.get());
2169 for (GLsizei ii = 0; ii < n; ++ii) {
2170 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2171 }
2172 return true;
2173}
2174
2175void GLES2DecoderImpl::DeleteBuffersHelper(
2176 GLsizei n, const GLuint* client_ids) {
2177 for (GLsizei ii = 0; ii < n; ++ii) {
2178 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
2179 if (info) {
2180 GLuint service_id = info->service_id();
2181 glDeleteBuffersARB(1, &service_id);
2182 RemoveBufferInfo(client_ids[ii]);
2183 }
[email protected]a93bb842010-02-16 23:03:472184 }
[email protected]07f54fcc2009-12-22 02:46:302185}
2186
[email protected]ae51d192010-04-27 00:48:032187void GLES2DecoderImpl::DeleteFramebuffersHelper(
2188 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582189 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032190 FramebufferManager::FramebufferInfo* info =
2191 GetFramebufferInfo(client_ids[ii]);
2192 if (info) {
2193 GLuint service_id = info->service_id();
2194 glDeleteFramebuffersEXT(1, &service_id);
2195 RemoveFramebufferInfo(client_ids[ii]);
2196 }
[email protected]a25fa872010-03-25 02:57:582197 }
[email protected]07f54fcc2009-12-22 02:46:302198}
2199
[email protected]ae51d192010-04-27 00:48:032200void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2201 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582202 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032203 RenderbufferManager::RenderbufferInfo* info =
2204 GetRenderbufferInfo(client_ids[ii]);
2205 if (info) {
2206 GLuint service_id = info->service_id();
2207 glDeleteRenderbuffersEXT(1, &service_id);
2208 RemoveRenderbufferInfo(client_ids[ii]);
2209 }
[email protected]a25fa872010-03-25 02:57:582210 }
[email protected]07f54fcc2009-12-22 02:46:302211}
2212
[email protected]ae51d192010-04-27 00:48:032213void GLES2DecoderImpl::DeleteTexturesHelper(
2214 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472215 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032216 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
2217 if (info) {
2218 GLuint service_id = info->service_id();
2219 glDeleteTextures(1, &service_id);
2220 RemoveTextureInfo(client_ids[ii]);
2221 }
[email protected]a93bb842010-02-16 23:03:472222 }
[email protected]07f54fcc2009-12-22 02:46:302223}
2224
[email protected]43f28f832010-02-03 02:28:482225// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322226
[email protected]eb54a562010-01-20 21:55:182227bool GLES2DecoderImpl::MakeCurrent() {
[email protected]f62a5ab2011-05-23 20:34:152228 return context_.get() ? context_->MakeCurrent(surface_.get()) : false;
[email protected]eb54a562010-01-20 21:55:182229}
2230
[email protected]8e3e0662010-08-23 18:46:302231void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2232 glBindRenderbufferEXT(
2233 GL_RENDERBUFFER,
2234 bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
2235}
2236
2237static void RebindCurrentFramebuffer(
2238 GLenum target,
2239 FramebufferManager::FramebufferInfo* info,
2240 FrameBuffer* offscreen_frame_buffer) {
2241 GLuint framebuffer_id = info ? info->service_id() : 0;
2242 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2243 framebuffer_id = offscreen_frame_buffer->id();
2244 }
2245 glBindFramebufferEXT(target, framebuffer_id);
2246}
2247
2248void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]a3ded6d2010-10-19 06:44:392249 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302250 RebindCurrentFramebuffer(
2251 GL_FRAMEBUFFER,
2252 bound_draw_framebuffer_.get(),
2253 offscreen_target_frame_buffer_.get());
2254 } else {
2255 RebindCurrentFramebuffer(
2256 GL_READ_FRAMEBUFFER_EXT,
2257 bound_read_framebuffer_.get(),
2258 offscreen_target_frame_buffer_.get());
2259 RebindCurrentFramebuffer(
2260 GL_DRAW_FRAMEBUFFER_EXT,
2261 bound_draw_framebuffer_.get(),
2262 offscreen_target_frame_buffer_.get());
2263 }
2264}
2265
2266void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2267 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2268 GLuint last_id;
2269 if (info.bound_texture_2d) {
2270 last_id = info.bound_texture_2d->service_id();
2271 } else {
2272 last_id = 0;
2273 }
2274
2275 glBindTexture(GL_TEXTURE_2D, last_id);
2276 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2277}
2278
[email protected]3a03a8f2011-03-19 00:51:272279bool GLES2DecoderImpl::CheckFramebufferComplete(const char* func_name) {
2280 if (bound_draw_framebuffer_ && bound_draw_framebuffer_->IsNotComplete()) {
[email protected]be45d7c2011-04-15 18:03:352281 SetGLError(GL_INVALID_FRAMEBUFFER_OPERATION,
[email protected]3a03a8f2011-03-19 00:51:272282 (std::string(func_name) + " framebuffer incomplete").c_str());
2283 return false;
2284 }
2285 return true;
2286}
2287
[email protected]8e3e0662010-08-23 18:46:302288gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2289 if (bound_read_framebuffer_ != 0) {
[email protected]9edc6b22010-12-23 02:00:262290 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2291 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2292 if (attachment) {
2293 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502294 }
[email protected]9edc6b22010-12-23 02:00:262295 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022296 } else if (offscreen_target_frame_buffer_.get()) {
2297 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352298 } else {
[email protected]f62a5ab2011-05-23 20:34:152299 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022300 }
[email protected]246a70452010-03-05 21:53:502301}
2302
[email protected]9edc6b22010-12-23 02:00:262303GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
2304 if (bound_read_framebuffer_ != 0) {
2305 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2306 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2307 if (attachment) {
2308 return attachment->internal_format();
2309 }
2310 return 0;
2311 } else if (offscreen_target_frame_buffer_.get()) {
2312 return offscreen_target_color_format_;
2313 } else {
[email protected]32fe9aa2011-01-21 23:47:132314 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262315 }
2316}
2317
[email protected]6217d392010-03-25 22:08:352318bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]34ff8b0c2010-10-01 20:06:022319 if (offscreen_size_ == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:352320 return true;
2321
[email protected]34ff8b0c2010-10-01 20:06:022322 offscreen_size_ = pending_offscreen_size_;
[email protected]a470d612011-02-25 04:15:002323 int w = offscreen_size_.width();
2324 int h = offscreen_size_.height();
2325 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2326 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2327 << "to allocate storage due to excessive dimensions.";
2328 return false;
2329 }
[email protected]34ff8b0c2010-10-01 20:06:022330
[email protected]6217d392010-03-25 22:08:352331 // Reallocate the offscreen target buffers.
[email protected]34ff8b0c2010-10-01 20:06:022332 DCHECK(offscreen_target_color_format_);
2333 if (IsOffscreenBufferMultisampled()) {
2334 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2335 pending_offscreen_size_, offscreen_target_color_format_,
2336 offscreen_target_samples_)) {
2337 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2338 << "to allocate storage for offscreen target color buffer.";
2339 return false;
2340 }
2341 } else {
2342 if (!offscreen_target_color_texture_->AllocateStorage(
2343 pending_offscreen_size_, offscreen_target_color_format_)) {
2344 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2345 << "to allocate storage for offscreen target color texture.";
2346 return false;
2347 }
2348 }
2349 if (offscreen_target_depth_format_ &&
2350 !offscreen_target_depth_render_buffer_->AllocateStorage(
2351 pending_offscreen_size_, offscreen_target_depth_format_,
2352 offscreen_target_samples_)) {
[email protected]d0498742010-09-20 20:27:012353 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
[email protected]34ff8b0c2010-10-01 20:06:022354 << "to allocate storage for offscreen target depth buffer.";
2355 return false;
2356 }
2357 if (offscreen_target_stencil_format_ &&
2358 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2359 pending_offscreen_size_, offscreen_target_stencil_format_,
2360 offscreen_target_samples_)) {
2361 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2362 << "to allocate storage for offscreen target stencil buffer.";
[email protected]6217d392010-03-25 22:08:352363 return false;
2364 }
2365
[email protected]2f2d7042010-04-14 21:45:582366 // Attach the offscreen target buffers to the target frame buffer.
[email protected]34ff8b0c2010-10-01 20:06:022367 if (IsOffscreenBufferMultisampled()) {
[email protected]b9363b22010-06-09 22:06:152368 offscreen_target_frame_buffer_->AttachRenderBuffer(
[email protected]34ff8b0c2010-10-01 20:06:022369 GL_COLOR_ATTACHMENT0,
2370 offscreen_target_color_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152371 } else {
[email protected]34ff8b0c2010-10-01 20:06:022372 offscreen_target_frame_buffer_->AttachRenderTexture(
2373 offscreen_target_color_texture_.get());
2374 }
2375 if (offscreen_target_depth_format_) {
2376 offscreen_target_frame_buffer_->AttachRenderBuffer(
2377 GL_DEPTH_ATTACHMENT,
2378 offscreen_target_depth_render_buffer_.get());
2379 }
2380 const bool packed_depth_stencil =
2381 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2382 if (packed_depth_stencil) {
[email protected]b9363b22010-06-09 22:06:152383 offscreen_target_frame_buffer_->AttachRenderBuffer(
2384 GL_STENCIL_ATTACHMENT,
2385 offscreen_target_depth_render_buffer_.get());
[email protected]34ff8b0c2010-10-01 20:06:022386 } else if (offscreen_target_stencil_format_) {
2387 offscreen_target_frame_buffer_->AttachRenderBuffer(
2388 GL_STENCIL_ATTACHMENT,
2389 offscreen_target_stencil_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152390 }
[email protected]34ff8b0c2010-10-01 20:06:022391
[email protected]6217d392010-03-25 22:08:352392 if (offscreen_target_frame_buffer_->CheckStatus() !=
2393 GL_FRAMEBUFFER_COMPLETE) {
[email protected]d0498742010-09-20 20:27:012394 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2395 << "because offscreen FBO was incomplete.";
[email protected]6217d392010-03-25 22:08:352396 return false;
2397 }
2398
[email protected]c007aa02010-09-02 22:22:402399 // Clear the target frame buffer.
2400 {
2401 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]3f0add5e2010-09-13 20:16:282402 glClearColor(0, 0, 0, 0);
[email protected]c007aa02010-09-02 22:22:402403 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2404 glClearStencil(0);
2405 glStencilMaskSeparate(GL_FRONT, GL_TRUE);
2406 glStencilMaskSeparate(GL_BACK, GL_TRUE);
2407 glClearDepth(0);
2408 glDepthMask(GL_TRUE);
2409 glDisable(GL_SCISSOR_TEST);
[email protected]2f2d7042010-04-14 21:45:582410 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402411 RestoreClearState();
[email protected]2f2d7042010-04-14 21:45:582412 }
[email protected]2f2d7042010-04-14 21:45:582413
[email protected]34ff8b0c2010-10-01 20:06:022414 if (parent_ || IsOffscreenBufferMultisampled()) {
[email protected]97872062010-11-03 19:07:052415 DCHECK(offscreen_saved_color_format_);
2416 offscreen_saved_color_texture_->AllocateStorage(
2417 pending_offscreen_size_, offscreen_saved_color_format_);
[email protected]d37231fa2010-04-09 21:16:022418
[email protected]34ff8b0c2010-10-01 20:06:022419 offscreen_saved_frame_buffer_->AttachRenderTexture(
2420 offscreen_saved_color_texture_.get());
2421 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2422 GL_FRAMEBUFFER_COMPLETE) {
2423 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2424 << "because offscreen saved FBO was incomplete.";
2425 return false;
2426 }
2427 }
2428
2429 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582430 // Update the info about the offscreen saved color texture in the parent.
2431 // The reference to the parent is a weak pointer and will become null if the
2432 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352433 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142434 GLuint client_id;
[email protected]262d7aa2010-12-03 22:07:292435 TextureManager* parent_texture_manager = parent_->texture_manager();
2436 CHECK(parent_texture_manager->GetClientId(service_id, &client_id));
[email protected]8d25d042010-06-16 19:48:142437 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352438 DCHECK(info);
2439
[email protected]262d7aa2010-12-03 22:07:292440 parent_texture_manager->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:112441 feature_info_,
[email protected]ef526492010-06-02 23:12:252442 info,
2443 GL_TEXTURE_2D,
2444 0, // level
2445 GL_RGBA,
2446 pending_offscreen_size_.width(),
2447 pending_offscreen_size_.height(),
2448 1, // depth
2449 0, // border
2450 GL_RGBA,
2451 GL_UNSIGNED_BYTE);
[email protected]262d7aa2010-12-03 22:07:292452 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042453 feature_info_,
2454 info,
2455 GL_TEXTURE_MAG_FILTER,
2456 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292457 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042458 feature_info_,
2459 info,
2460 GL_TEXTURE_MIN_FILTER,
2461 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292462 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042463 feature_info_,
2464 info,
2465 GL_TEXTURE_WRAP_S,
2466 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292467 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042468 feature_info_,
2469 info,
2470 GL_TEXTURE_WRAP_T,
2471 GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:352472
[email protected]c007aa02010-09-02 22:22:402473 // Clear the offscreen color texture.
2474 {
[email protected]34ff8b0c2010-10-01 20:06:022475 ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:402476 glClearColor(0, 0, 0, 0);
2477 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2478 glDisable(GL_SCISSOR_TEST);
[email protected]0c8c9d22010-06-25 17:36:392479 glClear(GL_COLOR_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402480 RestoreClearState();
[email protected]0c8c9d22010-06-25 17:36:392481 }
[email protected]0c8c9d22010-06-25 17:36:392482 }
[email protected]e566b955d2010-06-22 19:26:512483
[email protected]6217d392010-03-25 22:08:352484 return true;
2485}
2486
[email protected]7ff86b92010-11-25 17:50:002487void GLES2DecoderImpl::SetResizeCallback(Callback1<gfx::Size>::Type* callback) {
2488 resize_callback_.reset(callback);
2489}
2490
[email protected]43f28f832010-02-03 02:28:482491void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
2492 swap_buffers_callback_.reset(callback);
2493}
2494
[email protected]80c49752011-04-18 23:55:102495void GLES2DecoderImpl::SetLatchCallback(
2496 const base::Callback<void(bool)>& callback) {
2497 latch_callback_ = callback;
2498}
2499
[email protected]1318e922010-09-17 22:03:162500bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2501 uint32* service_texture_id) {
2502 TextureManager::TextureInfo* texture =
2503 texture_manager()->GetTextureInfo(client_texture_id);
2504 if (texture) {
2505 *service_texture_id = texture->service_id();
2506 return true;
2507 }
2508 return false;
2509}
2510
[email protected]96449d2c2009-11-25 00:01:322511void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392512 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052513
2514 if (group_.get())
2515 group_->set_have_context(have_context);
2516
[email protected]eadc96792010-10-27 19:39:392517 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142518 if (current_program_) {
2519 program_manager()->UnuseProgram(shader_manager(), current_program_);
2520 current_program_ = NULL;
2521 }
2522
[email protected]b1122982010-05-17 23:04:242523 if (attrib_0_buffer_id_) {
2524 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2525 }
[email protected]8fbedc02010-11-18 18:43:402526 if (fixed_attrib_buffer_id_) {
2527 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2528 }
[email protected]b1122982010-05-17 23:04:242529
[email protected]4bedba72010-04-20 22:08:542530 // Remove the saved frame buffer mapping from the parent decoder. The
2531 // parent pointer is a weak pointer so it will be null if the parent has
2532 // already been destroyed.
2533 if (parent_) {
2534 // First check the texture has been mapped into the parent. This might not
2535 // be the case if initialization failed midway through.
2536 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]ae51d192010-04-27 00:48:032537 GLuint client_id = 0;
2538 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]915a59a12010-09-30 21:29:112539 parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]4bedba72010-04-20 22:08:542540 }
[email protected]a3a93e7b2010-08-28 00:48:562541
2542 glDeleteFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:352543 }
[email protected]6217d392010-03-25 22:08:352544
[email protected]97872062010-11-03 19:07:052545 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542546 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052547 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542548 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052549 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022550 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052551 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152552 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052553 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152554 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052555 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022556 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052557 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542558 offscreen_saved_color_texture_->Destroy();
[email protected]66791e382010-07-14 20:48:302559
[email protected]eadc96792010-10-27 19:39:392560 // must release the ContextGroup before destroying the context as its
2561 // destructor uses GL.
2562 group_ = NULL;
[email protected]97872062010-11-03 19:07:052563 } else {
2564 if (offscreen_target_frame_buffer_.get())
2565 offscreen_target_frame_buffer_->Invalidate();
2566 if (offscreen_target_color_texture_.get())
2567 offscreen_target_color_texture_->Invalidate();
2568 if (offscreen_target_color_render_buffer_.get())
2569 offscreen_target_color_render_buffer_->Invalidate();
2570 if (offscreen_target_depth_render_buffer_.get())
2571 offscreen_target_depth_render_buffer_->Invalidate();
2572 if (offscreen_target_stencil_render_buffer_.get())
2573 offscreen_target_stencil_render_buffer_->Invalidate();
2574 if (offscreen_saved_frame_buffer_.get())
2575 offscreen_saved_frame_buffer_->Invalidate();
2576 if (offscreen_saved_color_texture_.get())
2577 offscreen_saved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022578 }
[email protected]97872062010-11-03 19:07:052579
[email protected]0fc35742011-04-13 17:57:542580 if (context_.get())
2581 context_->Destroy();
[email protected]fbe20372011-06-01 01:46:382582 context_ = NULL;
[email protected]0fc35742011-04-13 17:57:542583
[email protected]97872062010-11-03 19:07:052584 offscreen_target_frame_buffer_.reset();
2585 offscreen_target_color_texture_.reset();
2586 offscreen_target_color_render_buffer_.reset();
2587 offscreen_target_depth_render_buffer_.reset();
2588 offscreen_target_stencil_render_buffer_.reset();
2589 offscreen_saved_frame_buffer_.reset();
2590 offscreen_saved_color_texture_.reset();
[email protected]96449d2c2009-11-25 00:01:322591}
2592
[email protected]6217d392010-03-25 22:08:352593void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2594 // We can't resize the render buffers immediately because there might be a
2595 // partial frame rendered into them and we don't want the tail end of that
2596 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:022597 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352598}
2599
[email protected]269200b12010-11-18 22:53:062600void GLES2DecoderImpl::DoCopyTextureToParentTextureCHROMIUM(
[email protected]c007aa02010-09-02 22:22:402601 GLuint client_texture_id,
2602 GLuint parent_client_texture_id) {
[email protected]a3a93e7b2010-08-28 00:48:562603 if (parent_) {
[email protected]c007aa02010-09-02 22:22:402604 TextureManager::TextureInfo* texture = texture_manager()->GetTextureInfo(
2605 client_texture_id);
2606 TextureManager::TextureInfo* parent_texture =
2607 parent_->texture_manager()->GetTextureInfo(parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:562608 if (!texture || !parent_texture) {
2609 current_decoder_error_ = error::kInvalidArguments;
2610 return;
2611 }
2612 ScopedFrameBufferBinder fb_binder(this, copy_texture_to_parent_texture_fb_);
2613 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2614 GL_COLOR_ATTACHMENT0,
2615 GL_TEXTURE_2D,
2616 texture->service_id(),
2617 0);
2618 ScopedTexture2DBinder tex_binder(this, parent_texture->service_id());
2619 GLsizei width, height;
2620 parent_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
2621 glCopyTexImage2D(GL_TEXTURE_2D,
2622 0, // level
2623 GL_RGBA,
[email protected]c007aa02010-09-02 22:22:402624 0, 0, // x, y
[email protected]a3a93e7b2010-08-28 00:48:562625 width,
2626 height,
2627 0); // border
2628 }
2629}
2630
[email protected]43ecf372010-11-16 19:19:392631void GLES2DecoderImpl::DoResizeCHROMIUM(GLuint width, GLuint height) {
[email protected]7ff86b92010-11-25 17:50:002632#if defined(OS_LINUX)
2633 // Make sure that we are done drawing to the back buffer before resizing.
2634 glFinish();
2635#endif
2636 if (resize_callback_.get()) {
2637 gfx::Size size(width, height);
2638 resize_callback_->Run(size);
2639 }
[email protected]43ecf372010-11-16 19:19:392640}
2641
[email protected]fbe20372011-06-01 01:46:382642void GLES2DecoderImpl::DoSetSurfaceCHROMIUM(GLint surface_id) {
2643 gfx::GLSurface* surface = surface_manager_->LookupSurface(surface_id);
2644 if (!surface)
2645 return;
2646
2647 surface_ = surface;
2648}
2649
[email protected]96449d2c2009-11-25 00:01:322650const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2651 if (command_id > kStartPoint && command_id < kNumCommands) {
2652 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2653 }
2654 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2655}
2656
2657// Decode command with its arguments, and call the corresponding GL function.
2658// Note: args is a pointer to the command buffer. As such, it could be changed
2659// by a (malicious) client at any time, so if validation has to happen, it
2660// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142661error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322662 unsigned int command,
2663 unsigned int arg_count,
2664 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142665 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192666 if (debug()) {
2667 // TODO(gman): Change output to something useful for NaCl.
[email protected]d366c482010-10-20 00:11:272668 DVLOG(1) << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192669 }
[email protected]96449d2c2009-11-25 00:01:322670 unsigned int command_index = command - kStartPoint - 1;
2671 if (command_index < arraysize(g_command_info)) {
2672 const CommandInfo& info = g_command_info[command_index];
2673 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2674 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2675 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192676 uint32 immediate_data_size =
2677 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322678 switch (command) {
2679 #define GLES2_CMD_OP(name) \
2680 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192681 result = Handle ## name( \
2682 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322683 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192684 break; \
[email protected]96449d2c2009-11-25 00:01:322685
2686 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322687 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382688 }
2689 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302690 GLenum error;
2691 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382692 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292693 SetGLError(error, NULL);
[email protected]d366c482010-10-20 00:11:272694 DVLOG(1) << "GL ERROR: " << error << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192695 }
[email protected]96449d2c2009-11-25 00:01:322696 }
2697 } else {
[email protected]f7a64ee2010-02-01 22:24:142698 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322699 }
[email protected]b9849abf2009-11-25 19:13:192700 } else {
2701 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322702 }
[email protected]a3a93e7b2010-08-28 00:48:562703 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
2704 result = current_decoder_error_;
2705 current_decoder_error_ = error::kNoError;
2706 }
[email protected]b9849abf2009-11-25 19:13:192707 return result;
[email protected]96449d2c2009-11-25 00:01:322708}
2709
[email protected]ae51d192010-04-27 00:48:032710void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2711 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502712}
2713
[email protected]ae51d192010-04-27 00:48:032714bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2715 if (GetProgramInfo(client_id)) {
2716 return false;
2717 }
[email protected]96449d2c2009-11-25 00:01:322718 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032719 if (service_id != 0) {
2720 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322721 }
[email protected]ae51d192010-04-27 00:48:032722 return true;
[email protected]96449d2c2009-11-25 00:01:322723}
2724
[email protected]ae51d192010-04-27 00:48:032725bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2726 if (GetShaderInfo(client_id)) {
2727 return false;
[email protected]96449d2c2009-11-25 00:01:322728 }
[email protected]ae51d192010-04-27 00:48:032729 GLuint service_id = glCreateShader(type);
2730 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382731 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032732 }
2733 return true;
[email protected]96449d2c2009-11-25 00:01:322734}
2735
[email protected]3916c97e2010-02-25 03:20:502736void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452737 GLuint texture_index = texture_unit - GL_TEXTURE0;
2738 if (texture_index > group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292739 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502740 return;
2741 }
[email protected]36cef8ce2010-03-16 07:34:452742 active_texture_unit_ = texture_index;
2743 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502744}
2745
[email protected]051b1372010-04-12 02:42:082746void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502747 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082748 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032749 if (client_id != 0) {
2750 info = GetBufferInfo(client_id);
2751 if (!info) {
2752 // It's a new id so make a buffer info for it.
2753 glGenBuffersARB(1, &service_id);
2754 CreateBufferInfo(client_id, service_id);
2755 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102756 IdAllocator* id_allocator =
2757 group_->GetIdAllocator(id_namespaces::kBuffers);
2758 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032759 }
[email protected]051b1372010-04-12 02:42:082760 }
[email protected]ae51d192010-04-27 00:48:032761 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102762 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292763 SetGLError(GL_INVALID_OPERATION,
2764 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472765 return;
2766 }
[email protected]ae51d192010-04-27 00:48:032767 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472768 }
[email protected]96449d2c2009-11-25 00:01:322769 switch (target) {
2770 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502771 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322772 break;
2773 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502774 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322775 break;
2776 default:
[email protected]a93bb842010-02-16 23:03:472777 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322778 break;
2779 }
[email protected]051b1372010-04-12 02:42:082780 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322781}
2782
[email protected]051b1372010-04-12 02:42:082783void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2784 FramebufferManager::FramebufferInfo* info = NULL;
2785 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032786 if (client_id != 0) {
2787 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082788 if (!info) {
[email protected]ae51d192010-04-27 00:48:032789 // It's a new id so make a framebuffer info for it.
2790 glGenFramebuffersEXT(1, &service_id);
2791 CreateFramebufferInfo(client_id, service_id);
2792 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102793 IdAllocator* id_allocator =
2794 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2795 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032796 } else {
2797 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082798 }
[email protected]06c8b082011-01-05 18:00:362799 info->MarkAsValid();
[email protected]eff9a222010-12-21 21:48:562800 } else {
[email protected]f62a5ab2011-05-23 20:34:152801 service_id = 0;
[email protected]051b1372010-04-12 02:42:082802 }
[email protected]8e3e0662010-08-23 18:46:302803
2804 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
2805 bound_draw_framebuffer_ = info;
2806 }
2807 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
2808 bound_read_framebuffer_ = info;
2809 }
[email protected]6217d392010-03-25 22:08:352810
2811 // When rendering to an offscreen frame buffer, instead of unbinding from
2812 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:082813 if (info == NULL && offscreen_target_frame_buffer_.get())
2814 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:352815
[email protected]051b1372010-04-12 02:42:082816 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562817}
2818
[email protected]051b1372010-04-12 02:42:082819void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2820 RenderbufferManager::RenderbufferInfo* info = NULL;
2821 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032822 if (client_id != 0) {
2823 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082824 if (!info) {
[email protected]ae51d192010-04-27 00:48:032825 // It's a new id so make a renderbuffer info for it.
2826 glGenRenderbuffersEXT(1, &service_id);
2827 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102828 info = GetRenderbufferInfo(client_id);
2829 IdAllocator* id_allocator =
2830 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2831 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032832 } else {
2833 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082834 }
[email protected]06c8b082011-01-05 18:00:362835 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:082836 }
2837 bound_renderbuffer_ = info;
2838 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562839}
2840
[email protected]051b1372010-04-12 02:42:082841void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032842 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082843 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032844 if (client_id != 0) {
2845 info = GetTextureInfo(client_id);
2846 if (!info) {
2847 // It's a new id so make a texture info for it.
2848 glGenTextures(1, &service_id);
2849 CreateTextureInfo(client_id, service_id);
2850 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:102851 IdAllocator* id_allocator =
2852 group_->GetIdAllocator(id_namespaces::kTextures);
2853 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032854 }
2855 } else {
2856 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082857 }
[email protected]ae51d192010-04-27 00:48:032858
[email protected]1958e0e2010-04-22 05:17:152859 // Check the texture exists
2860 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032861 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292862 SetGLError(GL_INVALID_OPERATION,
2863 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152864 return;
2865 }
2866 if (info->target() == 0) {
2867 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472868 }
[email protected]ae51d192010-04-27 00:48:032869 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502870 TextureUnit& unit = texture_units_[active_texture_unit_];
2871 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472872 switch (target) {
2873 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502874 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472875 break;
2876 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502877 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472878 break;
2879 default:
2880 NOTREACHED(); // Validation should prevent us getting here.
2881 break;
2882 }
2883}
2884
[email protected]07f54fcc2009-12-22 02:46:302885void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082886 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:122887 if (index != 0 ||
2888 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:242889 glDisableVertexAttribArray(index);
2890 }
[email protected]07f54fcc2009-12-22 02:46:302891 } else {
[email protected]8eee29c2010-04-29 03:38:292892 SetGLError(GL_INVALID_VALUE,
2893 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302894 }
2895}
2896
2897void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082898 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302899 glEnableVertexAttribArray(index);
2900 } else {
[email protected]8eee29c2010-04-29 03:38:292901 SetGLError(GL_INVALID_VALUE,
2902 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302903 }
2904}
2905
[email protected]a93bb842010-02-16 23:03:472906void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502907 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]915a59a12010-09-30 21:29:112908 if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) {
[email protected]8eee29c2010-04-29 03:38:292909 SetGLError(GL_INVALID_OPERATION,
2910 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472911 return;
2912 }
[email protected]59f3ca02011-03-26 22:24:192913 // Workaround for Mac driver bug. In the large scheme of things setting
2914 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
2915 // hit so there's probably no need to make this conditional.
2916 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
[email protected]a93bb842010-02-16 23:03:472917 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:192918 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:472919}
2920
[email protected]b273e432010-04-12 17:23:582921bool GLES2DecoderImpl::GetHelper(
2922 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582923 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152924 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2925 switch (pname) {
[email protected]b273e432010-04-12 17:23:582926 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2927 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102928 if (params) {
[email protected]5094b0f2010-11-09 19:45:242929 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:102930 }
[email protected]b273e432010-04-12 17:23:582931 return true;
2932 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2933 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102934 if (params) {
[email protected]5094b0f2010-11-09 19:45:242935 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:102936 }
[email protected]b273e432010-04-12 17:23:582937 return true;
2938 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2939 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102940 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482941 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102942 }
[email protected]b273e432010-04-12 17:23:582943 return true;
2944 case GL_MAX_VARYING_VECTORS:
2945 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102946 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482947 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102948 }
[email protected]b273e432010-04-12 17:23:582949 return true;
2950 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2951 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102952 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482953 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102954 }
[email protected]b273e432010-04-12 17:23:582955 return true;
[email protected]5094b0f2010-11-09 19:45:242956 case GL_MAX_VIEWPORT_DIMS:
2957 if (offscreen_target_frame_buffer_.get()) {
2958 *num_written = 2;
2959 if (params) {
2960 params[0] = renderbuffer_manager()->max_renderbuffer_size();
2961 params[1] = renderbuffer_manager()->max_renderbuffer_size();
2962 }
2963 return true;
2964 }
[email protected]b9363b22010-06-09 22:06:152965 }
2966 }
2967 switch (pname) {
[email protected]656dcaad2010-05-07 17:18:372968 case GL_COMPRESSED_TEXTURE_FORMATS:
2969 *num_written = 0;
2970 // We don't support compressed textures.
2971 return true;
[email protected]b273e432010-04-12 17:23:582972 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
2973 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102974 if (params) {
2975 *params = 0; // We don't support compressed textures.
2976 }
[email protected]b273e432010-04-12 17:23:582977 return true;
2978 case GL_NUM_SHADER_BINARY_FORMATS:
2979 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102980 if (params) {
2981 *params = 0; // We don't support binary shader formats.
2982 }
[email protected]b273e432010-04-12 17:23:582983 return true;
2984 case GL_SHADER_BINARY_FORMATS:
2985 *num_written = 0;
2986 return true; // We don't support binary shader format.s
2987 case GL_SHADER_COMPILER:
2988 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102989 if (params) {
2990 *params = GL_TRUE;
2991 }
[email protected]b273e432010-04-12 17:23:582992 return true;
[email protected]6b8cf1a2010-05-06 16:13:582993 case GL_ARRAY_BUFFER_BINDING:
2994 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102995 if (params) {
2996 if (bound_array_buffer_) {
2997 GLuint client_id = 0;
2998 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
2999 &client_id);
3000 *params = client_id;
3001 } else {
3002 *params = 0;
3003 }
[email protected]6b8cf1a2010-05-06 16:13:583004 }
3005 return true;
3006 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3007 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103008 if (params) {
3009 if (bound_element_array_buffer_) {
3010 GLuint client_id = 0;
3011 buffer_manager()->GetClientId(
3012 bound_element_array_buffer_->service_id(),
3013 &client_id);
3014 *params = client_id;
3015 } else {
3016 *params = 0;
3017 }
[email protected]6b8cf1a2010-05-06 16:13:583018 }
3019 return true;
3020 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303021 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583022 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103023 if (params) {
[email protected]8e3e0662010-08-23 18:46:303024 if (bound_draw_framebuffer_) {
[email protected]4e8a5b122010-05-08 22:00:103025 GLuint client_id = 0;
3026 framebuffer_manager()->GetClientId(
[email protected]8e3e0662010-08-23 18:46:303027 bound_draw_framebuffer_->service_id(), &client_id);
3028 *params = client_id;
3029 } else {
3030 *params = 0;
3031 }
3032 }
3033 return true;
3034 case GL_READ_FRAMEBUFFER_BINDING:
3035 *num_written = 1;
3036 if (params) {
3037 if (bound_read_framebuffer_) {
3038 GLuint client_id = 0;
3039 framebuffer_manager()->GetClientId(
3040 bound_read_framebuffer_->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103041 *params = client_id;
3042 } else {
3043 *params = 0;
3044 }
[email protected]6b8cf1a2010-05-06 16:13:583045 }
3046 return true;
3047 case GL_RENDERBUFFER_BINDING:
3048 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103049 if (params) {
3050 if (bound_renderbuffer_) {
3051 GLuint client_id = 0;
3052 renderbuffer_manager()->GetClientId(
3053 bound_renderbuffer_->service_id(), &client_id);
3054 *params = client_id;
3055 } else {
3056 *params = 0;
3057 }
[email protected]6b8cf1a2010-05-06 16:13:583058 }
3059 return true;
3060 case GL_CURRENT_PROGRAM:
3061 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103062 if (params) {
3063 if (current_program_) {
3064 GLuint client_id = 0;
3065 program_manager()->GetClientId(
3066 current_program_->service_id(), &client_id);
3067 *params = client_id;
3068 } else {
3069 *params = 0;
3070 }
[email protected]6b8cf1a2010-05-06 16:13:583071 }
3072 return true;
[email protected]4e8a5b122010-05-08 22:00:103073 case GL_TEXTURE_BINDING_2D:
3074 *num_written = 1;
3075 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583076 TextureUnit& unit = texture_units_[active_texture_unit_];
3077 if (unit.bound_texture_2d) {
3078 GLuint client_id = 0;
3079 texture_manager()->GetClientId(
3080 unit.bound_texture_2d->service_id(), &client_id);
3081 *params = client_id;
3082 } else {
3083 *params = 0;
3084 }
[email protected]6b8cf1a2010-05-06 16:13:583085 }
[email protected]4e8a5b122010-05-08 22:00:103086 return true;
3087 case GL_TEXTURE_BINDING_CUBE_MAP:
3088 *num_written = 1;
3089 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583090 TextureUnit& unit = texture_units_[active_texture_unit_];
3091 if (unit.bound_texture_cube_map) {
3092 GLuint client_id = 0;
3093 texture_manager()->GetClientId(
3094 unit.bound_texture_cube_map->service_id(), &client_id);
3095 *params = client_id;
3096 } else {
3097 *params = 0;
3098 }
[email protected]6b8cf1a2010-05-06 16:13:583099 }
[email protected]4e8a5b122010-05-08 22:00:103100 return true;
[email protected]b273e432010-04-12 17:23:583101 default:
[email protected]4e8a5b122010-05-08 22:00:103102 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533103 return false;
[email protected]b273e432010-04-12 17:23:583104 }
3105}
3106
[email protected]4e8a5b122010-05-08 22:00:103107bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3108 GLenum pname, GLsizei* num_values) {
3109 return GetHelper(pname, NULL, num_values);
3110}
3111
[email protected]b273e432010-04-12 17:23:583112void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3113 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103114 GLsizei num_written = 0;
3115 if (GetHelper(pname, NULL, &num_written)) {
3116 scoped_array<GLint> values(new GLint[num_written]);
3117 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583118 for (GLsizei ii = 0; ii < num_written; ++ii) {
3119 params[ii] = static_cast<GLboolean>(values[ii]);
3120 }
3121 } else {
3122 glGetBooleanv(pname, params);
3123 }
3124}
3125
3126void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3127 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103128 GLsizei num_written = 0;
3129 if (GetHelper(pname, NULL, &num_written)) {
3130 scoped_array<GLint> values(new GLint[num_written]);
3131 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583132 for (GLsizei ii = 0; ii < num_written; ++ii) {
3133 params[ii] = static_cast<GLfloat>(values[ii]);
3134 }
3135 } else {
3136 glGetFloatv(pname, params);
3137 }
3138}
3139
3140void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3141 DCHECK(params);
3142 GLsizei num_written;
3143 if (!GetHelper(pname, params, &num_written)) {
3144 glGetIntegerv(pname, params);
3145 }
3146}
3147
[email protected]a0c3e972010-04-21 00:49:133148void GLES2DecoderImpl::DoGetProgramiv(
3149 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583150 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3151 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133152 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133153 return;
3154 }
3155 info->GetProgramiv(pname, params);
3156}
3157
[email protected]558847a2010-03-24 07:02:543158error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3159 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:583160 GLuint program = static_cast<GLuint>(c.program);
3161 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3162 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033163 if (!info) {
[email protected]558847a2010-03-24 07:02:543164 return error::kNoError;
3165 }
3166 GLuint index = static_cast<GLuint>(c.index);
3167 uint32 name_size = c.data_size;
3168 const char* name = GetSharedMemoryAs<const char*>(
3169 c.name_shm_id, c.name_shm_offset, name_size);
3170 if (name == NULL) {
3171 return error::kOutOfBounds;
3172 }
3173 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033174 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543175 return error::kNoError;
3176}
3177
3178error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3179 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583180 GLuint program = static_cast<GLuint>(c.program);
3181 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3182 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033183 if (!info) {
[email protected]558847a2010-03-24 07:02:543184 return error::kNoError;
3185 }
3186 GLuint index = static_cast<GLuint>(c.index);
3187 uint32 name_size = c.data_size;
3188 const char* name = GetImmediateDataAs<const char*>(
3189 c, name_size, immediate_data_size);
3190 if (name == NULL) {
3191 return error::kOutOfBounds;
3192 }
3193 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033194 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543195 return error::kNoError;
3196}
3197
3198error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3199 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583200 GLuint program = static_cast<GLuint>(c.program);
3201 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3202 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033203 if (!info) {
[email protected]558847a2010-03-24 07:02:543204 return error::kNoError;
3205 }
3206 GLuint index = static_cast<GLuint>(c.index);
3207 Bucket* bucket = GetBucket(c.name_bucket_id);
3208 if (!bucket || bucket->size() == 0) {
3209 return error::kInvalidArguments;
3210 }
3211 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183212 if (!bucket->GetAsString(&name_str)) {
3213 return error::kInvalidArguments;
3214 }
[email protected]ae51d192010-04-27 00:48:033215 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543216 return error::kNoError;
3217}
3218
[email protected]f7a64ee2010-02-01 22:24:143219error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463220 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033221 GLuint client_id = c.shader;
3222 if (client_id) {
3223 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3224 if (info) {
[email protected]ca488e12010-12-13 20:06:143225 if (!info->IsDeleted()) {
3226 glDeleteShader(info->service_id());
3227 shader_manager()->MarkAsDeleted(info);
3228 }
[email protected]ae51d192010-04-27 00:48:033229 } else {
[email protected]8eee29c2010-04-29 03:38:293230 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033231 }
[email protected]96449d2c2009-11-25 00:01:323232 }
[email protected]f7a64ee2010-02-01 22:24:143233 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323234}
3235
[email protected]f7a64ee2010-02-01 22:24:143236error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463237 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033238 GLuint client_id = c.program;
3239 if (client_id) {
3240 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3241 if (info) {
[email protected]ca488e12010-12-13 20:06:143242 if (!info->IsDeleted()) {
3243 glDeleteProgram(info->service_id());
3244 program_manager()->MarkAsDeleted(shader_manager(), info);
3245 }
[email protected]ae51d192010-04-27 00:48:033246 } else {
[email protected]8eee29c2010-04-29 03:38:293247 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033248 }
[email protected]96449d2c2009-11-25 00:01:323249 }
[email protected]f7a64ee2010-02-01 22:24:143250 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323251}
3252
[email protected]269200b12010-11-18 22:53:063253void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103254 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3255 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3256 for (GLsizei ii = 0; ii < n; ++ii) {
3257 id_allocator->FreeID(ids[ii]);
3258 }
3259}
3260
[email protected]269200b12010-11-18 22:53:063261error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3262 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103263 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3264 GLsizei n = static_cast<GLsizei>(c.n);
3265 uint32 data_size;
3266 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3267 return error::kOutOfBounds;
3268 }
3269 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3270 c.ids_shm_id, c.ids_shm_offset, data_size);
3271 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063272 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103273 return error::kNoError;
3274 }
3275 if (ids == NULL) {
3276 return error::kOutOfBounds;
3277 }
[email protected]269200b12010-11-18 22:53:063278 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103279 return error::kNoError;
3280}
3281
[email protected]269200b12010-11-18 22:53:063282void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103283 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
3284 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3285 if (id_offset == 0) {
3286 for (GLsizei ii = 0; ii < n; ++ii) {
3287 ids[ii] = id_allocator->AllocateID();
3288 }
3289 } else {
3290 for (GLsizei ii = 0; ii < n; ++ii) {
3291 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3292 id_offset = ids[ii] + 1;
3293 }
3294 }
3295}
3296
[email protected]269200b12010-11-18 22:53:063297error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3298 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103299 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3300 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3301 GLsizei n = static_cast<GLsizei>(c.n);
3302 uint32 data_size;
3303 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3304 return error::kOutOfBounds;
3305 }
3306 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3307 c.ids_shm_id, c.ids_shm_offset, data_size);
3308 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063309 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103310 return error::kNoError;
3311 }
3312 if (ids == NULL) {
3313 return error::kOutOfBounds;
3314 }
[email protected]269200b12010-11-18 22:53:063315 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103316 return error::kNoError;
3317}
3318
[email protected]269200b12010-11-18 22:53:063319void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103320 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3321 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3322 for (GLsizei ii = 0; ii < n; ++ii) {
3323 if (!id_allocator->MarkAsUsed(ids[ii])) {
3324 for (GLsizei jj = 0; jj < ii; ++jj) {
3325 id_allocator->FreeID(ids[jj]);
3326 }
3327 SetGLError(
3328 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063329 "RegisterSharedIdsCHROMIUM: attempt to register "
3330 "id that already exists");
[email protected]066849e32010-05-03 19:14:103331 return;
3332 }
3333 }
3334}
3335
[email protected]269200b12010-11-18 22:53:063336error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3337 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103338 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3339 GLsizei n = static_cast<GLsizei>(c.n);
3340 uint32 data_size;
3341 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3342 return error::kOutOfBounds;
3343 }
3344 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3345 c.ids_shm_id, c.ids_shm_offset, data_size);
3346 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063347 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103348 return error::kNoError;
3349 }
3350 if (ids == NULL) {
3351 return error::kOutOfBounds;
3352 }
[email protected]269200b12010-11-18 22:53:063353 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103354 return error::kNoError;
3355}
3356
[email protected]3a03a8f2011-03-19 00:51:273357void GLES2DecoderImpl::DoClear(GLbitfield mask) {
3358 if (CheckFramebufferComplete("glClear")) {
3359 glClear(mask);
3360 }
3361}
3362
[email protected]07f54fcc2009-12-22 02:46:303363void GLES2DecoderImpl::DoDrawArrays(
3364 GLenum mode, GLint first, GLsizei count) {
[email protected]3a03a8f2011-03-19 00:51:273365 if (!CheckFramebufferComplete("glDrawArrays")) {
3366 return;
3367 }
[email protected]d81e8c52010-06-07 17:58:323368 // We have to check this here because the prototype for glDrawArrays
3369 // is GLint not GLsizei.
3370 if (first < 0) {
[email protected]7601c3f2010-12-22 00:41:203371 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
[email protected]d81e8c52010-06-07 17:58:323372 return;
3373 }
[email protected]6c788fb72010-08-26 02:16:313374
3375 if (count == 0) {
3376 return;
3377 }
3378
[email protected]8fbedc02010-11-18 18:43:403379 GLuint max_vertex_accessed = first + count - 1;
3380 if (IsDrawValid(max_vertex_accessed)) {
3381 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
3382 bool simulated_fixed_attribs = false;
3383 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
3384 bool textures_set = SetBlackTextureForNonRenderableTextures();
3385 glDrawArrays(mode, first, count);
3386 if (textures_set) {
3387 RestoreStateForNonRenderableTextures();
3388 }
3389 if (simulated_fixed_attribs) {
3390 RestoreStateForSimulatedFixedAttribs();
3391 }
[email protected]3916c97e2010-02-25 03:20:503392 }
[email protected]b1122982010-05-17 23:04:243393 if (simulated_attrib_0) {
3394 RestoreStateForSimulatedAttrib0();
3395 }
[email protected]07f54fcc2009-12-22 02:46:303396 }
3397}
3398
[email protected]36cef8ce2010-03-16 07:34:453399void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3400 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033401 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303402 FramebufferManager::FramebufferInfo* framebuffer_info =
3403 GetFramebufferInfoForTarget(target);
3404 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293405 SetGLError(GL_INVALID_OPERATION,
3406 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453407 return;
3408 }
[email protected]ae51d192010-04-27 00:48:033409 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283410 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033411 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283412 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033413 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293414 SetGLError(GL_INVALID_OPERATION,
3415 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033416 return;
3417 }
3418 service_id = info->service_id();
3419 }
[email protected]9edc6b22010-12-23 02:00:263420 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033421 glFramebufferRenderbufferEXT(
3422 target, attachment, renderbuffertarget, service_id);
[email protected]9edc6b22010-12-23 02:00:263423 GLenum error = glGetError();
3424 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303425 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]9edc6b22010-12-23 02:00:263426 if (service_id == 0 ||
3427 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3428 if (info) {
3429 ClearUnclearedRenderbuffers(target, framebuffer_info);
3430 }
[email protected]3a2e7c7b2010-08-06 01:12:283431 }
3432 }
3433}
3434
3435void GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
3436 switch (cap) {
3437 case GL_SCISSOR_TEST:
3438 enable_scissor_test_ = enabled;
3439 break;
3440 default:
3441 break;
3442 }
3443}
3444
3445void GLES2DecoderImpl::DoDisable(GLenum cap) {
3446 SetCapabilityState(cap, false);
3447 glDisable(cap);
3448}
3449
3450void GLES2DecoderImpl::DoEnable(GLenum cap) {
3451 SetCapabilityState(cap, true);
3452 glEnable(cap);
3453}
3454
3455void GLES2DecoderImpl::DoClearColor(
3456 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
3457 clear_red_ = red;
3458 clear_green_ = green;
3459 clear_blue_ = blue;
3460 clear_alpha_ = alpha;
3461 glClearColor(red, green, blue, alpha);
3462}
3463
3464void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
3465 clear_depth_ = depth;
3466 glClearDepth(depth);
3467}
3468
3469void GLES2DecoderImpl::DoClearStencil(GLint s) {
3470 clear_stencil_ = s;
3471 glClearStencil(s);
3472}
3473
3474void GLES2DecoderImpl::DoColorMask(
3475 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
3476 mask_red_ = red;
3477 mask_green_ = green;
3478 mask_blue_ = blue;
3479 mask_alpha_ = alpha;
3480 glColorMask(red, green, blue, alpha);
3481}
3482
3483void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
3484 mask_depth_ = depth;
3485 glDepthMask(depth);
3486}
3487
3488void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
3489 mask_stencil_front_ = mask;
3490 mask_stencil_back_ = mask;
3491 glStencilMask(mask);
3492}
3493
3494void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
3495 if (face == GL_FRONT) {
3496 mask_stencil_front_ = mask;
3497 } else {
3498 mask_stencil_back_ = mask;
3499 }
3500 glStencilMaskSeparate(face, mask);
3501}
3502
3503// NOTE: There's an assumption here that Texture attachments
3504// are cleared because they are textures so we only need to clear
3505// the renderbuffers.
3506void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
[email protected]8e3e0662010-08-23 18:46:303507 GLenum target, FramebufferManager::FramebufferInfo* info) {
3508 if (target == GL_READ_FRAMEBUFFER_EXT) {
3509 // TODO(gman): bind this to the DRAW point, clear then bind back to READ
3510 }
[email protected]3a2e7c7b2010-08-06 01:12:283511 GLbitfield clear_bits = 0;
3512 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
3513 glClearColor(0, 0, 0, 0);
3514 glColorMask(true, true, true, true);
3515 clear_bits |= GL_COLOR_BUFFER_BIT;
3516 }
3517
3518 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
3519 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3520 glClearStencil(0);
3521 glStencilMask(-1);
3522 clear_bits |= GL_STENCIL_BUFFER_BIT;
3523 }
3524
3525 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
3526 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3527 glClearDepth(1.0f);
3528 glDepthMask(true);
3529 clear_bits |= GL_DEPTH_BUFFER_BIT;
3530 }
3531
3532 glDisable(GL_SCISSOR_TEST);
3533 glClear(clear_bits);
3534
3535 info->MarkAttachedRenderbuffersAsCleared();
3536
[email protected]c007aa02010-09-02 22:22:403537 RestoreClearState();
3538
3539 if (target == GL_READ_FRAMEBUFFER_EXT) {
3540 // TODO(gman): rebind draw.
3541 }
3542}
3543
3544void GLES2DecoderImpl::RestoreClearState() {
[email protected]3a2e7c7b2010-08-06 01:12:283545 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
3546 glColorMask(mask_red_, mask_green_, mask_blue_, mask_alpha_);
3547 glClearStencil(clear_stencil_);
3548 glStencilMaskSeparate(GL_FRONT, mask_stencil_front_);
3549 glStencilMaskSeparate(GL_BACK, mask_stencil_back_);
3550 glClearDepth(clear_depth_);
3551 glDepthMask(mask_depth_);
3552 if (enable_scissor_test_) {
3553 glEnable(GL_SCISSOR_TEST);
3554 }
[email protected]36cef8ce2010-03-16 07:34:453555}
3556
3557GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]8e3e0662010-08-23 18:46:303558 FramebufferManager::FramebufferInfo* info =
3559 GetFramebufferInfoForTarget(target);
3560 if (!info) {
[email protected]36cef8ce2010-03-16 07:34:453561 return GL_FRAMEBUFFER_COMPLETE;
3562 }
3563 return glCheckFramebufferStatusEXT(target);
3564}
3565
3566void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033567 GLenum target, GLenum attachment, GLenum textarget,
3568 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303569 FramebufferManager::FramebufferInfo* framebuffer_info =
3570 GetFramebufferInfoForTarget(target);
3571 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293572 SetGLError(GL_INVALID_OPERATION,
3573 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453574 return;
3575 }
[email protected]ae51d192010-04-27 00:48:033576 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283577 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033578 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283579 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033580 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293581 SetGLError(GL_INVALID_OPERATION,
3582 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033583 return;
3584 }
3585 service_id = info->service_id();
3586 }
[email protected]9edc6b22010-12-23 02:00:263587 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033588 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]9edc6b22010-12-23 02:00:263589 GLenum error = glGetError();
3590 if (error == GL_NO_ERROR) {
3591 framebuffer_info->AttachTexture(attachment, info, textarget, level);
3592 if (service_id != 0 &&
3593 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3594 ClearUnclearedRenderbuffers(target, framebuffer_info);
3595 }
[email protected]3a2e7c7b2010-08-06 01:12:283596 }
[email protected]36cef8ce2010-03-16 07:34:453597}
3598
3599void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3600 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303601 FramebufferManager::FramebufferInfo* framebuffer_info =
3602 GetFramebufferInfoForTarget(target);
3603 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293604 SetGLError(GL_INVALID_OPERATION,
3605 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453606 return;
3607 }
3608 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573609 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3610 GLint type = 0;
3611 GLuint client_id = 0;
3612 glGetFramebufferAttachmentParameterivEXT(
3613 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3614 switch (type) {
3615 case GL_RENDERBUFFER: {
3616 renderbuffer_manager()->GetClientId(*params, &client_id);
3617 break;
3618 }
3619 case GL_TEXTURE: {
3620 texture_manager()->GetClientId(*params, &client_id);
3621 break;
3622 }
3623 default:
3624 break;
3625 }
3626 *params = client_id;
3627 }
[email protected]36cef8ce2010-03-16 07:34:453628}
3629
3630void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
3631 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:083632 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293633 SetGLError(GL_INVALID_OPERATION,
3634 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453635 return;
3636 }
[email protected]3a03a8f2011-03-19 00:51:273637 switch (pname) {
3638 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]b71f52c2010-06-18 22:20:203639 *params = bound_renderbuffer_->internal_format();
[email protected]3a03a8f2011-03-19 00:51:273640 break;
3641 case GL_RENDERBUFFER_WIDTH:
3642 *params = bound_renderbuffer_->width();
3643 break;
3644 case GL_RENDERBUFFER_HEIGHT:
3645 *params = bound_renderbuffer_->height();
3646 break;
3647 default:
3648 glGetRenderbufferParameterivEXT(target, pname, params);
3649 break;
[email protected]b71f52c2010-06-18 22:20:203650 }
[email protected]36cef8ce2010-03-16 07:34:453651}
3652
[email protected]8e3e0662010-08-23 18:46:303653void GLES2DecoderImpl::DoBlitFramebufferEXT(
3654 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3655 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3656 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:393657 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303658 SetGLError(GL_INVALID_OPERATION,
3659 "glBlitFramebufferEXT: function not available");
3660 }
[email protected]5094b0f2010-11-09 19:45:243661 if (IsAngle()) {
3662 glBlitFramebufferANGLE(
3663 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3664 } else {
3665 glBlitFramebufferEXT(
3666 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3667 }
[email protected]8e3e0662010-08-23 18:46:303668}
3669
3670void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
3671 GLenum target, GLsizei samples, GLenum internalformat,
3672 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:393673 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303674 SetGLError(GL_INVALID_OPERATION,
3675 "glRenderbufferStorageMultisampleEXT: function not available");
3676 return;
3677 }
[email protected]8e3e0662010-08-23 18:46:303678
[email protected]9edc6b22010-12-23 02:00:263679 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:303680 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263681 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:303682 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263683 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:303684 break;
3685 case GL_RGBA4:
3686 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263687 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:303688 break;
3689 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263690 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:303691 break;
3692 }
3693 }
3694
[email protected]9edc6b22010-12-23 02:00:263695 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:083696 if (IsAngle()) {
3697 glRenderbufferStorageMultisampleANGLE(
3698 target, samples, impl_format, width, height);
3699 } else {
3700 glRenderbufferStorageMultisampleEXT(
3701 target, samples, impl_format, width, height);
3702 }
[email protected]9edc6b22010-12-23 02:00:263703 GLenum error = glGetError();
3704 if (error == GL_NO_ERROR) {
3705 bound_renderbuffer_->SetInfo(samples, internalformat, width, height);
3706 }
[email protected]8e3e0662010-08-23 18:46:303707}
3708
[email protected]36cef8ce2010-03-16 07:34:453709void GLES2DecoderImpl::DoRenderbufferStorage(
3710 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:083711 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293712 SetGLError(GL_INVALID_OPERATION,
3713 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453714 return;
3715 }
[email protected]876f6fee2010-08-02 23:10:323716
[email protected]9edc6b22010-12-23 02:00:263717 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:323718 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263719 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:323720 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263721 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:323722 break;
3723 case GL_RGBA4:
3724 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263725 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:323726 break;
3727 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263728 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:323729 break;
3730 }
[email protected]b71f52c2010-06-18 22:20:203731 }
[email protected]876f6fee2010-08-02 23:10:323732
[email protected]9edc6b22010-12-23 02:00:263733 CopyRealGLErrorsToWrapper();
3734 glRenderbufferStorageEXT(target, impl_format, width, height);
3735 GLenum error = glGetError();
3736 if (error == GL_NO_ERROR) {
3737 bound_renderbuffer_->SetInfo(0, internalformat, width, height);
3738 }
[email protected]36cef8ce2010-03-16 07:34:453739}
3740
[email protected]07f54fcc2009-12-22 02:46:303741void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]6b8cf1a2010-05-06 16:13:583742 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3743 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:473744 if (!info) {
[email protected]a93bb842010-02-16 23:03:473745 return;
3746 }
[email protected]05afda12011-01-20 00:17:343747
[email protected]d685a682011-04-29 16:19:573748 info->Link();
[email protected]07f54fcc2009-12-22 02:46:303749};
3750
[email protected]3916c97e2010-02-25 03:20:503751void GLES2DecoderImpl::DoTexParameterf(
3752 GLenum target, GLenum pname, GLfloat param) {
3753 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:303754 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293755 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243756 return;
[email protected]07f54fcc2009-12-22 02:46:303757 }
[email protected]cbb22e42011-05-12 23:36:243758
3759 if (!texture_manager()->SetParameter(
3760 feature_info_, info, pname, static_cast<GLint>(param))) {
3761 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
3762 return;
3763 }
3764 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:303765}
3766
[email protected]3916c97e2010-02-25 03:20:503767void GLES2DecoderImpl::DoTexParameteri(
3768 GLenum target, GLenum pname, GLint param) {
3769 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3770 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293771 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243772 return;
[email protected]3916c97e2010-02-25 03:20:503773 }
[email protected]cbb22e42011-05-12 23:36:243774
3775 if (!texture_manager()->SetParameter(feature_info_, info, pname, param)) {
3776 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
3777 return;
3778 }
3779 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:503780}
3781
3782void GLES2DecoderImpl::DoTexParameterfv(
3783 GLenum target, GLenum pname, const GLfloat* params) {
3784 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3785 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293786 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243787 return;
[email protected]3916c97e2010-02-25 03:20:503788 }
[email protected]cbb22e42011-05-12 23:36:243789
3790 if (!texture_manager()->SetParameter(
3791 feature_info_, info, pname, static_cast<GLint>(params[0]))) {
3792 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
3793 return;
3794 }
3795 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503796}
3797
3798void GLES2DecoderImpl::DoTexParameteriv(
3799 GLenum target, GLenum pname, const GLint* params) {
3800 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3801 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293802 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243803 return;
[email protected]3916c97e2010-02-25 03:20:503804 }
[email protected]cbb22e42011-05-12 23:36:243805
3806 if (!texture_manager()->SetParameter(feature_info_, info, pname, *params)) {
3807 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
3808 return;
3809 }
3810 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503811}
3812
[email protected]939e7362010-05-13 20:49:103813bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:143814 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:103815 // The program does not exist.
3816 SetGLError(GL_INVALID_OPERATION,
3817 (std::string(function_name) + ": no program in use").c_str());
3818 return false;
3819 }
[email protected]ca488e12010-12-13 20:06:143820 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:103821 SetGLError(GL_INVALID_OPERATION,
3822 (std::string(function_name) + ": program not linked").c_str());
3823 return false;
3824 }
3825 return true;
3826}
3827
3828bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
3829 GLint location, const char* function_name) {
3830 if (!CheckCurrentProgram(function_name)) {
3831 return false;
3832 }
3833 return location != -1;
3834}
3835
[email protected]43c2f1f2011-03-25 18:35:363836bool GLES2DecoderImpl::PrepForSetUniformByLocation(
3837 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
3838 DCHECK(type);
3839 DCHECK(count);
[email protected]939e7362010-05-13 20:49:103840 if (!CheckCurrentProgramForUniform(location, function_name)) {
3841 return false;
3842 }
[email protected]43c2f1f2011-03-25 18:35:363843 GLint array_index = -1;
3844 const ProgramManager::ProgramInfo::UniformInfo* info =
3845 current_program_->GetUniformInfoByLocation(location, &array_index);
3846 if (!info) {
[email protected]939e7362010-05-13 20:49:103847 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:363848 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:103849 return false;
3850 }
[email protected]43c2f1f2011-03-25 18:35:363851 if (*count > 1 && !info->is_array) {
3852 SetGLError(
3853 GL_INVALID_OPERATION,
3854 (std::string(function_name) + ": count > 1 for non-array").c_str());
3855 return false;
3856 }
3857 *count = std::min(info->size - array_index, *count);
3858 if (*count <= 0) {
3859 return false;
3860 }
3861 *type = info->type;
[email protected]939e7362010-05-13 20:49:103862 return true;
3863}
3864
[email protected]939e7362010-05-13 20:49:103865void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
3866 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:503867 return;
3868 }
3869 current_program_->SetSamplers(location, 1, &v0);
3870 glUniform1i(location, v0);
3871}
3872
3873void GLES2DecoderImpl::DoUniform1iv(
3874 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:103875 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:503876 return;
3877 }
[email protected]43c2f1f2011-03-25 18:35:363878 GLenum type = 0;
3879 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
3880 return;
3881 }
3882 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE) {
3883 current_program_->SetSamplers(location, count, value);
3884 }
[email protected]3916c97e2010-02-25 03:20:503885 glUniform1iv(location, count, value);
3886}
3887
[email protected]939e7362010-05-13 20:49:103888void GLES2DecoderImpl::DoUniform1fv(
3889 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363890 GLenum type = 0;
3891 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103892 return;
3893 }
3894 if (type == GL_BOOL) {
3895 scoped_array<GLint> temp(new GLint[count]);
3896 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:533897 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103898 }
3899 DoUniform1iv(location, count, temp.get());
3900 } else {
3901 glUniform1fv(location, count, value);
3902 }
3903}
3904
3905void GLES2DecoderImpl::DoUniform2fv(
3906 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363907 GLenum type = 0;
3908 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103909 return;
3910 }
3911 if (type == GL_BOOL_VEC2) {
3912 GLsizei num_values = count * 2;
3913 scoped_array<GLint> temp(new GLint[num_values]);
3914 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533915 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103916 }
3917 glUniform2iv(location, count, temp.get());
3918 } else {
3919 glUniform2fv(location, count, value);
3920 }
3921}
3922
3923void GLES2DecoderImpl::DoUniform3fv(
3924 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363925 GLenum type = 0;
3926 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103927 return;
3928 }
3929 if (type == GL_BOOL_VEC3) {
3930 GLsizei num_values = count * 3;
3931 scoped_array<GLint> temp(new GLint[num_values]);
3932 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533933 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103934 }
3935 glUniform3iv(location, count, temp.get());
3936 } else {
3937 glUniform3fv(location, count, value);
3938 }
3939}
3940
3941void GLES2DecoderImpl::DoUniform4fv(
3942 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363943 GLenum type = 0;
3944 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103945 return;
3946 }
3947 if (type == GL_BOOL_VEC4) {
3948 GLsizei num_values = count * 4;
3949 scoped_array<GLint> temp(new GLint[num_values]);
3950 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533951 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103952 }
3953 glUniform4iv(location, count, temp.get());
3954 } else {
3955 glUniform4fv(location, count, value);
3956 }
3957}
3958
[email protected]43c2f1f2011-03-25 18:35:363959void GLES2DecoderImpl::DoUniform2iv(
3960 GLint location, GLsizei count, const GLint* value) {
3961 GLenum type = 0;
3962 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
3963 return;
3964 }
3965 glUniform2iv(location, count, value);
3966}
3967
3968void GLES2DecoderImpl::DoUniform3iv(
3969 GLint location, GLsizei count, const GLint* value) {
3970 GLenum type = 0;
3971 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
3972 return;
3973 }
3974 glUniform3iv(location, count, value);
3975}
3976
3977void GLES2DecoderImpl::DoUniform4iv(
3978 GLint location, GLsizei count, const GLint* value) {
3979 GLenum type = 0;
3980 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
3981 return;
3982 }
3983 glUniform4iv(location, count, value);
3984}
3985
3986void GLES2DecoderImpl::DoUniformMatrix2fv(
3987 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
3988 GLenum type = 0;
3989 if (!PrepForSetUniformByLocation(
3990 location, "glUniformMatrix2fv", &type, &count)) {
3991 return;
3992 }
3993 glUniformMatrix2fv (location, count, transpose, value);
3994}
3995
3996void GLES2DecoderImpl::DoUniformMatrix3fv(
3997 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
3998 GLenum type = 0;
3999 if (!PrepForSetUniformByLocation(
4000 location, "glUniformMatrix3fv", &type, &count)) {
4001 return;
4002 }
4003 glUniformMatrix3fv (location, count, transpose, value);
4004}
4005
4006void GLES2DecoderImpl::DoUniformMatrix4fv(
4007 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4008 GLenum type = 0;
4009 if (!PrepForSetUniformByLocation(
4010 location, "glUniformMatrix4fv", &type, &count)) {
4011 return;
4012 }
4013 glUniformMatrix4fv (location, count, transpose, value);
4014}
4015
[email protected]3916c97e2010-02-25 03:20:504016void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034017 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504018 ProgramManager::ProgramInfo* info = NULL;
4019 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584020 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504021 if (!info) {
[email protected]ae51d192010-04-27 00:48:034022 return;
4023 }
4024 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504025 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294026 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504027 return;
4028 }
[email protected]ae51d192010-04-27 00:48:034029 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504030 }
[email protected]ca488e12010-12-13 20:06:144031 if (current_program_) {
4032 program_manager()->UnuseProgram(shader_manager(), current_program_);
4033 }
[email protected]3916c97e2010-02-25 03:20:504034 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144035 if (current_program_) {
4036 program_manager()->UseProgram(current_program_);
4037 }
[email protected]ae51d192010-04-27 00:48:034038 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504039}
4040
[email protected]96449d2c2009-11-25 00:01:324041GLenum GLES2DecoderImpl::GetGLError() {
4042 // Check the GL error first, then our wrapped error.
4043 GLenum error = glGetError();
4044 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374045 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324046 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294047 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324048 break;
4049 }
4050 }
4051 }
4052
4053 if (error != GL_NO_ERROR) {
4054 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294055 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324056 }
4057 return error;
4058}
4059
[email protected]8eee29c2010-04-29 03:38:294060void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4061 if (msg) {
4062 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:014063 LOG(ERROR) << last_error_;
[email protected]8eee29c2010-04-29 03:38:294064 }
[email protected]ddd968b82010-03-02 00:44:294065 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324066}
4067
[email protected]07f54fcc2009-12-22 02:46:304068void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4069 GLenum error;
4070 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294071 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304072 }
4073}
4074
[email protected]6217d392010-03-25 22:08:354075void GLES2DecoderImpl::ClearRealGLErrors() {
4076 GLenum error;
4077 while ((error = glGetError()) != GL_NO_ERROR) {
4078 NOTREACHED() << "GL error " << error << " was unhandled.";
4079 }
4080}
4081
[email protected]ef526492010-06-02 23:12:254082bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504083 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254084 // Only check if there are some unrenderable textures.
4085 if (!texture_manager()->HaveUnrenderableTextures()) {
4086 return false;
4087 }
4088 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504089 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4090 current_program_->sampler_indices();
4091 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4092 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4093 current_program_->GetUniformInfo(sampler_indices[ii]);
4094 DCHECK(uniform_info);
4095 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4096 GLuint texture_unit_index = uniform_info->texture_units[jj];
4097 if (texture_unit_index < group_->max_texture_units()) {
4098 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4099 TextureManager::TextureInfo* texture_info =
4100 uniform_info->type == GL_SAMPLER_2D ?
4101 texture_unit.bound_texture_2d :
4102 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114103 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]ef526492010-06-02 23:12:254104 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504105 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4106 glBindTexture(
4107 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
4108 GL_TEXTURE_CUBE_MAP,
[email protected]00f893d2010-08-24 18:55:494109 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504110 }
4111 }
4112 // else: should this be an error?
4113 }
4114 }
[email protected]ef526492010-06-02 23:12:254115 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504116}
4117
4118void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4119 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504120 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4121 current_program_->sampler_indices();
4122 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4123 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4124 current_program_->GetUniformInfo(sampler_indices[ii]);
4125 DCHECK(uniform_info);
4126 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4127 GLuint texture_unit_index = uniform_info->texture_units[jj];
4128 if (texture_unit_index < group_->max_texture_units()) {
4129 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4130 TextureManager::TextureInfo* texture_info =
4131 uniform_info->type == GL_SAMPLER_2D ?
4132 texture_unit.bound_texture_2d :
4133 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114134 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]3916c97e2010-02-25 03:20:504135 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4136 // Get the texture info that was previously bound here.
4137 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4138 texture_unit.bound_texture_2d :
4139 texture_unit.bound_texture_cube_map;
4140 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034141 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504142 }
4143 }
4144 }
4145 }
4146 // Set the active texture back to whatever the user had it as.
4147 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304148}
4149
4150bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034151 // NOTE: We specifically do not check current_program->IsValid() because
4152 // it could never be invalid since glUseProgram would have failed. While
4153 // glLinkProgram could later mark the program as invalid the previous
4154 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144155 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504156 // The program does not exist.
4157 // But GL says no ERROR.
4158 return false;
4159 }
[email protected]f39f4b3f2010-05-12 17:04:084160 // Validate all attribs currently enabled. If they are used by the current
4161 // program then check that they have enough elements to handle the draw call.
4162 // If they are not used by the current program check that they have a buffer
4163 // assigned.
4164 const VertexAttribManager::VertexAttribInfoList& infos =
4165 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4166 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404167 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084168 const VertexAttribManager::VertexAttribInfo* info = *it;
4169 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4170 current_program_->GetAttribInfoByLocation(info->index());
4171 if (attrib_info) {
4172 // This attrib is used in the current program.
4173 if (!info->CanAccess(max_vertex_accessed)) {
4174 SetGLError(GL_INVALID_OPERATION,
4175 "glDrawXXX: attempt to access out of range vertices");
4176 return false;
4177 }
4178 } else {
4179 // This attrib is not used in the current program.
4180 if (!info->buffer() || info->buffer()->IsDeleted()) {
4181 SetGLError(
4182 GL_INVALID_OPERATION,
4183 "glDrawXXX: attempt to render with no buffer attached to enabled "
4184 "attrib");
4185 return false;
4186 }
[email protected]1d32bc82010-01-13 22:06:464187 }
[email protected]07f54fcc2009-12-22 02:46:304188 }
[email protected]3916c97e2010-02-25 03:20:504189 return true;
[email protected]b1122982010-05-17 23:04:244190}
4191
4192bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
[email protected]876f6fee2010-08-02 23:10:324193 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4194 return false;
4195
[email protected]b1122982010-05-17 23:04:244196 const VertexAttribManager::VertexAttribInfo* info =
4197 vertex_attrib_manager_.GetVertexAttribInfo(0);
4198 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494199 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4200 if (info->enabled() && attrib_0_used) {
[email protected]b1122982010-05-17 23:04:244201 return false;
4202 }
4203
4204 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4205
4206 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4207
4208 // Make a buffer with a single repeated vec4 value enough to
4209 // simulate the constant value that is supposed to be here.
4210 // This is required to emulate GLES2 on GL.
4211 GLsizei num_vertices = max_vertex_accessed + 1;
4212 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
[email protected]fc753442011-02-04 19:49:494213 if (size_needed > attrib_0_size_) {
4214 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4215 // TODO(gman): check for error here?
4216 attrib_0_buffer_matches_value_ = false;
4217 }
4218 if (attrib_0_used &&
4219 (!attrib_0_buffer_matches_value_ ||
4220 (info->value().v[0] != attrib_0_value_.v[0] ||
4221 info->value().v[1] != attrib_0_value_.v[1] ||
4222 info->value().v[2] != attrib_0_value_.v[2] ||
4223 info->value().v[3] != attrib_0_value_.v[3]))) {
4224 std::vector<Vec4> temp(num_vertices, info->value());
4225 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4226 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244227 attrib_0_value_ = info->value();
4228 attrib_0_size_ = size_needed;
4229 }
4230
4231 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4232
4233 return true;
[email protected]b1122982010-05-17 23:04:244234}
4235
4236void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4237 const VertexAttribManager::VertexAttribInfo* info =
4238 vertex_attrib_manager_.GetVertexAttribInfo(0);
4239 const void* ptr = reinterpret_cast<const void*>(info->offset());
4240 BufferManager::BufferInfo* buffer_info = info->buffer();
4241 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4242 glVertexAttribPointer(
4243 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4244 ptr);
4245 glBindBuffer(GL_ARRAY_BUFFER,
4246 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4247}
[email protected]07f54fcc2009-12-22 02:46:304248
[email protected]8fbedc02010-11-18 18:43:404249bool GLES2DecoderImpl::SimulateFixedAttribs(
4250 GLuint max_vertex_accessed, bool* simulated) {
4251 DCHECK(simulated);
4252 *simulated = false;
4253 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4254 return true;
4255
4256 if (!vertex_attrib_manager_.HaveFixedAttribs()) {
4257 return true;
4258 }
4259
4260 // NOTE: we could be smart and try to check if a buffer is used
4261 // twice in 2 different attribs, find the overlapping parts and therefore
4262 // duplicate the minimum amount of data but this whole code path is not meant
4263 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4264 // tests so we just add to the buffer attrib used.
4265
4266 // Compute the number of elements needed.
4267 int num_vertices = max_vertex_accessed + 1;
4268 int elements_needed = 0;
4269 const VertexAttribManager::VertexAttribInfoList& infos =
4270 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4271 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4272 infos.begin(); it != infos.end(); ++it) {
4273 const VertexAttribManager::VertexAttribInfo* info = *it;
4274 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4275 current_program_->GetAttribInfoByLocation(info->index());
4276 if (attrib_info &&
4277 info->CanAccess(max_vertex_accessed) &&
4278 info->type() == GL_FIXED) {
4279 int elements_used = 0;
4280 if (!SafeMultiply(
4281 static_cast<int>(num_vertices),
4282 info->size(), &elements_used) ||
4283 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4284 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4285 return false;
4286 }
4287 }
4288 }
4289
4290 const int kSizeOfFloat = sizeof(float); // NOLINT
4291 int size_needed = 0;
4292 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed)) {
4293 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4294 return false;
4295 }
4296
4297
4298 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
4299 if (size_needed > fixed_attrib_buffer_size_) {
4300 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4301 }
4302
4303 // Copy the elements and convert to float
4304 GLintptr offset = 0;
4305 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4306 infos.begin(); it != infos.end(); ++it) {
4307 const VertexAttribManager::VertexAttribInfo* info = *it;
4308 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4309 current_program_->GetAttribInfoByLocation(info->index());
4310 if (attrib_info &&
4311 info->CanAccess(max_vertex_accessed) &&
4312 info->type() == GL_FIXED) {
4313 int num_elements = info->size() * kSizeOfFloat;
4314 int size = num_elements * num_vertices;
4315 scoped_array<float> data(new float[size]);
4316 const int32* src = reinterpret_cast<const int32 *>(
4317 info->buffer()->GetRange(info->offset(), size));
4318 const int32* end = src + num_elements;
4319 float* dst = data.get();
4320 while (src != end) {
4321 *dst++ = static_cast<float>(*src++) / 65536.0f;
4322 }
4323 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
4324 glVertexAttribPointer(
4325 info->index(), info->size(), GL_FLOAT, false, 0,
4326 reinterpret_cast<GLvoid*>(offset));
4327 offset += size;
4328 }
4329 }
4330 *simulated = true;
4331 return true;
4332}
4333
4334void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
4335 // There's no need to call glVertexAttribPointer because we shadow all the
4336 // settings and passing GL_FIXED to it will not work.
4337 glBindBuffer(GL_ARRAY_BUFFER,
4338 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4339}
4340
[email protected]f7a64ee2010-02-01 22:24:144341error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:194342 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:504343 if (!bound_element_array_buffer_ ||
4344 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:294345 SetGLError(GL_INVALID_OPERATION,
4346 "glDrawElements: No element array buffer bound");
4347 return error::kNoError;
4348 }
4349
4350 GLenum mode = c.mode;
4351 GLsizei count = c.count;
4352 GLenum type = c.type;
4353 int32 offset = c.index_offset;
4354 if (count < 0) {
4355 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
4356 return error::kNoError;
4357 }
4358 if (offset < 0) {
4359 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
4360 return error::kNoError;
4361 }
[email protected]9438b012010-06-15 22:55:054362 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:294363 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
4364 return error::kNoError;
4365 }
[email protected]9438b012010-06-15 22:55:054366 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294367 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
4368 return error::kNoError;
4369 }
4370
[email protected]3a03a8f2011-03-19 00:51:274371 if (!CheckFramebufferComplete("glDrawElements")) {
4372 return error::kNoError;
4373 }
4374
[email protected]6c788fb72010-08-26 02:16:314375 if (count == 0) {
4376 return error::kNoError;
4377 }
4378
[email protected]8eee29c2010-04-29 03:38:294379 GLuint max_vertex_accessed;
4380 if (!bound_element_array_buffer_->GetMaxValueForRange(
4381 offset, count, type, &max_vertex_accessed)) {
4382 SetGLError(GL_INVALID_OPERATION,
4383 "glDrawElements: range out of bounds for buffer");
4384 return error::kNoError;
4385 }
4386
4387 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:244388 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]8fbedc02010-11-18 18:43:404389 bool simulated_fixed_attribs = false;
4390 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4391 bool textures_set = SetBlackTextureForNonRenderableTextures();
4392 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
4393 glDrawElements(mode, count, type, indices);
4394 if (textures_set) {
4395 RestoreStateForNonRenderableTextures();
4396 }
4397 if (simulated_fixed_attribs) {
4398 RestoreStateForSimulatedFixedAttribs();
4399 }
[email protected]ba3176a2009-12-16 18:19:464400 }
[email protected]b1122982010-05-17 23:04:244401 if (simulated_attrib_0) {
4402 RestoreStateForSimulatedAttrib0();
4403 }
[email protected]96449d2c2009-11-25 00:01:324404 }
[email protected]f7a64ee2010-02-01 22:24:144405 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324406}
4407
[email protected]269200b12010-11-18 22:53:064408GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:234409 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
4410 GLuint max_vertex_accessed = 0;
4411 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:294412 if (!info) {
[email protected]ae51d192010-04-27 00:48:034413 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294414 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064415 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:234416 } else {
4417 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:034418 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:064419 SetGLError(
4420 GL_INVALID_OPERATION,
4421 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:234422 }
4423 }
4424 return max_vertex_accessed;
4425}
4426
[email protected]96449d2c2009-11-25 00:01:324427// Calls glShaderSource for the various versions of the ShaderSource command.
4428// Assumes that data / data_size points to a piece of memory that is in range
4429// of whatever context it came from (shared memory, immediate memory, bucket
4430// memory.)
[email protected]45bf5152010-02-12 00:11:314431error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034432 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:584433 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4434 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:314435 if (!info) {
[email protected]45bf5152010-02-12 00:11:314436 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324437 }
[email protected]45bf5152010-02-12 00:11:314438 // Note: We don't actually call glShaderSource here. We wait until
4439 // the call to glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524440 info->Update(std::string(data, data + data_size).c_str());
[email protected]f7a64ee2010-02-01 22:24:144441 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324442}
4443
[email protected]f7a64ee2010-02-01 22:24:144444error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:194445 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:324446 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314447 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:324448 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:464449 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144450 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324451 }
[email protected]ae51d192010-04-27 00:48:034452 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:324453}
4454
[email protected]f7a64ee2010-02-01 22:24:144455error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:194456 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:324457 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314458 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:304459 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464460 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144461 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324462 }
[email protected]ae51d192010-04-27 00:48:034463 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:314464}
4465
[email protected]558847a2010-03-24 07:02:544466error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
4467 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:544468 Bucket* bucket = GetBucket(c.data_bucket_id);
4469 if (!bucket || bucket->size() == 0) {
4470 return error::kInvalidArguments;
4471 }
4472 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034473 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:544474 bucket->size() - 1);
4475}
4476
[email protected]ae51d192010-04-27 00:48:034477void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584478 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4479 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:314480 if (!info) {
[email protected]45bf5152010-02-12 00:11:314481 return;
4482 }
[email protected]de17df392010-04-23 21:09:414483 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
4484 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524485 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:344486 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:184487 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:344488 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:454489 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:234490
[email protected]a550584e2010-09-17 18:01:454491 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:344492 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:184493 return;
4494 }
[email protected]a550584e2010-09-17 18:01:454495 shader_src = translator->translated_shader();
[email protected]de17df392010-04-23 21:09:414496 }
[email protected]de17df392010-04-23 21:09:414497
[email protected]ae51d192010-04-27 00:48:034498 glShaderSource(info->service_id(), 1, &shader_src, NULL);
4499 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:414500 GLint status = GL_FALSE;
4501 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
4502 if (status) {
[email protected]f57bb282010-11-12 00:51:344503 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:414504 } else {
[email protected]d9977d42010-09-01 20:27:024505 // We cannot reach here if we are using the shader translator.
4506 // All invalid shaders must be rejected by the translator.
4507 // All translated shaders must compile.
4508 LOG_IF(ERROR, use_shader_translator_)
4509 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:334510 GLint max_len = 0;
4511 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
4512 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:414513 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:334514 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
4515 DCHECK(max_len == 0 || len < max_len);
4516 DCHECK(len ==0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:524517 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:414518 }
[email protected]45bf5152010-02-12 00:11:314519};
4520
[email protected]ddd968b82010-03-02 00:44:294521void GLES2DecoderImpl::DoGetShaderiv(
4522 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:584523 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4524 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:294525 if (!info) {
[email protected]ddd968b82010-03-02 00:44:294526 return;
4527 }
[email protected]8f1ccdac2010-05-19 21:01:484528 switch (pname) {
4529 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524530 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:484531 return;
4532 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:414533 *params = info->IsValid();
4534 return;
[email protected]8f1ccdac2010-05-19 21:01:484535 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524536 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:414537 return;
[email protected]8f1ccdac2010-05-19 21:01:484538 default:
4539 break;
[email protected]ddd968b82010-03-02 00:44:294540 }
[email protected]8f1ccdac2010-05-19 21:01:484541 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:294542}
4543
[email protected]ae51d192010-04-27 00:48:034544error::Error GLES2DecoderImpl::HandleGetShaderSource(
4545 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
4546 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:034547 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4548 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:584549 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4550 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:524551 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:294552 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:294553 return error::kNoError;
4554 }
[email protected]df6cf1ad2011-01-29 01:20:524555 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:034556 return error::kNoError;
4557}
4558
4559error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
4560 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
4561 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:584562 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4563 Bucket* bucket = CreateBucket(bucket_id);
4564 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4565 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524566 if (!info || !info->log_info()) {
4567 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034568 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:314569 }
[email protected]df6cf1ad2011-01-29 01:20:524570 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034571 return error::kNoError;
4572}
4573
4574error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
4575 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
4576 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:584577 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4578 Bucket* bucket = CreateBucket(bucket_id);
4579 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4580 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524581 if (!info || !info->log_info()) {
[email protected]6b8cf1a2010-05-06 16:13:584582 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034583 return error::kNoError;
4584 }
[email protected]df6cf1ad2011-01-29 01:20:524585 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034586 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324587}
4588
[email protected]1958e0e2010-04-22 05:17:154589bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364590 const BufferManager::BufferInfo* info = GetBufferInfo(client_id);
4591 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154592}
4593
4594bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364595 const FramebufferManager::FramebufferInfo* info =
4596 GetFramebufferInfo(client_id);
4597 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154598}
4599
4600bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364601 // IsProgram is true for programs as soon as they are created, until they are
4602 // deleted and no longer in use.
[email protected]ae51d192010-04-27 00:48:034603 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154604}
4605
4606bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364607 const RenderbufferManager::RenderbufferInfo* info =
4608 GetRenderbufferInfo(client_id);
4609 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154610}
4611
4612bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364613 // IsShader is true for shaders as soon as they are created, until they
4614 // are deleted and not attached to any programs.
[email protected]ae51d192010-04-27 00:48:034615 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154616}
4617
4618bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364619 const TextureManager::TextureInfo* info = GetTextureInfo(client_id);
4620 return info && info->IsValid();
[email protected]ae51d192010-04-27 00:48:034621}
4622
4623void GLES2DecoderImpl::DoAttachShader(
4624 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584625 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4626 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034627 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034628 return;
[email protected]1958e0e2010-04-22 05:17:154629 }
[email protected]6b8cf1a2010-05-06 16:13:584630 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4631 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034632 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034633 return;
4634 }
[email protected]ca488e12010-12-13 20:06:144635 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:314636 SetGLError(GL_INVALID_OPERATION,
4637 "glAttachShader: can not attach more than"
4638 " one shader of the same type.");
4639 return;
4640 }
[email protected]ae51d192010-04-27 00:48:034641 glAttachShader(program_info->service_id(), shader_info->service_id());
4642}
4643
4644void GLES2DecoderImpl::DoDetachShader(
4645 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584646 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4647 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034648 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034649 return;
4650 }
[email protected]6b8cf1a2010-05-06 16:13:584651 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4652 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034653 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034654 return;
4655 }
[email protected]9a0ccd42011-03-16 23:58:224656 if (!program_info->DetachShader(shader_manager(), shader_info)) {
4657 SetGLError(GL_INVALID_OPERATION,
4658 "glDetachShader: shader not attached to program");
4659 return;
4660 }
[email protected]ae51d192010-04-27 00:48:034661 glDetachShader(program_info->service_id(), shader_info->service_id());
4662}
4663
4664void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584665 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4666 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:034667 if (!info) {
[email protected]ae51d192010-04-27 00:48:034668 return;
4669 }
[email protected]d685a682011-04-29 16:19:574670 info->Validate();
[email protected]1958e0e2010-04-22 05:17:154671}
4672
[email protected]b1122982010-05-17 23:04:244673void GLES2DecoderImpl::DoGetVertexAttribfv(
4674 GLuint index, GLenum pname, GLfloat* params) {
4675 VertexAttribManager::VertexAttribInfo* info =
4676 vertex_attrib_manager_.GetVertexAttribInfo(index);
4677 if (!info) {
4678 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
4679 return;
4680 }
4681 switch (pname) {
4682 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4683 BufferManager::BufferInfo* buffer = info->buffer();
4684 if (buffer && !buffer->IsDeleted()) {
4685 GLuint client_id;
4686 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4687 *params = static_cast<GLfloat>(client_id);
4688 }
4689 break;
4690 }
4691 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4692 *params = static_cast<GLfloat>(info->enabled());
4693 break;
4694 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4695 *params = static_cast<GLfloat>(info->size());
4696 break;
4697 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4698 *params = static_cast<GLfloat>(info->gl_stride());
4699 break;
4700 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4701 *params = static_cast<GLfloat>(info->type());
4702 break;
4703 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4704 *params = static_cast<GLfloat>(info->normalized());
4705 break;
4706 case GL_CURRENT_VERTEX_ATTRIB:
4707 params[0] = info->value().v[0];
4708 params[1] = info->value().v[1];
4709 params[2] = info->value().v[2];
4710 params[3] = info->value().v[3];
4711 break;
4712 default:
4713 NOTREACHED();
4714 break;
4715 }
4716}
4717
4718void GLES2DecoderImpl::DoGetVertexAttribiv(
4719 GLuint index, GLenum pname, GLint* params) {
4720 VertexAttribManager::VertexAttribInfo* info =
4721 vertex_attrib_manager_.GetVertexAttribInfo(index);
4722 if (!info) {
4723 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
4724 return;
4725 }
4726 switch (pname) {
4727 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4728 BufferManager::BufferInfo* buffer = info->buffer();
4729 if (buffer && !buffer->IsDeleted()) {
4730 GLuint client_id;
4731 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4732 *params = client_id;
4733 }
4734 break;
4735 }
4736 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4737 *params = info->enabled();
4738 break;
4739 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4740 *params = info->size();
4741 break;
4742 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4743 *params = info->gl_stride();
4744 break;
4745 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4746 *params = info->type();
4747 break;
4748 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4749 *params = static_cast<GLint>(info->normalized());
4750 break;
4751 case GL_CURRENT_VERTEX_ATTRIB:
4752 params[0] = static_cast<GLint>(info->value().v[0]);
4753 params[1] = static_cast<GLint>(info->value().v[1]);
4754 params[2] = static_cast<GLint>(info->value().v[2]);
4755 params[3] = static_cast<GLint>(info->value().v[3]);
4756 break;
4757 default:
4758 NOTREACHED();
4759 break;
4760 }
4761}
4762
4763void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
4764 VertexAttribManager::VertexAttribInfo* info =
4765 vertex_attrib_manager_.GetVertexAttribInfo(index);
4766 if (!info) {
4767 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
4768 return;
4769 }
4770 VertexAttribManager::VertexAttribInfo::Vec4 value;
4771 value.v[0] = v0;
4772 value.v[1] = 0.0f;
4773 value.v[2] = 0.0f;
4774 value.v[3] = 1.0f;
4775 info->set_value(value);
4776 glVertexAttrib1f(index, v0);
4777}
4778
4779void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
4780 VertexAttribManager::VertexAttribInfo* info =
4781 vertex_attrib_manager_.GetVertexAttribInfo(index);
4782 if (!info) {
4783 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
4784 return;
4785 }
4786 VertexAttribManager::VertexAttribInfo::Vec4 value;
4787 value.v[0] = v0;
4788 value.v[1] = v1;
4789 value.v[2] = 0.0f;
4790 value.v[3] = 1.0f;
4791 info->set_value(value);
4792 glVertexAttrib2f(index, v0, v1);
4793}
4794
4795void GLES2DecoderImpl::DoVertexAttrib3f(
4796 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
4797 VertexAttribManager::VertexAttribInfo* info =
4798 vertex_attrib_manager_.GetVertexAttribInfo(index);
4799 if (!info) {
4800 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
4801 return;
4802 }
4803 VertexAttribManager::VertexAttribInfo::Vec4 value;
4804 value.v[0] = v0;
4805 value.v[1] = v1;
4806 value.v[2] = v2;
4807 value.v[3] = 1.0f;
4808 info->set_value(value);
4809 glVertexAttrib3f(index, v0, v1, v2);
4810}
4811
4812void GLES2DecoderImpl::DoVertexAttrib4f(
4813 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
4814 VertexAttribManager::VertexAttribInfo* info =
4815 vertex_attrib_manager_.GetVertexAttribInfo(index);
4816 if (!info) {
4817 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
4818 return;
4819 }
4820 VertexAttribManager::VertexAttribInfo::Vec4 value;
4821 value.v[0] = v0;
4822 value.v[1] = v1;
4823 value.v[2] = v2;
4824 value.v[3] = v3;
4825 info->set_value(value);
4826 glVertexAttrib4f(index, v0, v1, v2, v3);
4827}
4828
4829void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
4830 VertexAttribManager::VertexAttribInfo* info =
4831 vertex_attrib_manager_.GetVertexAttribInfo(index);
4832 if (!info) {
4833 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
4834 return;
4835 }
4836 VertexAttribManager::VertexAttribInfo::Vec4 value;
4837 value.v[0] = v[0];
4838 value.v[1] = 0.0f;
4839 value.v[2] = 0.0f;
4840 value.v[3] = 1.0f;
4841 info->set_value(value);
4842 glVertexAttrib1fv(index, v);
4843}
4844
4845void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
4846 VertexAttribManager::VertexAttribInfo* info =
4847 vertex_attrib_manager_.GetVertexAttribInfo(index);
4848 if (!info) {
4849 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
4850 return;
4851 }
4852 VertexAttribManager::VertexAttribInfo::Vec4 value;
4853 value.v[0] = v[0];
4854 value.v[1] = v[1];
4855 value.v[2] = 0.0f;
4856 value.v[3] = 1.0f;
4857 info->set_value(value);
4858 glVertexAttrib2fv(index, v);
4859}
4860
4861void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
4862 VertexAttribManager::VertexAttribInfo* info =
4863 vertex_attrib_manager_.GetVertexAttribInfo(index);
4864 if (!info) {
4865 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
4866 return;
4867 }
4868 VertexAttribManager::VertexAttribInfo::Vec4 value;
4869 value.v[0] = v[0];
4870 value.v[1] = v[1];
4871 value.v[2] = v[2];
4872 value.v[3] = 1.0f;
4873 info->set_value(value);
4874 glVertexAttrib3fv(index, v);
4875}
4876
4877void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
4878 VertexAttribManager::VertexAttribInfo* info =
4879 vertex_attrib_manager_.GetVertexAttribInfo(index);
4880 if (!info) {
4881 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
4882 return;
4883 }
4884 VertexAttribManager::VertexAttribInfo::Vec4 value;
4885 value.v[0] = v[0];
4886 value.v[1] = v[1];
4887 value.v[2] = v[2];
4888 value.v[3] = v[3];
4889 info->set_value(value);
4890 glVertexAttrib4fv(index, v);
4891}
4892
[email protected]f7a64ee2010-02-01 22:24:144893error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:194894 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:294895 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
4896 SetGLError(GL_INVALID_VALUE,
4897 "glVertexAttribPointer: no array buffer bound");
4898 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324899 }
[email protected]8eee29c2010-04-29 03:38:294900
4901 GLuint indx = c.indx;
4902 GLint size = c.size;
4903 GLenum type = c.type;
4904 GLboolean normalized = c.normalized;
4905 GLsizei stride = c.stride;
4906 GLsizei offset = c.offset;
4907 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:054908 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294909 SetGLError(GL_INVALID_ENUM,
4910 "glVertexAttribPointer: type GL_INVALID_ENUM");
4911 return error::kNoError;
4912 }
[email protected]9438b012010-06-15 22:55:054913 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:314914 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:294915 "glVertexAttribPointer: size GL_INVALID_VALUE");
4916 return error::kNoError;
4917 }
4918 if (indx >= group_->max_vertex_attribs()) {
4919 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
4920 return error::kNoError;
4921 }
4922 if (stride < 0) {
4923 SetGLError(GL_INVALID_VALUE,
4924 "glVertexAttribPointer: stride < 0");
4925 return error::kNoError;
4926 }
4927 if (stride > 255) {
4928 SetGLError(GL_INVALID_VALUE,
4929 "glVertexAttribPointer: stride > 255");
4930 return error::kNoError;
4931 }
4932 if (offset < 0) {
4933 SetGLError(GL_INVALID_VALUE,
4934 "glVertexAttribPointer: offset < 0");
4935 return error::kNoError;
4936 }
4937 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:314938 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:294939 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:314940 SetGLError(GL_INVALID_OPERATION,
4941 "glVertexAttribPointer: offset not valid for type");
4942 return error::kNoError;
4943 }
4944 if (stride % component_size > 0) {
4945 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:294946 "glVertexAttribPointer: stride not valid for type");
4947 return error::kNoError;
4948 }
[email protected]8fbedc02010-11-18 18:43:404949 vertex_attrib_manager_.SetAttribInfo(
4950 indx,
[email protected]8eee29c2010-04-29 03:38:294951 bound_array_buffer_,
4952 size,
4953 type,
[email protected]b1122982010-05-17 23:04:244954 normalized,
4955 stride,
4956 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:294957 offset);
[email protected]8fbedc02010-11-18 18:43:404958 if (type != GL_FIXED) {
4959 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
4960 }
[email protected]f7a64ee2010-02-01 22:24:144961 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324962}
4963
[email protected]f7a64ee2010-02-01 22:24:144964error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:194965 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:314966 GLint x = c.x;
4967 GLint y = c.y;
4968 GLsizei width = c.width;
4969 GLsizei height = c.height;
4970 GLenum format = c.format;
4971 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:564972 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:294973 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:564974 return error::kNoError;
4975 }
[email protected]a51788e2010-02-24 21:54:254976 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:184977 uint32 pixels_size;
4978 if (!GLES2Util::ComputeImageDataSize(
4979 width, height, format, type, pack_alignment_, &pixels_size)) {
4980 return error::kOutOfBounds;
4981 }
[email protected]612d2f82009-12-08 20:49:314982 void* pixels = GetSharedMemoryAs<void*>(
4983 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:254984 Result* result = GetSharedMemoryAs<Result*>(
4985 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4986 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:144987 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464988 }
[email protected]a51788e2010-02-24 21:54:254989
[email protected]9438b012010-06-15 22:55:054990 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:294991 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
4992 return error::kNoError;
4993 }
[email protected]9438b012010-06-15 22:55:054994 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294995 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:124996 return error::kNoError;
4997 }
[email protected]57f223832010-03-19 01:57:564998 if (width == 0 || height == 0) {
4999 return error::kNoError;
5000 }
5001
5002 CopyRealGLErrorsToWrapper();
5003
[email protected]c0701082011-04-20 00:34:525004 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]34ff8b0c2010-10-01 20:06:025005
[email protected]57f223832010-03-19 01:57:565006 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:305007 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:565008
5009 GLint max_x;
5010 GLint max_y;
5011 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:295012 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:145013 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:315014 }
[email protected]57f223832010-03-19 01:57:565015
[email protected]d37231fa2010-04-09 21:16:025016 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:565017 // The user requested an out of range area. Get the results 1 line
5018 // at a time.
5019 uint32 temp_size;
5020 if (!GLES2Util::ComputeImageDataSize(
5021 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295022 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565023 return error::kNoError;
5024 }
5025 GLsizei unpadded_row_size = temp_size;
5026 if (!GLES2Util::ComputeImageDataSize(
5027 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295028 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565029 return error::kNoError;
5030 }
5031 GLsizei padded_row_size = temp_size - unpadded_row_size;
5032 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:295033 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565034 return error::kNoError;
5035 }
5036
5037 GLint dest_x_offset = std::max(-x, 0);
5038 uint32 dest_row_offset;
5039 if (!GLES2Util::ComputeImageDataSize(
5040 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:295041 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565042 return error::kNoError;
5043 }
5044
5045 // Copy each row into the larger dest rect.
5046 int8* dst = static_cast<int8*>(pixels);
5047 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:025048 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:565049 GLint read_width = read_end_x - read_x;
5050 for (GLint yy = 0; yy < height; ++yy) {
5051 GLint ry = y + yy;
5052
5053 // Clear the row.
5054 memset(dst, 0, unpadded_row_size);
5055
5056 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025057 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565058 glReadPixels(
5059 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5060 }
5061 dst += padded_row_size;
5062 }
5063 } else {
5064 glReadPixels(x, y, width, height, format, type, pixels);
5065 }
[email protected]a51788e2010-02-24 21:54:255066 GLenum error = glGetError();
5067 if (error == GL_NO_ERROR) {
5068 *result = true;
[email protected]4848b9f82011-03-10 18:37:565069
5070 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5071 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5072 if ((channels_exist & 0x0008) == 0) {
5073 // Set the alpha to 255 because some drivers are buggy in this regard.
5074 uint32 temp_size;
5075 if (!GLES2Util::ComputeImageDataSize(
5076 width, 1, format, type, pack_alignment_, &temp_size)) {
5077 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5078 return error::kNoError;
5079 }
5080 GLsizei unpadded_row_size = temp_size;
5081 if (!GLES2Util::ComputeImageDataSize(
5082 width, 2, format, type, pack_alignment_, &temp_size)) {
5083 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5084 return error::kNoError;
5085 }
5086 GLsizei padded_row_size = temp_size - unpadded_row_size;
5087 if (padded_row_size < 0 || unpadded_row_size < 0) {
5088 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5089 return error::kNoError;
5090 }
5091 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5092 // of this implementation.
5093 if (type != GL_UNSIGNED_BYTE) {
5094 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5095 return error::kNoError;
5096 }
5097 switch (format) {
5098 case GL_RGBA:
5099 case GL_ALPHA: {
5100 int offset = (format == GL_ALPHA) ? 0 : 3;
5101 int step = (format == GL_ALPHA) ? 1 : 4;
5102 uint8* dst = static_cast<uint8*>(pixels) + offset;
5103 for (GLint yy = 0; yy < height; ++yy) {
5104 uint8* end = dst + unpadded_row_size;
5105 for (uint8* d = dst; d < end; d += step) {
5106 *d = 255;
5107 }
5108 dst += padded_row_size;
5109 }
5110 break;
5111 }
5112 default:
5113 break;
5114 }
5115 }
[email protected]a51788e2010-02-24 21:54:255116 } else {
[email protected]8eee29c2010-04-29 03:38:295117 SetGLError(error, NULL);
[email protected]a51788e2010-02-24 21:54:255118 }
[email protected]4848b9f82011-03-10 18:37:565119
[email protected]f7a64ee2010-02-01 22:24:145120 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325121}
5122
[email protected]f7a64ee2010-02-01 22:24:145123error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195124 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5125 GLenum pname = c.pname;
5126 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055127 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295128 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125129 return error::kNoError;
5130 }
[email protected]9438b012010-06-15 22:55:055131 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:295132 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:145133 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195134 }
5135 glPixelStorei(pname, param);
5136 switch (pname) {
5137 case GL_PACK_ALIGNMENT:
5138 pack_alignment_ = param;
5139 break;
5140 case GL_UNPACK_ALIGNMENT:
5141 unpack_alignment_ = param;
5142 break;
5143 default:
5144 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:375145 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:195146 break;
5147 }
[email protected]f7a64ee2010-02-01 22:24:145148 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195149}
5150
[email protected]558847a2010-03-24 07:02:545151error::Error GLES2DecoderImpl::GetAttribLocationHelper(
5152 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5153 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585154 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5155 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:035156 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145157 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195158 }
[email protected]ae51d192010-04-27 00:48:035159 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295160 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255161 return error::kNoError;
5162 }
[email protected]b9849abf2009-11-25 19:13:195163 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545164 location_shm_id, location_shm_offset, sizeof(GLint));
5165 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145166 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195167 }
[email protected]558847a2010-03-24 07:02:545168 // Require the client to init this incase the context is lost and we are no
5169 // longer executing commands.
5170 if (*location != -1) {
5171 return error::kGenericError;
5172 }
[email protected]0bfd9882010-02-05 23:02:255173 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145174 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195175}
5176
[email protected]558847a2010-03-24 07:02:545177error::Error GLES2DecoderImpl::HandleGetAttribLocation(
5178 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
5179 uint32 name_size = c.data_size;
5180 const char* name = GetSharedMemoryAs<const char*>(
5181 c.name_shm_id, c.name_shm_offset, name_size);
5182 if (!name) {
5183 return error::kOutOfBounds;
5184 }
5185 String name_str(name, name_size);
5186 return GetAttribLocationHelper(
5187 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5188}
5189
[email protected]f7a64ee2010-02-01 22:24:145190error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195191 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:545192 uint32 name_size = c.data_size;
5193 const char* name = GetImmediateDataAs<const char*>(
5194 c, name_size, immediate_data_size);
5195 if (!name) {
5196 return error::kOutOfBounds;
5197 }
5198 String name_str(name, name_size);
5199 return GetAttribLocationHelper(
5200 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5201}
5202
5203error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
5204 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
5205 Bucket* bucket = GetBucket(c.name_bucket_id);
5206 if (!bucket) {
5207 return error::kInvalidArguments;
5208 }
5209 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185210 if (!bucket->GetAsString(&name_str)) {
5211 return error::kInvalidArguments;
5212 }
[email protected]558847a2010-03-24 07:02:545213 return GetAttribLocationHelper(
5214 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5215}
5216
5217error::Error GLES2DecoderImpl::GetUniformLocationHelper(
5218 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5219 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585220 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5221 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:035222 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145223 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195224 }
[email protected]ae51d192010-04-27 00:48:035225 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295226 SetGLError(GL_INVALID_OPERATION,
5227 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255228 return error::kNoError;
5229 }
[email protected]b9849abf2009-11-25 19:13:195230 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545231 location_shm_id, location_shm_offset, sizeof(GLint));
5232 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145233 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195234 }
[email protected]558847a2010-03-24 07:02:545235 // Require the client to init this incase the context is lost an we are no
5236 // longer executing commands.
5237 if (*location != -1) {
5238 return error::kGenericError;
5239 }
5240 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145241 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195242}
5243
[email protected]f7a64ee2010-02-01 22:24:145244error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:195245 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:195246 uint32 name_size = c.data_size;
5247 const char* name = GetSharedMemoryAs<const char*>(
5248 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:545249 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145250 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195251 }
5252 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545253 return GetUniformLocationHelper(
5254 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195255}
5256
[email protected]f7a64ee2010-02-01 22:24:145257error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195258 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:195259 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:305260 const char* name = GetImmediateDataAs<const char*>(
5261 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:545262 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145263 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195264 }
5265 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545266 return GetUniformLocationHelper(
5267 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5268}
5269
5270error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
5271 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
5272 Bucket* bucket = GetBucket(c.name_bucket_id);
5273 if (!bucket) {
5274 return error::kInvalidArguments;
5275 }
5276 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185277 if (!bucket->GetAsString(&name_str)) {
5278 return error::kInvalidArguments;
5279 }
[email protected]558847a2010-03-24 07:02:545280 return GetUniformLocationHelper(
5281 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195282}
5283
[email protected]ddd968b82010-03-02 00:44:295284error::Error GLES2DecoderImpl::HandleGetString(
5285 uint32 immediate_data_size, const gles2::GetString& c) {
5286 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:055287 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:295288 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:295289 return error::kNoError;
5290 }
[email protected]1958e0e2010-04-22 05:17:155291 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
5292 const char* str = NULL;
5293 switch (name) {
5294 case GL_VERSION:
5295 str = "OpenGL ES 2.0 Chromium";
5296 break;
5297 case GL_SHADING_LANGUAGE_VERSION:
5298 str = "OpenGL ES GLSL ES 1.0 Chromium";
5299 break;
5300 case GL_EXTENSIONS:
[email protected]915a59a12010-09-30 21:29:115301 str = feature_info_->extensions().c_str();
[email protected]1958e0e2010-04-22 05:17:155302 break;
5303 default:
5304 str = gl_str;
5305 break;
5306 }
[email protected]ddd968b82010-03-02 00:44:295307 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:155308 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:295309 return error::kNoError;
5310}
5311
[email protected]0c86dbf2010-03-05 08:14:115312void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:155313 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:055314 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295315 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
5316 return;
5317 }
[email protected]9438b012010-06-15 22:55:055318 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:295319 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:115320 return;
[email protected]3b6ec202010-03-05 05:16:235321 }
5322 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:295323 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:285324 return;
[email protected]3b6ec202010-03-05 05:16:235325 }
5326 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
5327 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295328 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285329 return;
[email protected]3b6ec202010-03-05 05:16:235330 }
5331 // Clear the buffer to 0 if no initial data was passed in.
5332 scoped_array<int8> zero;
5333 if (!data) {
5334 zero.reset(new int8[size]);
5335 memset(zero.get(), 0, size);
5336 data = zero.get();
5337 }
5338 CopyRealGLErrorsToWrapper();
5339 glBufferData(target, size, data, usage);
5340 GLenum error = glGetError();
5341 if (error != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:295342 SetGLError(error, NULL);
[email protected]3b6ec202010-03-05 05:16:235343 } else {
[email protected]4e8a5b122010-05-08 22:00:105344 buffer_manager()->SetSize(info, size);
[email protected]0c86dbf2010-03-05 08:14:115345 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:235346 }
[email protected]0c86dbf2010-03-05 08:14:115347}
5348
5349error::Error GLES2DecoderImpl::HandleBufferData(
5350 uint32 immediate_data_size, const gles2::BufferData& c) {
5351 GLenum target = static_cast<GLenum>(c.target);
5352 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
5353 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5354 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5355 GLenum usage = static_cast<GLenum>(c.usage);
5356 const void* data = NULL;
5357 if (data_shm_id != 0 || data_shm_offset != 0) {
5358 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
5359 if (!data) {
5360 return error::kOutOfBounds;
5361 }
5362 }
5363 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:145364 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195365}
5366
[email protected]f7a64ee2010-02-01 22:24:145367error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:195368 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
5369 GLenum target = static_cast<GLenum>(c.target);
5370 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:305371 const void* data = GetImmediateDataAs<const void*>(
5372 c, size, immediate_data_size);
5373 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145374 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:305375 }
[email protected]b9849abf2009-11-25 19:13:195376 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:115377 DoBufferData(target, size, data, usage);
5378 return error::kNoError;
5379}
5380
5381void GLES2DecoderImpl::DoBufferSubData(
5382 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:505383 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475384 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295385 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285386 return;
[email protected]a93bb842010-02-16 23:03:475387 }
[email protected]0c86dbf2010-03-05 08:14:115388 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:295389 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]07f54fcc2009-12-22 02:46:305390 } else {
[email protected]0c86dbf2010-03-05 08:14:115391 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:305392 }
[email protected]b9849abf2009-11-25 19:13:195393}
5394
[email protected]a93bb842010-02-16 23:03:475395error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
5396 GLenum target,
5397 GLint level,
5398 GLenum internal_format,
5399 GLsizei width,
5400 GLsizei height,
5401 GLint border,
5402 GLsizei image_size,
5403 const void* data) {
[email protected]a93bb842010-02-16 23:03:475404 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:055405 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295406 SetGLError(GL_INVALID_ENUM,
5407 "glCompressedTexImage2D: target GL_INVALID_ENUM");
5408 return error::kNoError;
5409 }
[email protected]9438b012010-06-15 22:55:055410 if (!validators_->compressed_texture_format.IsValid(
5411 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295412 SetGLError(GL_INVALID_ENUM,
5413 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:475414 return error::kNoError;
5415 }
[email protected]915a59a12010-09-30 21:29:115416 if (!texture_manager()->ValidForTarget(
5417 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475418 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295419 SetGLError(GL_INVALID_VALUE,
5420 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475421 return error::kNoError;
5422 }
[email protected]3916c97e2010-02-25 03:20:505423 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475424 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295425 SetGLError(GL_INVALID_VALUE,
5426 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:475427 return error::kNoError;
5428 }
5429 scoped_array<int8> zero;
5430 if (!data) {
5431 zero.reset(new int8[image_size]);
5432 memset(zero.get(), 0, image_size);
5433 data = zero.get();
5434 }
[email protected]cadde4a2010-07-31 17:10:435435 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475436 glCompressedTexImage2D(
5437 target, level, internal_format, width, height, border, image_size, data);
[email protected]cadde4a2010-07-31 17:10:435438 GLenum error = glGetError();
5439 if (error == GL_NO_ERROR) {
5440 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115441 feature_info_,
[email protected]cadde4a2010-07-31 17:10:435442 info, target, level, internal_format, width, height, 1, border, 0, 0);
5443 }
[email protected]a93bb842010-02-16 23:03:475444 return error::kNoError;
5445}
5446
[email protected]f7a64ee2010-02-01 22:24:145447error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195448 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
5449 GLenum target = static_cast<GLenum>(c.target);
5450 GLint level = static_cast<GLint>(c.level);
5451 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5452 GLsizei width = static_cast<GLsizei>(c.width);
5453 GLsizei height = static_cast<GLsizei>(c.height);
5454 GLint border = static_cast<GLint>(c.border);
5455 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
5456 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5457 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5458 const void* data = NULL;
5459 if (data_shm_id != 0 || data_shm_offset != 0) {
5460 data = GetSharedMemoryAs<const void*>(
5461 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:465462 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145463 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195464 }
5465 }
[email protected]a93bb842010-02-16 23:03:475466 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195467 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:195468}
5469
[email protected]f7a64ee2010-02-01 22:24:145470error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195471 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
5472 GLenum target = static_cast<GLenum>(c.target);
5473 GLint level = static_cast<GLint>(c.level);
5474 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5475 GLsizei width = static_cast<GLsizei>(c.width);
5476 GLsizei height = static_cast<GLsizei>(c.height);
5477 GLint border = static_cast<GLint>(c.border);
5478 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:305479 const void* data = GetImmediateDataAs<const void*>(
5480 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465481 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145482 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465483 }
[email protected]a93bb842010-02-16 23:03:475484 return DoCompressedTexImage2D(
5485 target, level, internal_format, width, height, border, image_size, data);
5486}
5487
[email protected]b6140d02010-05-17 14:47:165488error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
5489 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
5490 GLenum target = static_cast<GLenum>(c.target);
5491 GLint level = static_cast<GLint>(c.level);
5492 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5493 GLsizei width = static_cast<GLsizei>(c.width);
5494 GLsizei height = static_cast<GLsizei>(c.height);
5495 GLint border = static_cast<GLint>(c.border);
5496 Bucket* bucket = GetBucket(c.bucket_id);
5497 return DoCompressedTexImage2D(
5498 target, level, internal_format, width, height, border,
5499 bucket->size(), bucket->GetData(0, bucket->size()));
5500}
5501
5502error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
5503 uint32 immediate_data_size,
5504 const gles2::CompressedTexSubImage2DBucket& c) {
5505 GLenum target = static_cast<GLenum>(c.target);
5506 GLint level = static_cast<GLint>(c.level);
5507 GLint xoffset = static_cast<GLint>(c.xoffset);
5508 GLint yoffset = static_cast<GLint>(c.yoffset);
5509 GLsizei width = static_cast<GLsizei>(c.width);
5510 GLsizei height = static_cast<GLsizei>(c.height);
5511 GLenum format = static_cast<GLenum>(c.format);
5512 Bucket* bucket = GetBucket(c.bucket_id);
5513 uint32 data_size = bucket->size();
5514 GLsizei imageSize = data_size;
5515 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:055516 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:165517 SetGLError(
5518 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
5519 return error::kNoError;
5520 }
[email protected]9438b012010-06-15 22:55:055521 if (!validators_->compressed_texture_format.IsValid(format)) {
5522 SetGLError(GL_INVALID_ENUM,
5523 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
5524 return error::kNoError;
5525 }
[email protected]b6140d02010-05-17 14:47:165526 if (width < 0) {
5527 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
5528 return error::kNoError;
5529 }
5530 if (height < 0) {
5531 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
5532 return error::kNoError;
5533 }
5534 if (imageSize < 0) {
5535 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
5536 return error::kNoError;
5537 }
[email protected]cadde4a2010-07-31 17:10:435538 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:165539 target, level, xoffset, yoffset, width, height, format, imageSize, data);
5540 return error::kNoError;
5541}
5542
[email protected]a93bb842010-02-16 23:03:475543error::Error GLES2DecoderImpl::DoTexImage2D(
5544 GLenum target,
5545 GLint level,
5546 GLenum internal_format,
5547 GLsizei width,
5548 GLsizei height,
5549 GLint border,
5550 GLenum format,
5551 GLenum type,
5552 const void* pixels,
5553 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:055554 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295555 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
5556 return error::kNoError;
5557 }
[email protected]9438b012010-06-15 22:55:055558 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295559 SetGLError(GL_INVALID_ENUM,
5560 "glTexImage2D: internal_format GL_INVALID_ENUM");
5561 return error::kNoError;
5562 }
[email protected]9438b012010-06-15 22:55:055563 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295564 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
5565 return error::kNoError;
5566 }
[email protected]9438b012010-06-15 22:55:055567 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295568 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145569 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195570 }
[email protected]7b92c412010-07-20 17:48:255571 if (format != internal_format) {
5572 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
5573 return error::kNoError;
5574 }
[email protected]915a59a12010-09-30 21:29:115575 if (!texture_manager()->ValidForTarget(
5576 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475577 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295578 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475579 return error::kNoError;
5580 }
[email protected]3916c97e2010-02-25 03:20:505581 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475582 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295583 SetGLError(GL_INVALID_OPERATION,
5584 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:475585 return error::kNoError;
5586 }
5587 scoped_array<int8> zero;
5588 if (!pixels) {
5589 zero.reset(new int8[pixels_size]);
5590 memset(zero.get(), 0, pixels_size);
5591 pixels = zero.get();
5592 }
[email protected]876f6fee2010-08-02 23:10:325593
[email protected]f5719fb2010-08-04 18:27:185594 GLenum gl_internal_format = internal_format;
[email protected]876f6fee2010-08-02 23:10:325595 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
5596 if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
[email protected]f5719fb2010-08-04 18:27:185597 gl_internal_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:325598 } else if (type == GL_FLOAT) {
5599 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:185600 gl_internal_format = GL_RGBA32F_ARB;
[email protected]876f6fee2010-08-02 23:10:325601 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:185602 gl_internal_format = GL_RGB32F_ARB;
[email protected]876f6fee2010-08-02 23:10:325603 }
5604 } else if (type == GL_HALF_FLOAT_OES) {
5605 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:185606 gl_internal_format = GL_RGBA16F_ARB;
[email protected]876f6fee2010-08-02 23:10:325607 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:185608 gl_internal_format = GL_RGB16F_ARB;
[email protected]876f6fee2010-08-02 23:10:325609 }
[email protected]7b92c412010-07-20 17:48:255610 }
[email protected]7488d962010-07-16 02:41:585611 }
[email protected]876f6fee2010-08-02 23:10:325612
[email protected]cadde4a2010-07-31 17:10:435613 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475614 glTexImage2D(
[email protected]f5719fb2010-08-04 18:27:185615 target, level, gl_internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475616 pixels);
[email protected]cadde4a2010-07-31 17:10:435617 GLenum error = glGetError();
5618 if (error == GL_NO_ERROR) {
[email protected]915a59a12010-09-30 21:29:115619 texture_manager()->SetLevelInfo(feature_info_, info,
[email protected]cadde4a2010-07-31 17:10:435620 target, level, internal_format, width, height, 1, border, format, type);
[email protected]b493ee622011-04-13 23:52:005621 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:435622 }
[email protected]f7a64ee2010-02-01 22:24:145623 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195624}
5625
[email protected]f7a64ee2010-02-01 22:24:145626error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195627 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:585628 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:005629 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:195630 GLenum target = static_cast<GLenum>(c.target);
5631 GLint level = static_cast<GLint>(c.level);
5632 GLint internal_format = static_cast<GLint>(c.internalformat);
5633 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);
5638 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
5639 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:185640 uint32 pixels_size;
5641 if (!GLES2Util::ComputeImageDataSize(
5642 width, height, format, type, unpack_alignment_, &pixels_size)) {
5643 return error::kOutOfBounds;
5644 }
[email protected]b9849abf2009-11-25 19:13:195645 const void* pixels = NULL;
5646 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
5647 pixels = GetSharedMemoryAs<const void*>(
5648 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:465649 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145650 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195651 }
5652 }
[email protected]a93bb842010-02-16 23:03:475653 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195654 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475655 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:195656}
5657
[email protected]f7a64ee2010-02-01 22:24:145658error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195659 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
5660 GLenum target = static_cast<GLenum>(c.target);
5661 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:465662 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:195663 GLsizei width = static_cast<GLsizei>(c.width);
5664 GLsizei height = static_cast<GLsizei>(c.height);
5665 GLint border = static_cast<GLint>(c.border);
5666 GLenum format = static_cast<GLenum>(c.format);
5667 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:185668 uint32 size;
5669 if (!GLES2Util::ComputeImageDataSize(
5670 width, height, format, type, unpack_alignment_, &size)) {
5671 return error::kOutOfBounds;
5672 }
[email protected]07f54fcc2009-12-22 02:46:305673 const void* pixels = GetImmediateDataAs<const void*>(
5674 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465675 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145676 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465677 }
[email protected]a93bb842010-02-16 23:03:475678 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:465679 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475680 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:145681 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325682}
5683
[email protected]cadde4a2010-07-31 17:10:435684void GLES2DecoderImpl::DoCompressedTexSubImage2D(
5685 GLenum target,
5686 GLint level,
5687 GLint xoffset,
5688 GLint yoffset,
5689 GLsizei width,
5690 GLsizei height,
5691 GLenum format,
5692 GLsizei image_size,
5693 const void * data) {
5694 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5695 if (!info) {
5696 SetGLError(GL_INVALID_OPERATION,
5697 "glCompressedTexSubImage2D: unknown texture for target");
5698 return;
5699 }
5700 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:525701 GLenum internal_format = 0;
5702 if (!info->GetLevelType(target, level, &type, &internal_format)) {
5703 SetGLError(
5704 GL_INVALID_OPERATION,
5705 "glCompressdTexSubImage2D: level does not exist.");
5706 return;
5707 }
5708 if (internal_format != format) {
5709 SetGLError(
5710 GL_INVALID_OPERATION,
5711 "glCompressdTexSubImage2D: format does not match internal format.");
5712 return;
5713 }
5714 if (!info->ValidForTexture(
5715 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:435716 SetGLError(GL_INVALID_VALUE,
5717 "glCompressdTexSubImage2D: bad dimensions.");
5718 return;
5719 }
5720 glCompressedTexSubImage2D(
5721 target, level, xoffset, yoffset, width, height, format, image_size, data);
5722}
5723
[email protected]6e288612010-12-21 20:45:035724static void Clip(
5725 GLint start, GLint range, GLint sourceRange,
5726 GLint* out_start, GLint* out_range) {
5727 DCHECK(out_start);
5728 DCHECK(out_range);
5729 if (start < 0) {
5730 range += start;
5731 start = 0;
5732 }
5733 GLint end = start + range;
5734 if (end > sourceRange) {
5735 range -= end - sourceRange;
5736 }
5737 *out_start = start;
5738 *out_range = range;
5739}
5740
5741
[email protected]cadde4a2010-07-31 17:10:435742void GLES2DecoderImpl::DoCopyTexImage2D(
5743 GLenum target,
5744 GLint level,
5745 GLenum internal_format,
5746 GLint x,
5747 GLint y,
5748 GLsizei width,
5749 GLsizei height,
5750 GLint border) {
5751 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5752 if (!info) {
5753 SetGLError(GL_INVALID_OPERATION,
5754 "glCopyTexImage2D: unknown texture for target");
5755 return;
5756 }
[email protected]915a59a12010-09-30 21:29:115757 if (!texture_manager()->ValidForTarget(
5758 feature_info_, target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:185759 border != 0) {
5760 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
5761 return;
5762 }
5763
[email protected]9edc6b22010-12-23 02:00:265764 // Check we have compatible formats.
5765 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5766 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5767 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
5768
5769 if ((channels_needed & channels_exist) != channels_needed) {
5770 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
5771 return;
5772 }
5773
[email protected]cadde4a2010-07-31 17:10:435774 CopyRealGLErrorsToWrapper();
[email protected]c0701082011-04-20 00:34:525775 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]6e288612010-12-21 20:45:035776 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:265777
5778 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:035779 GLint copyX = 0;
5780 GLint copyY = 0;
5781 GLint copyWidth = 0;
5782 GLint copyHeight = 0;
5783 Clip(x, width, size.width(), &copyX, &copyWidth);
5784 Clip(y, height, size.height(), &copyY, &copyHeight);
5785
5786 if (copyX != x ||
5787 copyY != y ||
5788 copyWidth != width ||
5789 copyHeight != height) {
5790 // some part was clipped so clear the texture.
5791 uint32 pixels_size = 0;
5792 if (!GLES2Util::ComputeImageDataSize(
5793 width, height, internal_format, GL_UNSIGNED_BYTE,
5794 unpack_alignment_, &pixels_size)) {
5795 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions too large");
5796 return;
5797 }
5798 scoped_array<char> zero(new char[pixels_size]);
5799 memset(zero.get(), 0, pixels_size);
5800 glTexImage2D(target, level, internal_format, width, height, 0,
5801 internal_format, GL_UNSIGNED_BYTE, zero.get());
5802 if (copyHeight > 0 && copyWidth > 0) {
5803 GLint dx = copyX - x;
5804 GLint dy = copyY - y;
5805 GLint destX = dx;
5806 GLint destY = dy;
5807 glCopyTexSubImage2D(target, level,
5808 destX, destY, copyX, copyY,
5809 copyWidth, copyHeight);
5810 }
5811 } else {
5812 glCopyTexImage2D(target, level, internal_format,
5813 copyX, copyY, copyWidth, copyHeight, border);
5814 }
[email protected]cadde4a2010-07-31 17:10:435815 GLenum error = glGetError();
5816 if (error == GL_NO_ERROR) {
5817 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115818 feature_info_, info, target, level, internal_format, width, height, 1,
5819 border, internal_format, GL_UNSIGNED_BYTE);
[email protected]cadde4a2010-07-31 17:10:435820 }
5821}
5822
5823void GLES2DecoderImpl::DoCopyTexSubImage2D(
5824 GLenum target,
5825 GLint level,
5826 GLint xoffset,
5827 GLint yoffset,
5828 GLint x,
5829 GLint y,
5830 GLsizei width,
5831 GLsizei height) {
5832 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5833 if (!info) {
5834 SetGLError(GL_INVALID_OPERATION,
5835 "glCopyTexSubImage2D: unknown texture for target");
5836 return;
5837 }
5838 GLenum type = 0;
5839 GLenum format = 0;
5840 if (!info->GetLevelType(target, level, &type, &format) ||
5841 !info->ValidForTexture(
5842 target, level, xoffset, yoffset, width, height, format, type)) {
5843 SetGLError(GL_INVALID_VALUE,
5844 "glCopyTexSubImage2D: bad dimensions.");
5845 return;
5846 }
[email protected]9edc6b22010-12-23 02:00:265847
5848 // Check we have compatible formats.
5849 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5850 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5851 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
5852
5853 if ((channels_needed & channels_exist) != channels_needed) {
5854 SetGLError(
5855 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
5856 return;
5857 }
5858
[email protected]c0701082011-04-20 00:34:525859 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]6e288612010-12-21 20:45:035860 gfx::Size size = GetBoundReadFrameBufferSize();
5861 GLint copyX = 0;
5862 GLint copyY = 0;
5863 GLint copyWidth = 0;
5864 GLint copyHeight = 0;
5865 Clip(x, width, size.width(), &copyX, &copyWidth);
5866 Clip(y, height, size.height(), &copyY, &copyHeight);
5867 if (copyX != x ||
5868 copyY != y ||
5869 copyWidth != width ||
5870 copyHeight != height) {
5871 // some part was clipped so clear the texture.
5872 uint32 pixels_size = 0;
5873 if (!GLES2Util::ComputeImageDataSize(
5874 width, height, format, type, unpack_alignment_, &pixels_size)) {
5875 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
5876 return;
5877 }
5878 scoped_array<char> zero(new char[pixels_size]);
5879 memset(zero.get(), 0, pixels_size);
5880 glTexSubImage2D(
5881 target, level, xoffset, yoffset, width, height,
5882 format, type, zero.get());
5883 }
5884 if (copyHeight > 0 && copyWidth > 0) {
5885 GLint dx = copyX - x;
5886 GLint dy = copyY - y;
5887 GLint destX = xoffset + dx;
5888 GLint destY = yoffset + dy;
5889 glCopyTexSubImage2D(target, level,
5890 destX, destY, copyX, copyY,
5891 copyWidth, copyHeight);
5892 }
[email protected]cadde4a2010-07-31 17:10:435893}
5894
5895void GLES2DecoderImpl::DoTexSubImage2D(
5896 GLenum target,
5897 GLint level,
5898 GLint xoffset,
5899 GLint yoffset,
5900 GLsizei width,
5901 GLsizei height,
5902 GLenum format,
5903 GLenum type,
5904 const void * data) {
5905 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5906 if (!info) {
5907 SetGLError(GL_INVALID_OPERATION,
5908 "glTexSubImage2D: unknown texture for target");
5909 return;
5910 }
[email protected]df6cf1ad2011-01-29 01:20:525911 GLenum current_type = 0;
5912 GLenum internal_format = 0;
5913 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
5914 SetGLError(
5915 GL_INVALID_OPERATION,
5916 "glTexSubImage2D: level does not exist.");
5917 return;
5918 }
5919 if (format != internal_format) {
5920 SetGLError(GL_INVALID_OPERATION,
5921 "glTexSubImage2D: format does not match internal format.");
5922 return;
5923 }
5924 if (type != current_type) {
5925 SetGLError(GL_INVALID_OPERATION,
5926 "glTexSubImage2D: type does not match type of texture.");
5927 return;
5928 }
5929
[email protected]cadde4a2010-07-31 17:10:435930 if (!info->ValidForTexture(
5931 target, level, xoffset, yoffset, width, height, format, type)) {
5932 SetGLError(GL_INVALID_VALUE,
5933 "glTexSubImage2D: bad dimensions.");
5934 return;
5935 }
5936 glTexSubImage2D(
5937 target, level, xoffset, yoffset, width, height, format, type, data);
5938}
5939
[email protected]b493ee622011-04-13 23:52:005940error::Error GLES2DecoderImpl::HandleTexSubImage2D(
5941 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:585942 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:005943 GLboolean internal = static_cast<GLboolean>(c.internal);
5944 if (internal == GL_TRUE && tex_image_2d_failed_)
5945 return error::kNoError;
5946
5947 GLenum target = static_cast<GLenum>(c.target);
5948 GLint level = static_cast<GLint>(c.level);
5949 GLint xoffset = static_cast<GLint>(c.xoffset);
5950 GLint yoffset = static_cast<GLint>(c.yoffset);
5951 GLsizei width = static_cast<GLsizei>(c.width);
5952 GLsizei height = static_cast<GLsizei>(c.height);
5953 GLenum format = static_cast<GLenum>(c.format);
5954 GLenum type = static_cast<GLenum>(c.type);
5955 uint32 data_size;
5956 if (!GLES2Util::ComputeImageDataSize(
5957 width, height, format, type, unpack_alignment_, &data_size)) {
5958 return error::kOutOfBounds;
5959 }
5960 const void* pixels = GetSharedMemoryAs<const void*>(
5961 c.pixels_shm_id, c.pixels_shm_offset, data_size);
5962 if (!validators_->texture_target.IsValid(target)) {
5963 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
5964 return error::kNoError;
5965 }
5966 if (width < 0) {
5967 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
5968 return error::kNoError;
5969 }
5970 if (height < 0) {
5971 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
5972 return error::kNoError;
5973 }
5974 if (!validators_->texture_format.IsValid(format)) {
5975 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
5976 return error::kNoError;
5977 }
5978 if (!validators_->pixel_type.IsValid(type)) {
5979 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
5980 return error::kNoError;
5981 }
5982 if (pixels == NULL) {
5983 return error::kOutOfBounds;
5984 }
5985 DoTexSubImage2D(
5986 target, level, xoffset, yoffset, width, height, format, type, pixels);
5987 return error::kNoError;
5988}
5989
5990error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
5991 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
5992 GLboolean internal = static_cast<GLboolean>(c.internal);
5993 if (internal == GL_TRUE && tex_image_2d_failed_)
5994 return error::kNoError;
5995
5996 GLenum target = static_cast<GLenum>(c.target);
5997 GLint level = static_cast<GLint>(c.level);
5998 GLint xoffset = static_cast<GLint>(c.xoffset);
5999 GLint yoffset = static_cast<GLint>(c.yoffset);
6000 GLsizei width = static_cast<GLsizei>(c.width);
6001 GLsizei height = static_cast<GLsizei>(c.height);
6002 GLenum format = static_cast<GLenum>(c.format);
6003 GLenum type = static_cast<GLenum>(c.type);
6004 uint32 data_size;
6005 if (!GLES2Util::ComputeImageDataSize(
6006 width, height, format, type, unpack_alignment_, &data_size)) {
6007 return error::kOutOfBounds;
6008 }
6009 const void* pixels = GetImmediateDataAs<const void*>(
6010 c, data_size, immediate_data_size);
6011 if (!validators_->texture_target.IsValid(target)) {
6012 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6013 return error::kNoError;
6014 }
6015 if (width < 0) {
6016 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6017 return error::kNoError;
6018 }
6019 if (height < 0) {
6020 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6021 return error::kNoError;
6022 }
6023 if (!validators_->texture_format.IsValid(format)) {
6024 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6025 return error::kNoError;
6026 }
6027 if (!validators_->pixel_type.IsValid(type)) {
6028 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6029 return error::kNoError;
6030 }
6031 if (pixels == NULL) {
6032 return error::kOutOfBounds;
6033 }
6034 DoTexSubImage2D(
6035 target, level, xoffset, yoffset, width, height, format, type, pixels);
6036 return error::kNoError;
6037}
6038
[email protected]f7a64ee2010-02-01 22:24:146039error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:196040 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:366041 GLuint index = static_cast<GLuint>(c.index);
6042 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:256043 typedef gles2::GetVertexAttribPointerv::Result Result;
6044 Result* result = GetSharedMemoryAs<Result*>(
6045 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:366046 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:146047 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:366048 }
[email protected]07d0cc82010-02-17 04:51:406049 // Check that the client initialized the result.
6050 if (result->size != 0) {
6051 return error::kInvalidArguments;
6052 }
[email protected]9438b012010-06-15 22:55:056053 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296054 SetGLError(GL_INVALID_ENUM,
6055 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146056 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366057 }
[email protected]3916c97e2010-02-25 03:20:506058 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:296059 SetGLError(GL_INVALID_VALUE,
6060 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:146061 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366062 }
[email protected]0bfd9882010-02-05 23:02:256063 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:086064 *result->GetData() =
6065 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:146066 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326067}
6068
[email protected]f7b85372010-02-03 01:11:376069bool GLES2DecoderImpl::GetUniformSetup(
6070 GLuint program, GLint location,
6071 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:106072 error::Error* error, GLuint* service_id, void** result_pointer,
6073 GLenum* result_type) {
6074 DCHECK(error);
6075 DCHECK(service_id);
6076 DCHECK(result_pointer);
6077 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:376078 *error = error::kNoError;
6079 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:256080 SizedResult<GLint>* result;
6081 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6082 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
6083 if (!result) {
[email protected]f7b85372010-02-03 01:11:376084 *error = error::kOutOfBounds;
6085 return false;
6086 }
[email protected]0bfd9882010-02-05 23:02:256087 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:376088 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:256089 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:586090 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6091 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:376092 if (!info) {
[email protected]ae51d192010-04-27 00:48:036093 return false;
6094 }
6095 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:376096 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:296097 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:376098 return false;
6099 }
[email protected]ae51d192010-04-27 00:48:036100 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:366101 GLint array_index = -1;
6102 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6103 info->GetUniformInfoByLocation(location, &array_index);
6104 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:376105 // No such location.
[email protected]8eee29c2010-04-29 03:38:296106 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:376107 return false;
6108 }
[email protected]43c2f1f2011-03-25 18:35:366109 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:506110 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:376111 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:296112 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:376113 return false;
6114 }
[email protected]0bfd9882010-02-05 23:02:256115 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6116 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
6117 if (!result) {
[email protected]f7b85372010-02-03 01:11:376118 *error = error::kOutOfBounds;
6119 return false;
6120 }
[email protected]0bfd9882010-02-05 23:02:256121 result->size = size;
[email protected]939e7362010-05-13 20:49:106122 *result_type = type;
[email protected]f7b85372010-02-03 01:11:376123 return true;
6124}
6125
[email protected]f7a64ee2010-02-01 22:24:146126error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:196127 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:376128 GLuint program = c.program;
6129 GLint location = c.location;
6130 GLuint service_id;
[email protected]939e7362010-05-13 20:49:106131 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376132 Error error;
[email protected]0bfd9882010-02-05 23:02:256133 void* result;
[email protected]f7b85372010-02-03 01:11:376134 if (GetUniformSetup(
6135 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106136 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:256137 glGetUniformiv(
6138 service_id, location,
6139 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:376140 }
6141 return error;
[email protected]96449d2c2009-11-25 00:01:326142}
6143
[email protected]f7a64ee2010-02-01 22:24:146144error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:196145 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:376146 GLuint program = c.program;
6147 GLint location = c.location;
6148 GLuint service_id;
6149 Error error;
[email protected]0bfd9882010-02-05 23:02:256150 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:106151 Result* result;
6152 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376153 if (GetUniformSetup(
6154 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106155 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
6156 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
6157 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
6158 GLsizei num_values = result->GetNumResults();
6159 scoped_array<GLint> temp(new GLint[num_values]);
6160 glGetUniformiv(service_id, location, temp.get());
6161 GLfloat* dst = result->GetData();
6162 for (GLsizei ii = 0; ii < num_values; ++ii) {
6163 dst[ii] = (temp[ii] != 0);
6164 }
6165 } else {
6166 glGetUniformfv(service_id, location, result->GetData());
6167 }
[email protected]f7b85372010-02-03 01:11:376168 }
6169 return error;
[email protected]96449d2c2009-11-25 00:01:326170}
6171
[email protected]f7a64ee2010-02-01 22:24:146172error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:196173 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:256174 GLenum shader_type = static_cast<GLenum>(c.shadertype);
6175 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
6176 typedef gles2::GetShaderPrecisionFormat::Result Result;
6177 Result* result = GetSharedMemoryAs<Result*>(
6178 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6179 if (!result) {
6180 return error::kOutOfBounds;
6181 }
[email protected]07d0cc82010-02-17 04:51:406182 // Check that the client initialized the result.
6183 if (result->success != 0) {
6184 return error::kInvalidArguments;
6185 }
[email protected]9438b012010-06-15 22:55:056186 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:296187 SetGLError(GL_INVALID_ENUM,
6188 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
6189 return error::kNoError;
6190 }
[email protected]9438b012010-06-15 22:55:056191 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:296192 SetGLError(GL_INVALID_ENUM,
6193 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
6194 return error::kNoError;
6195 }
6196
6197 result->success = 1; // true
6198 switch (precision_type) {
6199 case GL_LOW_INT:
6200 case GL_MEDIUM_INT:
6201 case GL_HIGH_INT:
6202 result->min_range = -31;
6203 result->max_range = 31;
6204 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:106205 break;
[email protected]8eee29c2010-04-29 03:38:296206 case GL_LOW_FLOAT:
6207 case GL_MEDIUM_FLOAT:
6208 case GL_HIGH_FLOAT:
6209 result->min_range = -62;
6210 result->max_range = 62;
6211 result->precision = -16;
6212 break;
6213 default:
6214 NOTREACHED();
6215 break;
[email protected]0bfd9882010-02-05 23:02:256216 }
[email protected]f7a64ee2010-02-01 22:24:146217 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326218}
6219
[email protected]f7a64ee2010-02-01 22:24:146220error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:196221 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:256222 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:586223 GLuint program = static_cast<GLuint>(c.program);
6224 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6225 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:036226 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256227 return error::kNoError;
6228 }
6229 typedef gles2::GetAttachedShaders::Result Result;
6230 uint32 max_count = Result::ComputeMaxResults(result_size);
6231 Result* result = GetSharedMemoryAs<Result*>(
6232 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
6233 if (!result) {
6234 return error::kOutOfBounds;
6235 }
[email protected]07d0cc82010-02-17 04:51:406236 // Check that the client initialized the result.
6237 if (result->size != 0) {
6238 return error::kInvalidArguments;
6239 }
[email protected]0bfd9882010-02-05 23:02:256240 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:036241 glGetAttachedShaders(
6242 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:256243 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:036244 if (!shader_manager()->GetClientId(result->GetData()[ii],
6245 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:256246 NOTREACHED();
6247 return error::kGenericError;
6248 }
6249 }
6250 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:146251 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326252}
6253
[email protected]f7a64ee2010-02-01 22:24:146254error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:196255 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:256256 GLuint program = c.program;
6257 GLuint index = c.index;
6258 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256259 typedef gles2::GetActiveUniform::Result Result;
6260 Result* result = GetSharedMemoryAs<Result*>(
6261 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6262 if (!result) {
6263 return error::kOutOfBounds;
6264 }
[email protected]07d0cc82010-02-17 04:51:406265 // Check that the client initialized the result.
6266 if (result->success != 0) {
6267 return error::kInvalidArguments;
6268 }
[email protected]6b8cf1a2010-05-06 16:13:586269 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6270 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:036271 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256272 return error::kNoError;
6273 }
6274 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6275 info->GetUniformInfo(index);
6276 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:296277 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:256278 return error::kNoError;
6279 }
6280 result->success = 1; // true.
6281 result->size = uniform_info->size;
6282 result->type = uniform_info->type;
6283 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296284 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146285 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326286}
6287
[email protected]f7a64ee2010-02-01 22:24:146288error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:196289 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:256290 GLuint program = c.program;
6291 GLuint index = c.index;
6292 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256293 typedef gles2::GetActiveAttrib::Result Result;
6294 Result* result = GetSharedMemoryAs<Result*>(
6295 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6296 if (!result) {
6297 return error::kOutOfBounds;
6298 }
[email protected]07d0cc82010-02-17 04:51:406299 // Check that the client initialized the result.
6300 if (result->success != 0) {
6301 return error::kInvalidArguments;
6302 }
[email protected]6b8cf1a2010-05-06 16:13:586303 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6304 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:036305 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256306 return error::kNoError;
6307 }
6308 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
6309 info->GetAttribInfo(index);
6310 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:296311 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:256312 return error::kNoError;
6313 }
6314 result->success = 1; // true.
6315 result->size = attrib_info->size;
6316 result->type = attrib_info->type;
6317 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296318 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146319 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326320}
6321
[email protected]b273e432010-04-12 17:23:586322error::Error GLES2DecoderImpl::HandleShaderBinary(
6323 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
6324#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:296325 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:586326 return error::kNoError;
6327#else
6328 GLsizei n = static_cast<GLsizei>(c.n);
6329 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:296330 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:586331 return error::kNoError;
6332 }
6333 GLsizei length = static_cast<GLsizei>(c.length);
6334 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:296335 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:586336 return error::kNoError;
6337 }
6338 uint32 data_size;
6339 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
6340 return error::kOutOfBounds;
6341 }
6342 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
6343 c.shaders_shm_id, c.shaders_shm_offset, data_size);
6344 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
6345 const void* binary = GetSharedMemoryAs<const void*>(
6346 c.binary_shm_id, c.binary_shm_offset, length);
6347 if (shaders == NULL || binary == NULL) {
6348 return error::kOutOfBounds;
6349 }
6350 scoped_array<GLuint> service_ids(new GLuint[n]);
6351 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:036352 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
6353 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296354 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:586355 return error::kNoError;
6356 }
[email protected]ae51d192010-04-27 00:48:036357 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:586358 }
6359 // TODO(gman): call glShaderBinary
6360 return error::kNoError;
6361#endif
6362}
6363
[email protected]6217d392010-03-25 22:08:356364error::Error GLES2DecoderImpl::HandleSwapBuffers(
6365 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:496366 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
6367 int this_frame_number = frame_number_++;
6368 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
6369 "offscreen", is_offscreen,
6370 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:356371 // If offscreen then don't actually SwapBuffers to the display. Just copy
6372 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:496373 if (is_offscreen) {
[email protected]6217d392010-03-25 22:08:356374 ScopedGLErrorSuppressor suppressor(this);
6375
6376 // First check to see if a deferred offscreen render buffer resize is
6377 // pending.
[email protected]d0498742010-09-20 20:27:016378 if (!UpdateOffscreenFrameBufferSize()) {
6379 LOG(ERROR) << "Context lost because reallocation of offscreen FBO "
6380 << "failed.";
[email protected]6217d392010-03-25 22:08:356381 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016382 }
[email protected]6217d392010-03-25 22:08:356383
[email protected]34ff8b0c2010-10-01 20:06:026384 if (IsOffscreenBufferMultisampled()) {
6385 // For multisampled buffers, bind the resolved frame buffer so that
6386 // callbacks can call ReadPixels or CopyTexImage2D.
[email protected]c0701082011-04-20 00:34:526387 ScopedResolvedFrameBufferBinder binder(this, true);
[email protected]34ff8b0c2010-10-01 20:06:026388 if (swap_buffers_callback_.get()) {
6389 swap_buffers_callback_->Run();
6390 }
[email protected]89d6ed02011-04-20 00:23:236391 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:486392 } else {
[email protected]0c8c9d22010-06-25 17:36:396393 ScopedFrameBufferBinder binder(this,
6394 offscreen_target_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:406395
[email protected]b86b14982010-10-11 18:45:486396 if (parent_) {
6397 // Copy the target frame buffer to the saved offscreen texture.
6398 offscreen_saved_color_texture_->Copy(
6399 offscreen_saved_color_texture_->size());
6400
[email protected]a3ded6d2010-10-19 06:44:396401 // Ensure the side effects of the copy are visible to the parent
6402 // context. There is no need to do this for ANGLE because it uses a
6403 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:486404 if (!IsAngle())
6405 glFlush();
6406 }
6407
6408 // Run the callback with |binder| in scope, so that the callback can call
6409 // ReadPixels or CopyTexImage2D.
6410 if (swap_buffers_callback_.get()) {
6411 swap_buffers_callback_->Run();
6412 }
[email protected]89d6ed02011-04-20 00:23:236413 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:396414 }
[email protected]6217d392010-03-25 22:08:356415 } else {
[email protected]64ace852011-05-19 21:49:496416 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:156417 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:016418 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:026419 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016420 }
[email protected]6217d392010-03-25 22:08:356421 }
6422
6423 if (swap_buffers_callback_.get()) {
6424 swap_buffers_callback_->Run();
6425 }
6426
[email protected]89d6ed02011-04-20 00:23:236427 return error::kNoError;
[email protected]6217d392010-03-25 22:08:356428}
6429
[email protected]1e6f58d2011-03-24 00:00:406430error::Error GLES2DecoderImpl::HandleSetLatchCHROMIUM(
6431 uint32 immediate_data_size, const gles2::SetLatchCHROMIUM& c) {
[email protected]366ae242011-05-10 02:23:586432 TRACE_EVENT0("gpu", "SetLatch");
[email protected]ce9eea602011-04-12 20:09:576433 // Ensure the side effects of previous commands are visible to other contexts.
6434 // There is no need to do this for ANGLE because it uses a
6435 // single D3D device for all contexts.
6436 if (!IsAngle())
6437 glFlush();
6438
6439 int32 shm_id = gpu::kLatchSharedMemoryId;
[email protected]1e6f58d2011-03-24 00:00:406440 uint32 latch_id = c.latch_id;
6441 uint32 shm_offset = 0;
6442 base::subtle::Atomic32* latch;
6443 if (!SafeMultiplyUint32(latch_id, sizeof(*latch), &shm_offset)) {
6444 return error::kOutOfBounds;
6445 }
6446 latch = GetSharedMemoryAs<base::subtle::Atomic32*>(
6447 shm_id, shm_offset, sizeof(*latch));
6448 if (!latch) {
6449 return error::kOutOfBounds;
6450 }
[email protected]fbe20372011-06-01 01:46:386451 base::subtle::Atomic32 old =
6452 base::subtle::NoBarrier_CompareAndSwap(latch, 0, 1);
6453 DCHECK(old == 0);
[email protected]80c49752011-04-18 23:55:106454 if (!latch_callback_.is_null())
6455 latch_callback_.Run(true);
[email protected]1e6f58d2011-03-24 00:00:406456 return error::kNoError;
6457}
6458
6459error::Error GLES2DecoderImpl::HandleWaitLatchCHROMIUM(
6460 uint32 immediate_data_size, const gles2::WaitLatchCHROMIUM& c) {
[email protected]366ae242011-05-10 02:23:586461 TRACE_EVENT0("gpu", "WaitLatch");
[email protected]ce9eea602011-04-12 20:09:576462 int32 shm_id = gpu::kLatchSharedMemoryId;
[email protected]1e6f58d2011-03-24 00:00:406463 uint32 latch_id = c.latch_id;
6464 uint32 shm_offset = 0;
6465 base::subtle::Atomic32* latch;
6466 if (!SafeMultiplyUint32(latch_id, sizeof(*latch), &shm_offset)) {
6467 return error::kOutOfBounds;
6468 }
6469 latch = GetSharedMemoryAs<base::subtle::Atomic32*>(
6470 shm_id, shm_offset, sizeof(*latch));
6471 if (!latch) {
6472 return error::kOutOfBounds;
6473 }
6474
6475 base::subtle::Atomic32 old =
6476 base::subtle::NoBarrier_CompareAndSwap(latch, 1, 0);
[email protected]80c49752011-04-18 23:55:106477 if (old == 0) {
6478 if (!latch_callback_.is_null())
6479 latch_callback_.Run(false);
6480 return error::kWaiting;
6481 } else {
6482 return error::kNoError;
6483 }
[email protected]1e6f58d2011-03-24 00:00:406484}
6485
[email protected]269200b12010-11-18 22:53:066486error::Error GLES2DecoderImpl::HandleCommandBufferEnableCHROMIUM(
6487 uint32 immediate_data_size, const gles2::CommandBufferEnableCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:186488 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]269200b12010-11-18 22:53:066489 typedef gles2::CommandBufferEnableCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:186490 Result* result = GetSharedMemoryAs<Result*>(
6491 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6492 if (!result) {
6493 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:106494 }
[email protected]b1d2dcb2010-05-17 19:24:186495 // Check that the client initialized the result.
6496 if (*result != 0) {
6497 return error::kInvalidArguments;
6498 }
6499 std::string feature_str;
6500 if (!bucket->GetAsString(&feature_str)) {
6501 return error::kInvalidArguments;
6502 }
6503
6504 // TODO(gman): make this some kind of table to function pointer thingy.
6505 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
6506 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]8fbedc02010-11-18 18:43:406507 } else if (feature_str.compare(PEPPER3D_SUPPORT_FIXED_ATTRIBS) == 0) {
6508 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
6509 // TODO(gman): decide how to remove the need for this const_cast.
6510 // I could make validators_ non const but that seems bad as this is the only
6511 // place it is needed. I could make some special friend class of validators
6512 // just to allow this to set them. That seems silly. I could refactor this
6513 // code to use the extension mechanism or the initialization attributes to
6514 // turn this feature on. Given that the only real point of this is to make
6515 // the conformance tests pass and given that there is lots of real work that
6516 // needs to be done it seems like refactoring for one to one of those
6517 // methods is a very low priority.
6518 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]b1d2dcb2010-05-17 19:24:186519 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
6520 use_shader_translator_ = false;
6521 } else {
6522 return error::kNoError;
6523 }
6524
6525 *result = 1; // true.
6526 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:106527}
6528
[email protected]c2f8c8402010-12-06 18:07:246529error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
6530 uint32 immediate_data_size,
6531 const gles2::GetRequestableExtensionsCHROMIUM& c) {
6532 Bucket* bucket = CreateBucket(c.bucket_id);
6533 scoped_ptr<FeatureInfo> info(new FeatureInfo());
[email protected]c410da802011-03-14 19:17:416534 info->Initialize(disallowed_extensions_, NULL);
[email protected]c2f8c8402010-12-06 18:07:246535 bucket->SetFromString(info->extensions().c_str());
6536 return error::kNoError;
6537}
6538
6539error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
6540 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
6541 Bucket* bucket = GetBucket(c.bucket_id);
6542 std::string feature_str;
6543 if (!bucket->GetAsString(&feature_str)) {
6544 return error::kInvalidArguments;
6545 }
6546
6547 bool std_derivatives_enabled =
6548 feature_info_->feature_flags().oes_standard_derivatives;
6549 bool webglsl_enabled =
6550 feature_info_->feature_flags().chromium_webglsl;
6551
6552 feature_info_->AddFeatures(feature_str.c_str());
6553
6554 // If we just enabled a feature which affects the shader translator,
6555 // we may need to re-initialize it.
6556 if (std_derivatives_enabled !=
6557 feature_info_->feature_flags().oes_standard_derivatives ||
6558 webglsl_enabled !=
6559 feature_info_->feature_flags().chromium_webglsl) {
6560 InitializeShaderTranslator();
6561 }
6562
6563 return error::kNoError;
6564}
6565
[email protected]96449d2c2009-11-25 00:01:326566// Include the auto-generated part of this file. We split this because it means
6567// we can easily edit the non-auto generated parts right here in this file
6568// instead of having to edit some template or the code generator.
6569#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
6570
6571} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:256572} // namespace gpu