blob: e0df16556b8951fe21fd13c7947f62ff1be8e459 [file] [log] [blame]
[email protected]d366c482010-10-20 00:11:271// Copyright (c) 2010 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
15#include "app/gfx/gl/gl_context.h"
[email protected]b9363b22010-06-09 22:06:1516#include "app/gfx/gl/gl_implementation.h"
[email protected]00eb49a2010-08-12 20:46:5717#include "base/at_exit.h"
[email protected]2041cf342010-02-19 03:15:5918#include "base/callback.h"
[email protected]96449d2c2009-11-25 00:01:3219#include "base/scoped_ptr.h"
[email protected]6217d392010-03-25 22:08:3520#include "base/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0221#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3222#define GLES2_GPU_SERVICE 1
23#include "gpu/command_buffer/common/gles2_cmd_format.h"
24#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1025#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5026#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3227#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5028#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1129#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5830#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3231#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4632#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4733#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5834#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4735#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4536#include "gpu/command_buffer/service/shader_translator.h"
[email protected]a93bb842010-02-16 23:03:4737#include "gpu/command_buffer/service/texture_manager.h"
[email protected]4e8a5b122010-05-08 22:00:1038#include "gpu/GLES2/gles2_command_buffer.h"
[email protected]de17df392010-04-23 21:09:4139
[email protected]6217d392010-03-25 22:08:3540#if !defined(GL_DEPTH24_STENCIL8)
41#define GL_DEPTH24_STENCIL8 0x88F0
42#endif
43
[email protected]a7a27ace2009-12-12 00:11:2544namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3245namespace gles2 {
46
[email protected]6217d392010-03-25 22:08:3547class GLES2DecoderImpl;
48
[email protected]07f54fcc2009-12-22 02:46:3049// Check that certain assumptions the code makes are true. There are places in
50// the code where shared memory is passed direclty to GL. Example, glUniformiv,
51// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
52// a few others) are 32bits. If they are not 32bits the code will have to change
53// to call those GL functions with service side memory and then copy the results
54// to shared memory, converting the sizes.
55COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
56 GLint_not_same_size_as_uint32);
57COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
58 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3759COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
60 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3061
[email protected]43f28f832010-02-03 02:28:4862// TODO(kbr): the use of this anonymous namespace core dumps the
63// linker on Mac OS X 10.6 when the symbol ordering file is used
64// namespace {
[email protected]96449d2c2009-11-25 00:01:3265
66// Returns the address of the first byte after a struct.
67template <typename T>
68const void* AddressAfterStruct(const T& pod) {
69 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
70}
71
[email protected]07f54fcc2009-12-22 02:46:3072// Returns the address of the frst byte after the struct or NULL if size >
73// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3274template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3075RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
76 uint32 size,
77 uint32 immediate_data_size) {
78 return (size <= immediate_data_size) ?
79 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
80 NULL;
[email protected]96449d2c2009-11-25 00:01:3281}
82
[email protected]07f54fcc2009-12-22 02:46:3083// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1884bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3285 GLuint count,
86 size_t size,
[email protected]a76b0052010-03-05 00:33:1887 unsigned int elements_per_unit,
88 uint32* dst) {
89 uint32 value;
90 if (!SafeMultiplyUint32(count, size, &value)) {
91 return false;
92 }
93 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
94 return false;
95 }
96 *dst = value;
97 return true;
[email protected]96449d2c2009-11-25 00:01:3298}
99
100// A struct to hold info about each command.
101struct CommandInfo {
102 int arg_flags; // How to handle the arguments for this command
103 int arg_count; // How many arguments are expected for this command.
104};
105
106// A table of CommandInfo for all the commands.
107const CommandInfo g_command_info[] = {
108 #define GLES2_CMD_OP(name) { \
109 name::kArgFlags, \
110 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
111
112 GLES2_COMMAND_LIST(GLES2_CMD_OP)
113
114 #undef GLES2_CMD_OP
115};
116
[email protected]34ff8b0c2010-10-01 20:06:02117static bool IsAngle() {
118#if defined(OS_WIN)
119 return gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
120#else
121 return false;
122#endif
123}
124
[email protected]6217d392010-03-25 22:08:35125// This class prevents any GL errors that occur when it is in scope from
126// being reported to the client.
127class ScopedGLErrorSuppressor {
128 public:
129 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
130 ~ScopedGLErrorSuppressor();
131 private:
132 GLES2DecoderImpl* decoder_;
133 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
134};
135
136// Temporarily changes a decoder's bound 2D texture and restore it when this
137// object goes out of scope. Also temporarily switches to using active texture
138// unit zero in case the client has changed that to something invalid.
139class ScopedTexture2DBinder {
140 public:
141 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
142 ~ScopedTexture2DBinder();
143
144 private:
145 GLES2DecoderImpl* decoder_;
146 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
147};
148
149// Temporarily changes a decoder's bound render buffer and restore it when this
150// object goes out of scope.
151class ScopedRenderBufferBinder {
152 public:
153 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
154 ~ScopedRenderBufferBinder();
155
156 private:
157 GLES2DecoderImpl* decoder_;
158 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
159};
160
161// Temporarily changes a decoder's bound frame buffer and restore it when this
162// object goes out of scope.
163class ScopedFrameBufferBinder {
164 public:
165 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
166 ~ScopedFrameBufferBinder();
167
168 private:
169 GLES2DecoderImpl* decoder_;
170 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
171};
172
[email protected]34ff8b0c2010-10-01 20:06:02173// Temporarily changes a decoder's bound frame buffer to a resolved version of
174// the multisampled offscreen render buffer if and only if that buffer is
175// currently bound and is multisampled.
176class ScopedResolvedFrameBufferBinder {
177 public:
178 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder);
179 ~ScopedResolvedFrameBufferBinder();
180
181 private:
182 GLES2DecoderImpl* decoder_;
183 bool resolve_and_bind_;
184 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
185};
186
[email protected]6217d392010-03-25 22:08:35187// Encapsulates an OpenGL texture.
188class Texture {
189 public:
190 explicit Texture(GLES2DecoderImpl* decoder);
191 ~Texture();
192
193 // Create a new render texture.
194 void Create();
195
196 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02197 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35198
199 // Copy the contents of the currently bound frame buffer.
200 void Copy(const gfx::Size& size);
201
202 // Destroy the render texture. This must be explicitly called before
203 // destroying this object.
204 void Destroy();
205
[email protected]97872062010-11-03 19:07:05206 // Invalidate the texture. This can be used when a context is lost and it is
207 // not possible to make it current in order to free the resource.
208 void Invalidate();
209
[email protected]6217d392010-03-25 22:08:35210 GLuint id() const {
211 return id_;
212 }
213
[email protected]d37231fa2010-04-09 21:16:02214 gfx::Size size() const {
215 return size_;
216 }
217
[email protected]6217d392010-03-25 22:08:35218 private:
219 GLES2DecoderImpl* decoder_;
220 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02221 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35222 DISALLOW_COPY_AND_ASSIGN(Texture);
223};
224
225// Encapsulates an OpenGL render buffer of any format.
226class RenderBuffer {
227 public:
228 explicit RenderBuffer(GLES2DecoderImpl* decoder);
229 ~RenderBuffer();
230
231 // Create a new render buffer.
232 void Create();
233
234 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02235 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35236
237 // Destroy the render buffer. This must be explicitly called before destroying
238 // this object.
239 void Destroy();
240
[email protected]97872062010-11-03 19:07:05241 // Invalidate the render buffer. This can be used when a context is lost and
242 // it is not possible to make it current in order to free the resource.
243 void Invalidate();
244
[email protected]6217d392010-03-25 22:08:35245 GLuint id() const {
246 return id_;
247 }
248
249 private:
250 GLES2DecoderImpl* decoder_;
251 GLuint id_;
252 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
253};
254
255// Encapsulates an OpenGL frame buffer.
256class FrameBuffer {
257 public:
258 explicit FrameBuffer(GLES2DecoderImpl* decoder);
259 ~FrameBuffer();
260
261 // Create a new frame buffer.
262 void Create();
263
264 // Attach a color render buffer to a frame buffer.
265 void AttachRenderTexture(Texture* texture);
266
[email protected]b9363b22010-06-09 22:06:15267 // Attach a render buffer to a frame buffer. Note that this unbinds any
268 // currently bound frame buffer.
269 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35270
271 // Clear the given attached buffers.
272 void Clear(GLbitfield buffers);
273
274 // Destroy the frame buffer. This must be explicitly called before destroying
275 // this object.
276 void Destroy();
277
[email protected]97872062010-11-03 19:07:05278 // Invalidate the frame buffer. This can be used when a context is lost and it
279 // is not possible to make it current in order to free the resource.
280 void Invalidate();
281
[email protected]6217d392010-03-25 22:08:35282 // See glCheckFramebufferStatusEXT.
283 GLenum CheckStatus();
284
285 GLuint id() const {
286 return id_;
287 }
288
289 private:
290 GLES2DecoderImpl* decoder_;
291 GLuint id_;
292 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
293};
[email protected]34ff8b0c2010-10-01 20:06:02294
295class ContextCreationAttribParser {
296 public:
297 ContextCreationAttribParser();
298 bool Parse(const std::vector<int32>& attribs);
299
300 // -1 if invalid or unspecified.
301 int32 alpha_size_;
302 int32 blue_size_;
303 int32 green_size_;
304 int32 red_size_;
305 int32 depth_size_;
306 int32 stencil_size_;
307 int32 samples_;
308 int32 sample_buffers_;
309};
310
311ContextCreationAttribParser::ContextCreationAttribParser()
312 : alpha_size_(-1),
313 blue_size_(-1),
314 green_size_(-1),
315 red_size_(-1),
316 depth_size_(-1),
317 stencil_size_(-1),
318 samples_(-1),
319 sample_buffers_(-1) {
320}
321
322bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
323 // From <EGL/egl.h>.
324 const int32 EGL_ALPHA_SIZE = 0x3021;
325 const int32 EGL_BLUE_SIZE = 0x3022;
326 const int32 EGL_GREEN_SIZE = 0x3023;
327 const int32 EGL_RED_SIZE = 0x3024;
328 const int32 EGL_DEPTH_SIZE = 0x3025;
329 const int32 EGL_STENCIL_SIZE = 0x3026;
330 const int32 EGL_SAMPLES = 0x3031;
331 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
332 const int32 EGL_NONE = 0x3038;
333
334 for (size_t i = 0; i < attribs.size(); i += 2) {
335 const int32 attrib = attribs[i];
336 if (i + 1 >= attribs.size()) {
337 if (attrib == EGL_NONE)
338 return true;
339
340 DLOG(ERROR) << "Missing value after context creation attribute: "
341 << attrib;
342 return false;
343 }
344
345 const int32 value = attribs[i+1];
346 switch (attrib) {
347 case EGL_ALPHA_SIZE:
348 alpha_size_ = value;
349 break;
350 case EGL_BLUE_SIZE:
351 blue_size_ = value;
352 break;
353 case EGL_GREEN_SIZE:
354 green_size_ = value;
355 break;
356 case EGL_RED_SIZE:
357 red_size_ = value;
358 break;
359 case EGL_DEPTH_SIZE:
360 depth_size_ = value;
361 break;
362 case EGL_STENCIL_SIZE:
363 stencil_size_ = value;
364 break;
365 case EGL_SAMPLES:
366 samples_ = value;
367 break;
368 case EGL_SAMPLE_BUFFERS:
369 sample_buffers_ = value;
370 break;
371 case EGL_NONE:
372 // Terminate list, even if more attributes.
373 return true;
374 default:
375 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
376 return false;
377 }
378 }
379
380 return true;
381}
382
[email protected]43f28f832010-02-03 02:28:48383// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32384
[email protected]a3ded6d2010-10-19 06:44:39385GLES2Decoder::GLES2Decoder()
386 : debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32387}
388
[email protected]3916c97e2010-02-25 03:20:50389GLES2Decoder::~GLES2Decoder() {
390}
391
[email protected]f39f4b3f2010-05-12 17:04:08392class VertexAttribManager {
[email protected]96449d2c2009-11-25 00:01:32393 public:
[email protected]07f54fcc2009-12-22 02:46:30394 // Info about Vertex Attributes. This is used to track what the user currently
395 // has bound on each Vertex Attribute so that checking can be done at
396 // glDrawXXX time.
397 class VertexAttribInfo {
398 public:
[email protected]f39f4b3f2010-05-12 17:04:08399 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
[email protected]b1122982010-05-17 23:04:24400 struct Vec4 {
401 float v[4];
402 };
[email protected]f39f4b3f2010-05-12 17:04:08403
[email protected]07f54fcc2009-12-22 02:46:30404 VertexAttribInfo()
[email protected]f39f4b3f2010-05-12 17:04:08405 : index_(0),
406 enabled_(false),
407 size_(4),
408 type_(GL_FLOAT),
[email protected]07f54fcc2009-12-22 02:46:30409 offset_(0),
[email protected]b1122982010-05-17 23:04:24410 normalized_(GL_FALSE),
411 gl_stride_(0),
[email protected]f39f4b3f2010-05-12 17:04:08412 real_stride_(16),
413 list_(NULL) {
[email protected]b1122982010-05-17 23:04:24414 value_.v[0] = 0.0f;
415 value_.v[1] = 0.0f;
416 value_.v[2] = 0.0f;
417 value_.v[3] = 1.0f;
[email protected]07f54fcc2009-12-22 02:46:30418 }
[email protected]3916c97e2010-02-25 03:20:50419
[email protected]07f54fcc2009-12-22 02:46:30420 // Returns true if this VertexAttrib can access index.
[email protected]f39f4b3f2010-05-12 17:04:08421 bool CanAccess(GLuint index) const;
[email protected]07f54fcc2009-12-22 02:46:30422
[email protected]3916c97e2010-02-25 03:20:50423 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30424 return buffer_;
425 }
426
[email protected]8bf5a3e2010-01-29 04:21:36427 GLsizei offset() const {
428 return offset_;
429 }
430
[email protected]f39f4b3f2010-05-12 17:04:08431 GLuint index() const {
432 return index_;
433 }
434
[email protected]b1122982010-05-17 23:04:24435 GLint size() const {
436 return size_;
437 }
438
439 GLenum type() const {
440 return type_;
441 }
442
443 GLboolean normalized() const {
444 return normalized_;
445 }
446
447 GLsizei gl_stride() const {
448 return gl_stride_;
449 }
450
[email protected]07f54fcc2009-12-22 02:46:30451 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50452 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30453 GLint size,
454 GLenum type,
[email protected]b1122982010-05-17 23:04:24455 GLboolean normalized,
456 GLsizei gl_stride,
[email protected]07f54fcc2009-12-22 02:46:30457 GLsizei real_stride,
458 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24459 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30460 buffer_ = buffer;
461 size_ = size;
462 type_ = type;
[email protected]b1122982010-05-17 23:04:24463 normalized_ = normalized;
464 gl_stride_ = gl_stride;
[email protected]07f54fcc2009-12-22 02:46:30465 real_stride_ = real_stride;
466 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50467 }
468
469 void ClearBuffer() {
470 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30471 }
472
[email protected]f39f4b3f2010-05-12 17:04:08473 bool enabled() const {
474 return enabled_;
475 }
476
[email protected]b1122982010-05-17 23:04:24477 void set_value(const Vec4& value) {
478 value_ = value;
479 }
480
481 const Vec4& value() const {
482 return value_;
483 }
484
[email protected]07f54fcc2009-12-22 02:46:30485 private:
[email protected]f39f4b3f2010-05-12 17:04:08486 friend class VertexAttribManager;
487
488 void set_enabled(bool enabled) {
489 enabled_ = enabled;
490 }
491
492 void set_index(GLuint index) {
493 index_ = index;
494 }
495
496 void SetList(VertexAttribInfoList* new_list) {
497 DCHECK(new_list);
498
499 if (list_) {
500 list_->erase(it_);
501 }
502
503 it_ = new_list->insert(new_list->end(), this);
504 list_ = new_list;
505 }
506
507 // The index of this attrib.
508 GLuint index_;
509
[email protected]07f54fcc2009-12-22 02:46:30510 // Whether or not this attribute is enabled.
511 bool enabled_;
512
513 // number of components (1, 2, 3, 4)
514 GLint size_;
515
516 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
517 GLenum type_;
518
519 // The offset into the buffer.
520 GLsizei offset_;
521
[email protected]b1122982010-05-17 23:04:24522 GLboolean normalized_;
523
524 // The stride passed to glVertexAttribPointer.
525 GLsizei gl_stride_;
526
[email protected]07f54fcc2009-12-22 02:46:30527 // The stride that will be used to access the buffer. This is the actual
528 // stide, NOT the GL bogus stride. In other words there is never a stride
529 // of 0.
530 GLsizei real_stride_;
531
[email protected]b1122982010-05-17 23:04:24532 // The current value of the attrib.
533 Vec4 value_;
534
[email protected]3916c97e2010-02-25 03:20:50535 // The buffer bound to this attribute.
536 BufferManager::BufferInfo::Ref buffer_;
[email protected]f39f4b3f2010-05-12 17:04:08537
538 // List this info is on.
539 VertexAttribInfoList* list_;
540
541 // Iterator for list this info is on. Enabled/Disabled
542 VertexAttribInfoList::iterator it_;
[email protected]07f54fcc2009-12-22 02:46:30543 };
544
[email protected]f39f4b3f2010-05-12 17:04:08545 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
546
547 VertexAttribManager()
548 : max_vertex_attribs_(0) {
549 }
550
551 void Initialize(uint32 num_vertex_attribs);
552
553 bool Enable(GLuint index, bool enable);
554
555 const VertexAttribInfoList& GetEnabledVertexAttribInfos() const {
556 return enabled_vertex_attribs_;
557 }
558
559 VertexAttribInfo* GetVertexAttribInfo(GLuint index) {
[email protected]b1122982010-05-17 23:04:24560 if (index < max_vertex_attribs_) {
561 return &vertex_attrib_infos_[index];
562 }
563 return NULL;
[email protected]f39f4b3f2010-05-12 17:04:08564 }
565
566 private:
567 uint32 max_vertex_attribs_;
568
569 // Info for each vertex attribute saved so we can check at glDrawXXX time
570 // if it is safe to draw.
571 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
572
573 // Lists for which vertex attribs are enabled, disabled.
574 VertexAttribInfoList enabled_vertex_attribs_;
575 VertexAttribInfoList disabled_vertex_attribs_;
576};
577
578bool VertexAttribManager::VertexAttribInfo::CanAccess(GLuint index) const {
579 if (!enabled_) {
580 return true;
581 }
582
583 if (!buffer_ || buffer_->IsDeleted()) {
584 return false;
585 }
586
587 // The number of elements that can be accessed.
588 GLsizeiptr buffer_size = buffer_->size();
589 if (offset_ > buffer_size || real_stride_ == 0) {
590 return false;
591 }
592
593 uint32 usable_size = buffer_size - offset_;
594 GLuint num_elements = usable_size / real_stride_ +
595 ((usable_size % real_stride_) >=
596 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
597 return index < num_elements;
598}
599
600
601void VertexAttribManager::Initialize(uint32 max_vertex_attribs) {
602 max_vertex_attribs_ = max_vertex_attribs;
603 vertex_attrib_infos_.reset(
604 new VertexAttribInfo[max_vertex_attribs]);
605 for (uint32 vv = 0; vv < max_vertex_attribs; ++vv) {
606 vertex_attrib_infos_[vv].set_index(vv);
607 vertex_attrib_infos_[vv].SetList(&disabled_vertex_attribs_);
608 }
609}
610
611bool VertexAttribManager::Enable(GLuint index, bool enable) {
612 if (index >= max_vertex_attribs_) {
613 return false;
614 }
615 VertexAttribInfo& info = vertex_attrib_infos_[index];
616 if (info.enabled() != enable) {
617 info.set_enabled(enable);
618 info.SetList(enable ? &enabled_vertex_attribs_ : &disabled_vertex_attribs_);
619 }
620 return true;
621}
622
623// This class implements GLES2Decoder so we don't have to expose all the GLES2
624// cmd stuff to outside this class.
625class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
626 public GLES2Decoder {
627 public:
628 explicit GLES2DecoderImpl(ContextGroup* group);
629
[email protected]96449d2c2009-11-25 00:01:32630 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14631 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50632 unsigned int arg_count,
633 const void* args);
[email protected]96449d2c2009-11-25 00:01:32634
635 // Overridden from AsyncAPIInterface.
636 virtual const char* GetCommandName(unsigned int command_id) const;
637
638 // Overridden from GLES2Decoder.
[email protected]5a6db6c2010-04-22 18:32:06639 virtual bool Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:35640 const gfx::Size& size,
[email protected]a3ded6d2010-10-19 06:44:39641 const char* allowed_extensions,
[email protected]34ff8b0c2010-10-01 20:06:02642 const std::vector<int32>& attribs,
[email protected]d37231fa2010-04-09 21:16:02643 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35644 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32645 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35646 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]c71caa82010-06-02 23:25:45647 virtual bool UpdateOffscreenFrameBufferSize();
[email protected]eb54a562010-01-20 21:55:18648 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55649 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30650 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39651 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48652
653 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
[email protected]1318e922010-09-17 22:03:16654 virtual bool GetServiceTextureId(uint32 client_texture_id,
655 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48656
[email protected]8e3e0662010-08-23 18:46:30657 // Restores the current state to the user's settings.
658 void RestoreCurrentFramebufferBindings();
659 void RestoreCurrentRenderbufferBindings();
660 void RestoreCurrentTexture2DBindings();
661
[email protected]96449d2c2009-11-25 00:01:32662 private:
[email protected]6217d392010-03-25 22:08:35663 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02664 friend class ScopedResolvedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35665 friend class RenderBuffer;
666 friend class FrameBuffer;
667
[email protected]3916c97e2010-02-25 03:20:50668 // State associated with each texture unit.
669 struct TextureUnit {
670 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
671
672 // The last target that was bound to this texture unit.
673 GLenum bind_target;
674
675 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
676 TextureManager::TextureInfo::Ref bound_texture_2d;
677
678 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
679 // glBindTexture
680 TextureManager::TextureInfo::Ref bound_texture_cube_map;
681 };
682
[email protected]ae51d192010-04-27 00:48:03683 // Helpers for the glGen and glDelete functions.
684 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
685 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
686 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
687 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
688 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
689 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
690 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
691 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47692
[email protected]3916c97e2010-02-25 03:20:50693 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50694 BufferManager* buffer_manager() {
695 return group_->buffer_manager();
696 }
697
[email protected]a25fa872010-03-25 02:57:58698 RenderbufferManager* renderbuffer_manager() {
699 return group_->renderbuffer_manager();
700 }
701
702 FramebufferManager* framebuffer_manager() {
703 return group_->framebuffer_manager();
704 }
705
[email protected]3916c97e2010-02-25 03:20:50706 ProgramManager* program_manager() {
707 return group_->program_manager();
708 }
709
710 ShaderManager* shader_manager() {
711 return group_->shader_manager();
712 }
713
714 TextureManager* texture_manager() {
715 return group_->texture_manager();
716 }
717
[email protected]34ff8b0c2010-10-01 20:06:02718 bool IsOffscreenBufferMultisampled() const {
719 return offscreen_target_samples_ > 1;
720 }
721
[email protected]a93bb842010-02-16 23:03:47722 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03723 TextureManager::TextureInfo* CreateTextureInfo(
724 GLuint client_id, GLuint service_id) {
[email protected]915a59a12010-09-30 21:29:11725 return texture_manager()->CreateTextureInfo(
726 feature_info_, client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47727 }
728
729 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03730 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50731 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03732 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50733 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47734 }
735
736 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03737 void RemoveTextureInfo(GLuint client_id) {
[email protected]915a59a12010-09-30 21:29:11738 texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]3916c97e2010-02-25 03:20:50739 }
[email protected]a93bb842010-02-16 23:03:47740
[email protected]d37231fa2010-04-09 21:16:02741 // Get the size (in pixels) of the currently bound frame buffer (either FBO
742 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30743 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02744
[email protected]a93bb842010-02-16 23:03:47745 // Wrapper for CompressedTexImage2D commands.
746 error::Error DoCompressedTexImage2D(
747 GLenum target,
748 GLint level,
749 GLenum internal_format,
750 GLsizei width,
751 GLsizei height,
752 GLint border,
753 GLsizei image_size,
754 const void* data);
755
[email protected]cadde4a2010-07-31 17:10:43756 // Wrapper for CompressedTexSubImage2D.
757 void DoCompressedTexSubImage2D(
758 GLenum target,
759 GLint level,
760 GLint xoffset,
761 GLint yoffset,
762 GLsizei width,
763 GLsizei height,
764 GLenum format,
765 GLsizei imageSize,
766 const void * data);
767
768 // Wrapper for CopyTexImage2D.
769 void DoCopyTexImage2D(
770 GLenum target,
771 GLint level,
772 GLenum internal_format,
773 GLint x,
774 GLint y,
775 GLsizei width,
776 GLsizei height,
777 GLint border);
778
779 // Wrapper for CopyTexSubImage2D.
780 void DoCopyTexSubImage2D(
781 GLenum target,
782 GLint level,
783 GLint xoffset,
784 GLint yoffset,
785 GLint x,
786 GLint y,
787 GLsizei width,
788 GLsizei height);
789
[email protected]a93bb842010-02-16 23:03:47790 // Wrapper for TexImage2D commands.
791 error::Error DoTexImage2D(
792 GLenum target,
793 GLint level,
794 GLenum internal_format,
795 GLsizei width,
796 GLsizei height,
797 GLint border,
798 GLenum format,
799 GLenum type,
800 const void* pixels,
801 uint32 pixels_size);
802
[email protected]cadde4a2010-07-31 17:10:43803 // Wrapper for TexSubImage2D.
804 void DoTexSubImage2D(
805 GLenum target,
806 GLint level,
807 GLint xoffset,
808 GLint yoffset,
809 GLsizei width,
810 GLsizei height,
811 GLenum format,
812 GLenum type,
813 const void * data);
814
[email protected]a93bb842010-02-16 23:03:47815 // Creates a ProgramInfo for the given program.
[email protected]ae51d192010-04-27 00:48:03816 void CreateProgramInfo(GLuint client_id, GLuint service_id) {
817 program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47818 }
819
[email protected]07f54fcc2009-12-22 02:46:30820 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03821 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50822 ProgramManager::ProgramInfo* info =
[email protected]ae51d192010-04-27 00:48:03823 program_manager()->GetProgramInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50824 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46825 }
[email protected]07f54fcc2009-12-22 02:46:30826
[email protected]6b8cf1a2010-05-06 16:13:58827 // Gets the program info for the given program. If it's not a program
828 // generates a GL error. Returns NULL if not program.
829 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
830 GLuint client_id, const char* function_name) {
831 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
832 if (!info) {
833 if (GetShaderInfo(client_id)) {
834 SetGLError(GL_INVALID_OPERATION,
835 (std::string(function_name) +
836 ": shader passed for program").c_str());
837 } else {
838 SetGLError(GL_INVALID_VALUE,
839 (std::string(function_name) + ": unknown program").c_str());
840 }
841 }
842 return info;
843 }
844
845
[email protected]07f54fcc2009-12-22 02:46:30846 // Deletes the program info for the given program.
[email protected]ae51d192010-04-27 00:48:03847 void RemoveProgramInfo(GLuint client_id) {
848 program_manager()->RemoveProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46849 }
[email protected]07f54fcc2009-12-22 02:46:30850
[email protected]45bf5152010-02-12 00:11:31851 // Creates a ShaderInfo for the given shader.
[email protected]7cea56d92010-04-28 17:21:38852 void CreateShaderInfo(GLuint client_id,
853 GLuint service_id,
854 GLenum shader_type) {
855 shader_manager()->CreateShaderInfo(client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31856 }
857
858 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03859 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
860 ShaderManager::ShaderInfo* info =
861 shader_manager()->GetShaderInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50862 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]45bf5152010-02-12 00:11:31863 }
864
[email protected]6b8cf1a2010-05-06 16:13:58865 // Gets the shader info for the given shader. If it's not a shader generates a
866 // GL error. Returns NULL if not shader.
867 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
868 GLuint client_id, const char* function_name) {
869 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
870 if (!info) {
871 if (GetProgramInfo(client_id)) {
872 SetGLError(
873 GL_INVALID_OPERATION,
874 (std::string(function_name) +
875 ": program passed for shader").c_str());
876 } else {
877 SetGLError(GL_INVALID_VALUE,
878 (std::string(function_name) + ": unknown shader").c_str());
879 }
880 }
881 return info;
882 }
883
[email protected]45bf5152010-02-12 00:11:31884 // Deletes the shader info for the given shader.
[email protected]ae51d192010-04-27 00:48:03885 void RemoveShaderInfo(GLuint client_id) {
886 shader_manager()->RemoveShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31887 }
888
[email protected]a93bb842010-02-16 23:03:47889 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03890 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
891 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47892 }
893
[email protected]07f54fcc2009-12-22 02:46:30894 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03895 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
896 BufferManager::BufferInfo* info =
897 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50898 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46899 }
[email protected]07f54fcc2009-12-22 02:46:30900
[email protected]a93bb842010-02-16 23:03:47901 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
902 // on glDeleteBuffers so we can make sure the user does not try to render
903 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03904 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47905
[email protected]a25fa872010-03-25 02:57:58906 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03907 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
908 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58909 }
910
911 // Gets the framebuffer info for the given framebuffer.
912 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03913 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58914 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03915 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58916 return (info && !info->IsDeleted()) ? info : NULL;
917 }
918
919 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03920 void RemoveFramebufferInfo(GLuint client_id) {
921 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58922 }
923
924 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03925 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
926 return renderbuffer_manager()->CreateRenderbufferInfo(
927 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58928 }
929
930 // Gets the renderbuffer info for the given renderbuffer.
931 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03932 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58933 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03934 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58935 return (info && !info->IsDeleted()) ? info : NULL;
936 }
937
938 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03939 void RemoveRenderbufferInfo(GLuint client_id) {
940 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58941 }
942
[email protected]558847a2010-03-24 07:02:54943 error::Error GetAttribLocationHelper(
944 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
945 const std::string& name_str);
946
947 error::Error GetUniformLocationHelper(
948 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
949 const std::string& name_str);
950
[email protected]3916c97e2010-02-25 03:20:50951 // Helper for glShaderSource.
952 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03953 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30954
[email protected]3a2e7c7b2010-08-06 01:12:28955 // Clears any uncleared render buffers attached to the given frame buffer.
[email protected]8e3e0662010-08-23 18:46:30956 void ClearUnclearedRenderbuffers(
957 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28958
[email protected]c007aa02010-09-02 22:22:40959 // Restore all GL state that affects clearing.
960 void RestoreClearState();
961
[email protected]3a2e7c7b2010-08-06 01:12:28962 // Remembers the state of some capabilities.
963 void SetCapabilityState(GLenum cap, bool enabled);
964
[email protected]939e7362010-05-13 20:49:10965 // Checks if the current program exists and is valid. If not generates the
966 // appropriate GL error. Returns true if the current program is in a usable
967 // state.
968 bool CheckCurrentProgram(const char* function_name);
969
970 // Checks if the current program exists and is valid and that location is not
971 // -1. If the current program is not valid generates the appropriate GL
972 // error. Returns true if the current program is in a usable state and
973 // location is not -1.
974 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
975
976 // Gets the type of a uniform for a location in the current program. Sets GL
977 // errors if the current program is not valid. Returns true if the current
978 // program is valid and the location exists.
979 bool GetUniformTypeByLocation(
980 GLint location, const char* function_name, GLenum* type);
981
[email protected]b273e432010-04-12 17:23:58982 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
983 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
984
[email protected]96449d2c2009-11-25 00:01:32985 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03986 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32987
988 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03989 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32990
[email protected]3916c97e2010-02-25 03:20:50991 // Wrapper for glActiveTexture
992 void DoActiveTexture(GLenum texture_unit);
993
[email protected]ae51d192010-04-27 00:48:03994 // Wrapper for glAttachShader
995 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
996
[email protected]96449d2c2009-11-25 00:01:32997 // Wrapper for glBindBuffer since we need to track the current targets.
998 void DoBindBuffer(GLenum target, GLuint buffer);
999
[email protected]86093972010-03-11 00:13:561000 // Wrapper for glBindFramebuffer since we need to track the current targets.
1001 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1002
1003 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1004 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1005
[email protected]a93bb842010-02-16 23:03:471006 // Wrapper for glBindTexture since we need to track the current targets.
1007 void DoBindTexture(GLenum target, GLuint texture);
1008
[email protected]8e3e0662010-08-23 18:46:301009 // Wrapper for glBlitFramebufferEXT.
1010 void DoBlitFramebufferEXT(
1011 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1012 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1013 GLbitfield mask, GLenum filter);
1014
[email protected]36cef8ce2010-03-16 07:34:451015 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111016 void DoBufferData(
1017 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1018
[email protected]36cef8ce2010-03-16 07:34:451019 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111020 void DoBufferSubData(
1021 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1022
[email protected]36cef8ce2010-03-16 07:34:451023 // Wrapper for glCheckFramebufferStatus
1024 GLenum DoCheckFramebufferStatus(GLenum target);
1025
[email protected]3a2e7c7b2010-08-06 01:12:281026 // Wrappers for clear and mask settings functions.
1027 void DoClearColor(
1028 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1029 void DoClearDepthf(GLclampf depth);
1030 void DoClearStencil(GLint s);
1031 void DoColorMask(
1032 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1033 void DoDepthMask(GLboolean depth);
1034 void DoStencilMask(GLuint mask);
1035 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1036
[email protected]45bf5152010-02-12 00:11:311037 // Wrapper for glCompileShader.
1038 void DoCompileShader(GLuint shader);
1039
[email protected]066849e32010-05-03 19:14:101040 // Helper for DeleteSharedIds commands.
1041 void DoDeleteSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
1042
[email protected]ae51d192010-04-27 00:48:031043 // Wrapper for glDetachShader
1044 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1045
[email protected]07f54fcc2009-12-22 02:46:301046 // Wrapper for glDrawArrays.
1047 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
1048
[email protected]3a2e7c7b2010-08-06 01:12:281049 // Wrapper for glDisable
1050 void DoDisable(GLenum cap);
1051
[email protected]07f54fcc2009-12-22 02:46:301052 // Wrapper for glDisableVertexAttribArray.
1053 void DoDisableVertexAttribArray(GLuint index);
1054
[email protected]3a2e7c7b2010-08-06 01:12:281055 // Wrapper for glEnable
1056 void DoEnable(GLenum cap);
1057
[email protected]07f54fcc2009-12-22 02:46:301058 // Wrapper for glEnableVertexAttribArray.
1059 void DoEnableVertexAttribArray(GLuint index);
1060
[email protected]36cef8ce2010-03-16 07:34:451061 // Wrapper for glFramebufferRenderbufffer.
1062 void DoFramebufferRenderbuffer(
1063 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1064 GLuint renderbuffer);
1065
1066 // Wrapper for glFramebufferTexture2D.
1067 void DoFramebufferTexture2D(
1068 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1069 GLint level);
1070
[email protected]a93bb842010-02-16 23:03:471071 // Wrapper for glGenerateMipmap
1072 void DoGenerateMipmap(GLenum target);
1073
[email protected]066849e32010-05-03 19:14:101074 // Helper for GenSharedIds commands.
1075 void DoGenSharedIds(
1076 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1077
[email protected]b273e432010-04-12 17:23:581078 // Wrapper for DoGetBooleanv.
1079 void DoGetBooleanv(GLenum pname, GLboolean* params);
1080
1081 // Wrapper for DoGetFloatv.
1082 void DoGetFloatv(GLenum pname, GLfloat* params);
1083
[email protected]36cef8ce2010-03-16 07:34:451084 // Wrapper for glGetFramebufferAttachmentParameteriv.
1085 void DoGetFramebufferAttachmentParameteriv(
1086 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1087
[email protected]a0c3e972010-04-21 00:49:131088 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581089 void DoGetIntegerv(GLenum pname, GLint* params);
1090
[email protected]29a9eb52010-04-13 09:04:231091 // Gets the max value in a range in a buffer.
1092 GLuint DoGetMaxValueInBuffer(
1093 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1094
[email protected]a0c3e972010-04-21 00:49:131095 // Wrapper for glGetProgramiv.
1096 void DoGetProgramiv(
1097 GLuint program_id, GLenum pname, GLint* params);
1098
[email protected]36cef8ce2010-03-16 07:34:451099 // Wrapper for glRenderbufferParameteriv.
1100 void DoGetRenderbufferParameteriv(
1101 GLenum target, GLenum pname, GLint* params);
1102
[email protected]ddd968b82010-03-02 00:44:291103 // Wrapper for glGetShaderiv
1104 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1105
[email protected]b1122982010-05-17 23:04:241106 // Wrappers for glGetVertexAttrib.
1107 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1108 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1109
[email protected]1958e0e2010-04-22 05:17:151110 // Wrappers for glIsXXX functions.
1111 bool DoIsBuffer(GLuint client_id);
1112 bool DoIsFramebuffer(GLuint client_id);
1113 bool DoIsProgram(GLuint client_id);
1114 bool DoIsRenderbuffer(GLuint client_id);
1115 bool DoIsShader(GLuint client_id);
1116 bool DoIsTexture(GLuint client_id);
1117
[email protected]07f54fcc2009-12-22 02:46:301118 // Wrapper for glLinkProgram
1119 void DoLinkProgram(GLuint program);
1120
[email protected]066849e32010-05-03 19:14:101121 // Helper for RegisterSharedIds.
1122 void DoRegisterSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
1123
[email protected]36cef8ce2010-03-16 07:34:451124 // Wrapper for glRenderbufferStorage.
1125 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031126 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451127
[email protected]8e3e0662010-08-23 18:46:301128 // Wrapper for glRenderbufferStorageMultisampleEXT.
1129 void DoRenderbufferStorageMultisample(
1130 GLenum target, GLsizei samples, GLenum internalformat,
1131 GLsizei width, GLsizei height);
1132
[email protected]b273e432010-04-12 17:23:581133 // Wrapper for glReleaseShaderCompiler.
1134 void DoReleaseShaderCompiler() { }
1135
[email protected]3916c97e2010-02-25 03:20:501136 // Wrappers for glTexParameter functions.
1137 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1138 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1139 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1140 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1141
1142 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1143 // spec only these 2 functions can be used to set sampler uniforms.
1144 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101145 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
1146
1147 // Wrappers for glUniformfv because some drivers don't correctly accept
1148 // bool uniforms.
1149 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1150 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1151 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1152 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501153
[email protected]b1122982010-05-17 23:04:241154 // Wrappers for glVertexAttrib??
1155 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1156 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1157 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1158 void DoVertexAttrib4f(
1159 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1160 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1161 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1162 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1163 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1164
[email protected]07f54fcc2009-12-22 02:46:301165 // Wrapper for glUseProgram
1166 void DoUseProgram(GLuint program);
1167
[email protected]ae51d192010-04-27 00:48:031168 // Wrapper for glValidateProgram.
1169 void DoValidateProgram(GLuint program_client_id);
1170
[email protected]c007aa02010-09-02 22:22:401171 void DoCopyTextureToParentTexture(GLuint client_texture_id,
1172 GLuint parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:561173
[email protected]4e8a5b122010-05-08 22:00:101174 // Gets the number of values that will be returned by glGetXXX. Returns
1175 // false if pname is unknown.
1176 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1177
[email protected]96449d2c2009-11-25 00:01:321178 // Gets the GLError through our wrapper.
1179 GLenum GetGLError();
1180
1181 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:291182 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:321183
[email protected]07f54fcc2009-12-22 02:46:301184 // Copies the real GL errors to the wrapper. This is so we can
1185 // make sure there are no native GL errors before calling some GL function
1186 // so that on return we know any error generated was for that specific
1187 // command.
1188 void CopyRealGLErrorsToWrapper();
1189
[email protected]6217d392010-03-25 22:08:351190 // Clear all real GL errors. This is to prevent the client from seeing any
1191 // errors caused by GL calls that it was not responsible for issuing.
1192 void ClearRealGLErrors();
1193
[email protected]07f54fcc2009-12-22 02:46:301194 // Checks if the current program and vertex attributes are valid for drawing.
1195 bool IsDrawValid(GLuint max_vertex_accessed);
1196
[email protected]b1122982010-05-17 23:04:241197 // Returns true if attrib0 was simulated.
1198 bool SimulateAttrib0(GLuint max_vertex_accessed);
1199 void RestoreStateForSimulatedAttrib0();
1200
[email protected]ef526492010-06-02 23:12:251201 // Returns true if textures were set.
1202 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501203 void RestoreStateForNonRenderableTextures();
1204
[email protected]07f54fcc2009-12-22 02:46:301205 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501206 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301207 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501208 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1209 bound_array_buffer_ : bound_element_array_buffer_;
1210 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301211 }
1212
[email protected]a93bb842010-02-16 23:03:471213 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501214 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1215 TextureUnit& unit = texture_units_[active_texture_unit_];
1216 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471217 switch (target) {
1218 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501219 info = unit.bound_texture_2d;
1220 break;
[email protected]a93bb842010-02-16 23:03:471221 case GL_TEXTURE_CUBE_MAP:
1222 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1223 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1224 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1225 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1226 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1227 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501228 info = unit.bound_texture_cube_map;
1229 break;
[email protected]1aef98132010-02-23 18:00:071230 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1231 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1232 // because |texture_| is used by the FBO rendering mechanism for readback
1233 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471234 default:
1235 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501236 return NULL;
[email protected]a93bb842010-02-16 23:03:471237 }
[email protected]3916c97e2010-02-25 03:20:501238 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471239 }
1240
[email protected]8e3e0662010-08-23 18:46:301241 // Gets the framebuffer info for a particular target.
1242 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1243 GLenum target) {
1244 FramebufferManager::FramebufferInfo* info = NULL;
1245 switch (target) {
1246 case GL_FRAMEBUFFER:
1247 case GL_DRAW_FRAMEBUFFER:
1248 info = bound_draw_framebuffer_;
1249 break;
1250 case GL_READ_FRAMEBUFFER:
1251 info = bound_read_framebuffer_;
1252 break;
1253 default:
1254 NOTREACHED();
1255 break;
1256 }
1257 return (info && !info->IsDeleted()) ? info : NULL;
1258 }
1259
[email protected]f7b85372010-02-03 01:11:371260 // Validates the program and location for a glGetUniform call and returns
1261 // a SizeResult setup to receive the result. Returns true if glGetUniform
1262 // should be called.
1263 bool GetUniformSetup(
1264 GLuint program, GLint location,
1265 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101266 error::Error* error, GLuint* service_id, void** result,
1267 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371268
[email protected]96449d2c2009-11-25 00:01:321269 // Generate a member function prototype for each command in an automated and
1270 // typesafe way.
1271 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141272 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191273 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321274 const gles2::name& args); \
1275
1276 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1277
1278 #undef GLES2_CMD_OP
1279
[email protected]2f2d7042010-04-14 21:45:581280 // The GL context this decoder renders to on behalf of the client.
[email protected]66791e382010-07-14 20:48:301281 scoped_ptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021282
[email protected]a3ded6d2010-10-19 06:44:391283 // The ContextGroup for this decoder uses to track resources.
1284 ContextGroup::Ref group_;
1285
[email protected]6217d392010-03-25 22:08:351286 // A parent decoder can access this decoders saved offscreen frame buffer.
1287 // The parent pointer is reset if the parent is destroyed.
1288 base::WeakPtr<GLES2DecoderImpl> parent_;
1289
1290 // Width and height to which an offscreen frame buffer should be resized on
1291 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021292 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351293
[email protected]34ff8b0c2010-10-01 20:06:021294 // Current width and height of the offscreen frame buffer.
1295 gfx::Size offscreen_size_;
1296
[email protected]96449d2c2009-11-25 00:01:321297 // Current GL error bits.
1298 uint32 error_bits_;
1299
[email protected]96449d2c2009-11-25 00:01:321300 // Util to help with GL.
1301 GLES2Util util_;
1302
1303 // pack alignment as last set by glPixelStorei
1304 GLint pack_alignment_;
1305
1306 // unpack alignment as last set by glPixelStorei
1307 GLint unpack_alignment_;
1308
1309 // The currently bound array buffer. If this is 0 it is illegal to call
1310 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501311 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321312
1313 // The currently bound element array buffer. If this is 0 it is illegal
1314 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501315 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301316
[email protected]f39f4b3f2010-05-12 17:04:081317 // Class that manages vertex attribs.
1318 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301319
[email protected]b1122982010-05-17 23:04:241320 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1321 GLuint attrib_0_buffer_id_;
1322
1323 // The value currently in attrib_0.
1324 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1325
1326 // The size of attrib 0.
1327 GLsizei attrib_0_size_;
1328
[email protected]3916c97e2010-02-25 03:20:501329 // Current active texture by 0 - n index.
1330 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1331 // be 2.
1332 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301333
[email protected]3916c97e2010-02-25 03:20:501334 // Which textures are bound to texture units through glActiveTexture.
1335 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471336
[email protected]3a2e7c7b2010-08-06 01:12:281337 // state saved for clearing so we can clear render buffers and then
1338 // restore to these values.
1339 GLclampf clear_red_;
1340 GLclampf clear_green_;
1341 GLclampf clear_blue_;
1342 GLclampf clear_alpha_;
1343 GLboolean mask_red_;
1344 GLboolean mask_green_;
1345 GLboolean mask_blue_;
1346 GLboolean mask_alpha_;
1347 GLint clear_stencil_;
1348 GLuint mask_stencil_front_;
1349 GLuint mask_stencil_back_;
1350 GLclampf clear_depth_;
1351 GLboolean mask_depth_;
1352 bool enable_scissor_test_;
1353
[email protected]1d32bc82010-01-13 22:06:461354 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501355 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301356
[email protected]8e3e0662010-08-23 18:46:301357 // The currently bound framebuffers
1358 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1359 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561360
1361 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081362 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561363
[email protected]b9363b22010-06-09 22:06:151364 // The offscreen frame buffer that the client renders to. With EGL, the
1365 // depth and stencil buffers are separate. With regular GL there is a single
1366 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1367 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351368 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1369 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021370 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151371 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1372 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021373 GLenum offscreen_target_color_format_;
1374 GLenum offscreen_target_depth_format_;
1375 GLenum offscreen_target_stencil_format_;
1376 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351377
[email protected]a3a93e7b2010-08-28 00:48:561378 GLuint copy_texture_to_parent_texture_fb_;
1379
[email protected]34ff8b0c2010-10-01 20:06:021380 // The copy that is saved when SwapBuffers is called. It is also
1381 // used as the destination for multi-sample resolves.
1382 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351383 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]97872062010-11-03 19:07:051384 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351385
[email protected]43f28f832010-02-03 02:28:481386 scoped_ptr<Callback0::Type> swap_buffers_callback_;
1387
[email protected]8eee29c2010-04-29 03:38:291388 // The last error message set.
1389 std::string last_error_;
1390
[email protected]a3a93e7b2010-08-28 00:48:561391 // The current decoder error.
1392 error::Error current_decoder_error_;
1393
[email protected]b1d2dcb2010-05-17 19:24:181394 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451395 scoped_ptr<ShaderTranslator> vertex_translator_;
1396 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181397
[email protected]915a59a12010-09-30 21:29:111398 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051399 const Validators* validators_;
[email protected]915a59a12010-09-30 21:29:111400 FeatureInfo* feature_info_;
[email protected]9438b012010-06-15 22:55:051401
[email protected]96449d2c2009-11-25 00:01:321402 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1403};
1404
[email protected]6217d392010-03-25 22:08:351405ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1406 : decoder_(decoder) {
1407 decoder_->CopyRealGLErrorsToWrapper();
1408}
1409
1410ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1411 decoder_->ClearRealGLErrors();
1412}
1413
1414ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1415 GLuint id)
1416 : decoder_(decoder) {
1417 ScopedGLErrorSuppressor suppressor(decoder_);
1418
1419 // TODO(apatrick): Check if there are any other states that need to be reset
1420 // before binding a new texture.
1421 glActiveTexture(GL_TEXTURE0);
1422 glBindTexture(GL_TEXTURE_2D, id);
1423}
1424
1425ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1426 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301427 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351428}
1429
1430ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1431 GLuint id)
1432 : decoder_(decoder) {
1433 ScopedGLErrorSuppressor suppressor(decoder_);
1434 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1435}
1436
1437ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1438 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301439 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351440}
1441
1442ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1443 GLuint id)
1444 : decoder_(decoder) {
1445 ScopedGLErrorSuppressor suppressor(decoder_);
1446 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1447}
1448
1449ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1450 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301451 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351452}
1453
[email protected]34ff8b0c2010-10-01 20:06:021454ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1455 GLES2DecoderImpl* decoder) : decoder_(decoder) {
1456 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1457 decoder_->IsOffscreenBufferMultisampled() &&
1458 !decoder_->bound_read_framebuffer_.get());
1459 if (!resolve_and_bind_)
1460 return;
1461
1462 ScopedGLErrorSuppressor suppressor(decoder_);
1463 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1464 decoder_->offscreen_target_frame_buffer_->id());
1465 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT,
1466 decoder_->offscreen_saved_frame_buffer_->id());
1467 const int width = decoder_->offscreen_size_.width();
1468 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181469 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021470 if (IsAngle()) {
1471 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1472 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1473 } else {
1474 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1475 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1476 }
1477 glBindFramebufferEXT(GL_FRAMEBUFFER,
1478 decoder_->offscreen_saved_frame_buffer_->id());
1479}
1480
1481ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1482 if (!resolve_and_bind_)
1483 return;
1484
1485 ScopedGLErrorSuppressor suppressor(decoder_);
1486 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181487 if (decoder_->enable_scissor_test_) {
1488 glEnable(GL_SCISSOR_TEST);
1489 }
[email protected]34ff8b0c2010-10-01 20:06:021490}
1491
[email protected]6217d392010-03-25 22:08:351492Texture::Texture(GLES2DecoderImpl* decoder)
1493 : decoder_(decoder),
1494 id_(0) {
1495}
1496
1497Texture::~Texture() {
1498 // This does not destroy the render texture because that would require that
1499 // the associated GL context was current. Just check that it was explicitly
1500 // destroyed.
1501 DCHECK_EQ(id_, 0u);
1502}
1503
1504void Texture::Create() {
1505 ScopedGLErrorSuppressor suppressor(decoder_);
1506 Destroy();
1507 glGenTextures(1, &id_);
1508}
1509
[email protected]34ff8b0c2010-10-01 20:06:021510bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351511 DCHECK_NE(id_, 0u);
1512 ScopedGLErrorSuppressor suppressor(decoder_);
1513 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]8c515f82010-11-09 03:40:041514 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1515 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1516 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1517 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351518
1519 glTexImage2D(GL_TEXTURE_2D,
1520 0, // mip level
[email protected]34ff8b0c2010-10-01 20:06:021521 format,
[email protected]6217d392010-03-25 22:08:351522 size.width(),
1523 size.height(),
1524 0, // border
[email protected]34ff8b0c2010-10-01 20:06:021525 format,
[email protected]6217d392010-03-25 22:08:351526 GL_UNSIGNED_BYTE,
1527 NULL);
1528
[email protected]d37231fa2010-04-09 21:16:021529 size_ = size;
1530
[email protected]6217d392010-03-25 22:08:351531 return glGetError() == GL_NO_ERROR;
1532}
1533
1534void Texture::Copy(const gfx::Size& size) {
1535 DCHECK_NE(id_, 0u);
1536 ScopedGLErrorSuppressor suppressor(decoder_);
1537 ScopedTexture2DBinder binder(decoder_, id_);
1538 glCopyTexImage2D(GL_TEXTURE_2D,
1539 0, // level
1540 GL_RGBA,
1541 0, 0,
1542 size.width(),
1543 size.height(),
1544 0); // border
1545}
1546
1547void Texture::Destroy() {
1548 if (id_ != 0) {
1549 ScopedGLErrorSuppressor suppressor(decoder_);
1550 glDeleteTextures(1, &id_);
1551 id_ = 0;
1552 }
1553}
1554
[email protected]97872062010-11-03 19:07:051555void Texture::Invalidate() {
1556 id_ = 0;
1557}
1558
[email protected]6217d392010-03-25 22:08:351559RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1560 : decoder_(decoder),
1561 id_(0) {
1562}
1563
1564RenderBuffer::~RenderBuffer() {
1565 // This does not destroy the render buffer because that would require that
1566 // the associated GL context was current. Just check that it was explicitly
1567 // destroyed.
1568 DCHECK_EQ(id_, 0u);
1569}
1570
1571void RenderBuffer::Create() {
1572 ScopedGLErrorSuppressor suppressor(decoder_);
1573 Destroy();
1574 glGenRenderbuffersEXT(1, &id_);
1575}
1576
[email protected]34ff8b0c2010-10-01 20:06:021577bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1578 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351579 ScopedGLErrorSuppressor suppressor(decoder_);
1580 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021581 if (samples <= 1) {
1582 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1583 format,
1584 size.width(),
1585 size.height());
1586 } else {
1587 if (IsAngle()) {
1588 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1589 samples,
1590 format,
1591 size.width(),
1592 size.height());
1593 } else {
1594 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1595 samples,
1596 format,
1597 size.width(),
1598 size.height());
1599 }
1600 }
[email protected]6217d392010-03-25 22:08:351601 return glGetError() == GL_NO_ERROR;
1602}
1603
1604void RenderBuffer::Destroy() {
1605 if (id_ != 0) {
1606 ScopedGLErrorSuppressor suppressor(decoder_);
1607 glDeleteRenderbuffersEXT(1, &id_);
1608 id_ = 0;
1609 }
1610}
1611
[email protected]97872062010-11-03 19:07:051612void RenderBuffer::Invalidate() {
1613 id_ = 0;
1614}
1615
[email protected]6217d392010-03-25 22:08:351616FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1617 : decoder_(decoder),
1618 id_(0) {
1619}
1620
1621FrameBuffer::~FrameBuffer() {
1622 // This does not destroy the frame buffer because that would require that
1623 // the associated GL context was current. Just check that it was explicitly
1624 // destroyed.
1625 DCHECK_EQ(id_, 0u);
1626}
1627
1628void FrameBuffer::Create() {
1629 ScopedGLErrorSuppressor suppressor(decoder_);
1630 Destroy();
1631 glGenFramebuffersEXT(1, &id_);
1632}
1633
1634void FrameBuffer::AttachRenderTexture(Texture* texture) {
1635 DCHECK_NE(id_, 0u);
1636 ScopedGLErrorSuppressor suppressor(decoder_);
1637 ScopedFrameBufferBinder binder(decoder_, id_);
1638 GLuint attach_id = texture ? texture->id() : 0;
1639 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1640 GL_COLOR_ATTACHMENT0,
1641 GL_TEXTURE_2D,
1642 attach_id,
1643 0);
1644}
1645
[email protected]b9363b22010-06-09 22:06:151646void FrameBuffer::AttachRenderBuffer(GLenum target,
1647 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351648 DCHECK_NE(id_, 0u);
1649 ScopedGLErrorSuppressor suppressor(decoder_);
1650 ScopedFrameBufferBinder binder(decoder_, id_);
1651 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1652 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151653 target,
[email protected]6217d392010-03-25 22:08:351654 GL_RENDERBUFFER,
1655 attach_id);
1656}
1657
1658void FrameBuffer::Clear(GLbitfield buffers) {
1659 ScopedGLErrorSuppressor suppressor(decoder_);
1660 ScopedFrameBufferBinder binder(decoder_, id_);
1661 glClear(buffers);
1662}
1663
1664void FrameBuffer::Destroy() {
1665 if (id_ != 0) {
1666 ScopedGLErrorSuppressor suppressor(decoder_);
1667 glDeleteFramebuffersEXT(1, &id_);
1668 id_ = 0;
1669 }
1670}
1671
[email protected]97872062010-11-03 19:07:051672void FrameBuffer::Invalidate() {
1673 id_ = 0;
1674}
1675
[email protected]6217d392010-03-25 22:08:351676GLenum FrameBuffer::CheckStatus() {
1677 DCHECK_NE(id_, 0u);
1678 ScopedGLErrorSuppressor suppressor(decoder_);
1679 ScopedFrameBufferBinder binder(decoder_, id_);
1680 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1681}
1682
[email protected]3916c97e2010-02-25 03:20:501683GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1684 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321685}
1686
[email protected]3916c97e2010-02-25 03:20:501687GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391688 : GLES2Decoder(),
1689 group_(ContextGroup::Ref(group ? group : new ContextGroup())),
[email protected]96449d2c2009-11-25 00:01:321690 error_bits_(0),
1691 util_(0), // TODO(gman): Set to actual num compress texture formats.
1692 pack_alignment_(4),
1693 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241694 attrib_0_buffer_id_(0),
1695 attrib_0_size_(0),
[email protected]3916c97e2010-02-25 03:20:501696 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281697 clear_red_(0),
1698 clear_green_(0),
1699 clear_blue_(0),
1700 clear_alpha_(0),
1701 mask_red_(true),
1702 mask_green_(true),
1703 mask_blue_(true),
1704 mask_alpha_(true),
1705 clear_stencil_(0),
1706 mask_stencil_front_(-1),
1707 mask_stencil_back_(-1),
1708 clear_depth_(1.0f),
1709 mask_depth_(true),
1710 enable_scissor_test_(false),
[email protected]34ff8b0c2010-10-01 20:06:021711 offscreen_target_color_format_(0),
1712 offscreen_target_depth_format_(0),
1713 offscreen_target_stencil_format_(0),
1714 offscreen_target_samples_(0),
[email protected]97872062010-11-03 19:07:051715 offscreen_saved_color_format_(0),
[email protected]a3a93e7b2010-08-28 00:48:561716 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051717 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111718 validators_(group_->feature_info()->validators()),
[email protected]34ff8b0c2010-10-01 20:06:021719 feature_info_(group_->feature_info()) {
[email protected]b1122982010-05-17 23:04:241720 attrib_0_value_.v[0] = 0.0f;
1721 attrib_0_value_.v[1] = 0.0f;
1722 attrib_0_value_.v[2] = 0.0f;
1723 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151724
1725 // The shader translator is not needed for EGL because it already uses the
1726 // GLSL ES syntax. It is translated for the unit tests because
1727 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the empty
1728 // string to CompileShader and this is not a valid shader. TODO(apatrick):
1729 // fix this test.
1730 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ||
1731 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1732 use_shader_translator_ = false;
1733 }
[email protected]96449d2c2009-11-25 00:01:321734}
1735
[email protected]5a6db6c2010-04-22 18:32:061736bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:351737 const gfx::Size& size,
[email protected]a3ded6d2010-10-19 06:44:391738 const char* allowed_extensions,
[email protected]34ff8b0c2010-10-01 20:06:021739 const std::vector<int32>& attribs,
[email protected]d37231fa2010-04-09 21:16:021740 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:351741 uint32 parent_client_texture_id) {
[email protected]4bedba72010-04-20 22:08:541742 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301743 DCHECK(!context_.get());
1744
1745 // Take ownership of the GLContext.
1746 context_.reset(context);
[email protected]d37231fa2010-04-09 21:16:021747
[email protected]6217d392010-03-25 22:08:351748 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021749 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351750 if (parent)
1751 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1752
[email protected]246a70452010-03-05 21:53:501753 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011754 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1755 << "MakeCurrent failed.";
[email protected]246a70452010-03-05 21:53:501756 Destroy();
1757 return false;
[email protected]eb54a562010-01-20 21:55:181758 }
1759
[email protected]a3ded6d2010-10-19 06:44:391760 if (!group_->Initialize(allowed_extensions)) {
1761 LOG(ERROR) << "GPUProcessor::InitializeCommon failed because group "
1762 << "failed to initialize.";
1763 Destroy();
1764 }
1765
[email protected]246a70452010-03-05 21:53:501766 CHECK_GL_ERROR();
1767
[email protected]f39f4b3f2010-05-12 17:04:081768 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321769
[email protected]b1122982010-05-17 23:04:241770 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1771 // OpenGL ES 2.0 does not have this issue.
1772 glEnableVertexAttribArray(0);
1773 glGenBuffersARB(1, &attrib_0_buffer_id_);
1774 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1775 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1776 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]f39f4b3f2010-05-12 17:04:081777
[email protected]246a70452010-03-05 21:53:501778 texture_units_.reset(
1779 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151780 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491781 glActiveTexture(GL_TEXTURE0 + tt);
1782 // Do cube map first because we want the last bind to be 2D.
1783 TextureManager::TextureInfo* info =
[email protected]1958e0e2010-04-22 05:17:151784 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491785 texture_units_[tt].bound_texture_cube_map = info;
1786 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1787 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1788 texture_units_[tt].bound_texture_2d = info;
1789 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151790 }
[email protected]00f893d2010-08-24 18:55:491791 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501792 CHECK_GL_ERROR();
1793
[email protected]d37231fa2010-04-09 21:16:021794 if (context_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:021795 ContextCreationAttribParser attrib_parser;
1796 if (!attrib_parser.Parse(attribs))
1797 return false;
1798
1799 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:541800 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:021801 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
1802 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:431803 // max_sample_count must be initialized to a sane value. If
1804 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
1805 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:021806 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
1807 offscreen_target_samples_ = std::min(attrib_parser.samples_,
1808 max_sample_count);
1809 } else {
1810 offscreen_target_samples_ = 1;
1811 }
1812
1813 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1814 const bool rgb8_supported =
1815 context_->HasExtension("GL_OES_rgb8_rgba8");
1816 // The only available default render buffer formats in GLES2 have very
1817 // little precision. Don't enable multisampling unless 8-bit render
1818 // buffer formats are available--instead fall back to 8-bit textures.
1819 if (rgb8_supported && offscreen_target_samples_ > 1) {
1820 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1821 GL_RGBA8 : GL_RGB8;
1822 } else {
1823 offscreen_target_samples_ = 1;
1824 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1825 GL_RGBA : GL_RGB;
1826 }
1827
1828 // ANGLE only supports packed depth/stencil formats, so use it if it is
1829 // available.
1830 const bool depth24_stencil8_supported =
1831 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271832 VLOG(1) << "GL_OES_packed_depth_stencil "
1833 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:001834 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1835 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021836 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1837 offscreen_target_stencil_format_ = 0;
1838 } else {
1839 // It may be the case that this depth/stencil combination is not
1840 // supported, but this will be checked later by CheckFramebufferStatus.
1841 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1842 GL_DEPTH_COMPONENT16 : 0;
1843 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1844 GL_STENCIL_INDEX8 : 0;
1845 }
1846 } else {
1847 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1848 GL_RGBA : GL_RGB;
1849
1850 // If depth is requested at all, use the packed depth stencil format if
1851 // it's available, as some desktop GL drivers don't support any non-packed
1852 // formats for depth attachments.
1853 const bool depth24_stencil8_supported =
1854 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271855 VLOG(1) << "GL_EXT_packed_depth_stencil "
1856 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:021857
[email protected]71ee3642010-10-14 18:08:001858 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1859 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021860 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1861 offscreen_target_stencil_format_ = 0;
1862 } else {
1863 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1864 GL_DEPTH_COMPONENT : 0;
1865 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1866 GL_STENCIL_INDEX : 0;
1867 }
1868 }
1869
[email protected]97872062010-11-03 19:07:051870 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
1871 GL_RGBA : GL_RGB;
1872
[email protected]6217d392010-03-25 22:08:351873 // Create the target frame buffer. This is the one that the client renders
1874 // directly to.
1875 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1876 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021877 // Due to GLES2 format limitations, either the color texture (for
1878 // non-multisampling) or the color render buffer (for multisampling) will be
1879 // attached to the offscreen frame buffer. The render buffer has more
1880 // limited formats available to it, but the texture can't do multisampling.
1881 if (IsOffscreenBufferMultisampled()) {
1882 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
1883 offscreen_target_color_render_buffer_->Create();
1884 } else {
1885 offscreen_target_color_texture_.reset(new Texture(this));
1886 offscreen_target_color_texture_->Create();
1887 }
1888 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151889 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021890 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151891 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:351892
1893 // Create the saved offscreen texture. The target frame buffer is copied
1894 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021895 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
1896 offscreen_saved_frame_buffer_->Create();
1897 //
[email protected]6217d392010-03-25 22:08:351898 offscreen_saved_color_texture_.reset(new Texture(this));
1899 offscreen_saved_color_texture_->Create();
1900
[email protected]6217d392010-03-25 22:08:351901 // Map the ID of the saved offscreen texture into the parent so that
1902 // it can reference it.
1903 if (parent_) {
1904 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]6217d392010-03-25 22:08:351905 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:031906 parent_->CreateTextureInfo(parent_client_texture_id, service_id);
[email protected]6217d392010-03-25 22:08:351907 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
1908 }
1909
1910 // Allocate the render buffers at their initial size and check the status
1911 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021912 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351913 if (!UpdateOffscreenFrameBufferSize()) {
[email protected]d0498742010-09-20 20:27:011914 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:351915 Destroy();
1916 return false;
1917 }
1918
1919 // Bind to the new default frame buffer (the offscreen target frame buffer).
1920 // This should now be associated with ID zero.
1921 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]a3a93e7b2010-08-28 00:48:561922
1923 glGenFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:351924 }
1925
[email protected]76a0ee102010-04-07 21:03:041926 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1927 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1928 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:371929 // mailing list archives. It also implicitly enables the desktop GL
1930 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
1931 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:151932 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1933 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:371934 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:151935 }
[email protected]de17df392010-04-23 21:09:411936
[email protected]f517cc842010-08-25 19:13:401937 if (use_shader_translator_) {
[email protected]a64c6e62010-10-06 20:06:011938 ShBuiltInResources resources;
1939 ShInitBuiltInResources(&resources);
[email protected]bf947d4652010-08-26 19:52:021940 resources.MaxVertexAttribs = group_->max_vertex_attribs();
1941 resources.MaxVertexUniformVectors =
[email protected]f517cc842010-08-25 19:13:401942 group_->max_vertex_uniform_vectors();
[email protected]bf947d4652010-08-26 19:52:021943 resources.MaxVaryingVectors = group_->max_varying_vectors();
1944 resources.MaxVertexTextureImageUnits =
[email protected]f517cc842010-08-25 19:13:401945 group_->max_vertex_texture_image_units();
[email protected]bf947d4652010-08-26 19:52:021946 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
1947 resources.MaxTextureImageUnits = group_->max_texture_image_units();
1948 resources.MaxFragmentUniformVectors =
[email protected]f517cc842010-08-25 19:13:401949 group_->max_fragment_uniform_vectors();
[email protected]bf947d4652010-08-26 19:52:021950 resources.MaxDrawBuffers = 1;
[email protected]9fcd3932010-09-17 22:00:461951 resources.OES_standard_derivatives =
[email protected]915a59a12010-09-30 21:29:111952 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
[email protected]a550584e2010-09-17 18:01:451953 vertex_translator_.reset(new ShaderTranslator);
[email protected]bc518752010-10-20 21:38:271954 ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ?
1955 SH_WEBGL_SPEC : SH_GLES2_SPEC;
1956 if (!vertex_translator_->Init(SH_VERTEX_SHADER, shader_spec, &resources)) {
[email protected]d0498742010-09-20 20:27:011957 LOG(ERROR) << "Could not initialize vertex shader translator.";
[email protected]f517cc842010-08-25 19:13:401958 Destroy();
1959 return false;
1960 }
[email protected]a550584e2010-09-17 18:01:451961 fragment_translator_.reset(new ShaderTranslator);
[email protected]bc518752010-10-20 21:38:271962 if (!fragment_translator_->Init(
1963 SH_FRAGMENT_SHADER, shader_spec, &resources)) {
[email protected]d0498742010-09-20 20:27:011964 LOG(ERROR) << "Could not initialize fragment shader translator.";
[email protected]f517cc842010-08-25 19:13:401965 Destroy();
1966 return false;
1967 }
[email protected]de17df392010-04-23 21:09:411968 }
[email protected]76a0ee102010-04-07 21:03:041969
[email protected]246a70452010-03-05 21:53:501970 return true;
[email protected]96449d2c2009-11-25 00:01:321971}
1972
[email protected]ae51d192010-04-27 00:48:031973bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471974 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031975 if (GetBufferInfo(client_ids[ii])) {
1976 return false;
1977 }
1978 }
1979 scoped_array<GLuint> service_ids(new GLuint[n]);
1980 glGenBuffersARB(n, service_ids.get());
1981 for (GLsizei ii = 0; ii < n; ++ii) {
1982 CreateBufferInfo(client_ids[ii], service_ids[ii]);
1983 }
1984 return true;
1985}
1986
1987bool GLES2DecoderImpl::GenFramebuffersHelper(
1988 GLsizei n, const GLuint* client_ids) {
1989 for (GLsizei ii = 0; ii < n; ++ii) {
1990 if (GetFramebufferInfo(client_ids[ii])) {
1991 return false;
1992 }
1993 }
1994 scoped_array<GLuint> service_ids(new GLuint[n]);
1995 glGenFramebuffersEXT(n, service_ids.get());
1996 for (GLsizei ii = 0; ii < n; ++ii) {
1997 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
1998 }
1999 return true;
2000}
2001
2002bool GLES2DecoderImpl::GenRenderbuffersHelper(
2003 GLsizei n, const GLuint* client_ids) {
2004 for (GLsizei ii = 0; ii < n; ++ii) {
2005 if (GetRenderbufferInfo(client_ids[ii])) {
2006 return false;
2007 }
2008 }
2009 scoped_array<GLuint> service_ids(new GLuint[n]);
2010 glGenRenderbuffersEXT(n, service_ids.get());
2011 for (GLsizei ii = 0; ii < n; ++ii) {
2012 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2013 }
2014 return true;
2015}
2016
2017bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2018 for (GLsizei ii = 0; ii < n; ++ii) {
2019 if (GetTextureInfo(client_ids[ii])) {
2020 return false;
2021 }
2022 }
2023 scoped_array<GLuint> service_ids(new GLuint[n]);
2024 glGenTextures(n, service_ids.get());
2025 for (GLsizei ii = 0; ii < n; ++ii) {
2026 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2027 }
2028 return true;
2029}
2030
2031void GLES2DecoderImpl::DeleteBuffersHelper(
2032 GLsizei n, const GLuint* client_ids) {
2033 for (GLsizei ii = 0; ii < n; ++ii) {
2034 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
2035 if (info) {
2036 GLuint service_id = info->service_id();
2037 glDeleteBuffersARB(1, &service_id);
2038 RemoveBufferInfo(client_ids[ii]);
2039 }
[email protected]a93bb842010-02-16 23:03:472040 }
[email protected]07f54fcc2009-12-22 02:46:302041}
2042
[email protected]ae51d192010-04-27 00:48:032043void GLES2DecoderImpl::DeleteFramebuffersHelper(
2044 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582045 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032046 FramebufferManager::FramebufferInfo* info =
2047 GetFramebufferInfo(client_ids[ii]);
2048 if (info) {
2049 GLuint service_id = info->service_id();
2050 glDeleteFramebuffersEXT(1, &service_id);
2051 RemoveFramebufferInfo(client_ids[ii]);
2052 }
[email protected]a25fa872010-03-25 02:57:582053 }
[email protected]07f54fcc2009-12-22 02:46:302054}
2055
[email protected]ae51d192010-04-27 00:48:032056void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2057 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582058 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032059 RenderbufferManager::RenderbufferInfo* info =
2060 GetRenderbufferInfo(client_ids[ii]);
2061 if (info) {
2062 GLuint service_id = info->service_id();
2063 glDeleteRenderbuffersEXT(1, &service_id);
2064 RemoveRenderbufferInfo(client_ids[ii]);
2065 }
[email protected]a25fa872010-03-25 02:57:582066 }
[email protected]07f54fcc2009-12-22 02:46:302067}
2068
[email protected]ae51d192010-04-27 00:48:032069void GLES2DecoderImpl::DeleteTexturesHelper(
2070 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472071 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032072 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
2073 if (info) {
2074 GLuint service_id = info->service_id();
2075 glDeleteTextures(1, &service_id);
2076 RemoveTextureInfo(client_ids[ii]);
2077 }
[email protected]a93bb842010-02-16 23:03:472078 }
[email protected]07f54fcc2009-12-22 02:46:302079}
2080
[email protected]43f28f832010-02-03 02:28:482081// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322082
[email protected]eb54a562010-01-20 21:55:182083bool GLES2DecoderImpl::MakeCurrent() {
[email protected]66791e382010-07-14 20:48:302084 return context_.get() ? context_->MakeCurrent() : false;
[email protected]eb54a562010-01-20 21:55:182085}
2086
[email protected]8e3e0662010-08-23 18:46:302087void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2088 glBindRenderbufferEXT(
2089 GL_RENDERBUFFER,
2090 bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
2091}
2092
2093static void RebindCurrentFramebuffer(
2094 GLenum target,
2095 FramebufferManager::FramebufferInfo* info,
2096 FrameBuffer* offscreen_frame_buffer) {
2097 GLuint framebuffer_id = info ? info->service_id() : 0;
2098 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2099 framebuffer_id = offscreen_frame_buffer->id();
2100 }
2101 glBindFramebufferEXT(target, framebuffer_id);
2102}
2103
2104void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]a3ded6d2010-10-19 06:44:392105 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302106 RebindCurrentFramebuffer(
2107 GL_FRAMEBUFFER,
2108 bound_draw_framebuffer_.get(),
2109 offscreen_target_frame_buffer_.get());
2110 } else {
2111 RebindCurrentFramebuffer(
2112 GL_READ_FRAMEBUFFER_EXT,
2113 bound_read_framebuffer_.get(),
2114 offscreen_target_frame_buffer_.get());
2115 RebindCurrentFramebuffer(
2116 GL_DRAW_FRAMEBUFFER_EXT,
2117 bound_draw_framebuffer_.get(),
2118 offscreen_target_frame_buffer_.get());
2119 }
2120}
2121
2122void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2123 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2124 GLuint last_id;
2125 if (info.bound_texture_2d) {
2126 last_id = info.bound_texture_2d->service_id();
2127 } else {
2128 last_id = 0;
2129 }
2130
2131 glBindTexture(GL_TEXTURE_2D, last_id);
2132 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2133}
2134
2135gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2136 if (bound_read_framebuffer_ != 0) {
[email protected]d37231fa2010-04-09 21:16:022137 int width = 0;
2138 int height = 0;
[email protected]246a70452010-03-05 21:53:502139
[email protected]a3ded6d2010-10-19 06:44:392140 GLenum target =
2141 feature_info_->feature_flags().chromium_framebuffer_multisample ?
2142 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
[email protected]8e3e0662010-08-23 18:46:302143
[email protected]d37231fa2010-04-09 21:16:022144 // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
2145 // stencil.
2146 GLint fb_type = 0;
2147 glGetFramebufferAttachmentParameterivEXT(
[email protected]8e3e0662010-08-23 18:46:302148 target,
[email protected]d37231fa2010-04-09 21:16:022149 GL_COLOR_ATTACHMENT0,
2150 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
2151 &fb_type);
2152 switch (fb_type) {
2153 case GL_RENDERBUFFER:
2154 {
2155 GLint renderbuffer_id = 0;
2156 glGetFramebufferAttachmentParameterivEXT(
[email protected]8e3e0662010-08-23 18:46:302157 target,
[email protected]d37231fa2010-04-09 21:16:022158 GL_COLOR_ATTACHMENT0,
2159 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
2160 &renderbuffer_id);
2161 if (renderbuffer_id != 0) {
2162 glGetRenderbufferParameterivEXT(
2163 GL_RENDERBUFFER,
2164 GL_RENDERBUFFER_WIDTH,
2165 &width);
2166 glGetRenderbufferParameterivEXT(
2167 GL_RENDERBUFFER,
2168 GL_RENDERBUFFER_HEIGHT,
2169 &height);
2170 }
2171 break;
2172 }
2173 case GL_TEXTURE:
2174 {
2175 GLint texture_id = 0;
2176 glGetFramebufferAttachmentParameterivEXT(
[email protected]8e3e0662010-08-23 18:46:302177 target,
[email protected]d37231fa2010-04-09 21:16:022178 GL_COLOR_ATTACHMENT0,
2179 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
2180 &texture_id);
2181 if (texture_id != 0) {
[email protected]ae51d192010-04-27 00:48:032182 GLuint client_id = 0;
2183 if (texture_manager()->GetClientId(texture_id, &client_id)) {
2184 TextureManager::TextureInfo* texture_info =
2185 GetTextureInfo(client_id);
2186 if (texture_info) {
2187 GLint level = 0;
2188 GLint face = 0;
2189 glGetFramebufferAttachmentParameterivEXT(
[email protected]8e3e0662010-08-23 18:46:302190 target,
[email protected]ae51d192010-04-27 00:48:032191 GL_COLOR_ATTACHMENT0,
2192 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
2193 &level);
2194 glGetFramebufferAttachmentParameterivEXT(
[email protected]8e3e0662010-08-23 18:46:302195 target,
[email protected]ae51d192010-04-27 00:48:032196 GL_COLOR_ATTACHMENT0,
2197 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
2198 &face);
2199 texture_info->GetLevelSize(
2200 face ? face : GL_TEXTURE_2D, level, &width, &height);
2201 }
[email protected]d37231fa2010-04-09 21:16:022202 }
2203 }
2204 break;
2205 }
2206 default:
2207 // unknown so assume width and height are zero.
2208 break;
[email protected]246a70452010-03-05 21:53:502209 }
2210
[email protected]d37231fa2010-04-09 21:16:022211 return gfx::Size(width, height);
[email protected]34ff8b0c2010-10-01 20:06:022212 } else if (offscreen_target_frame_buffer_.get()) {
2213 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352214 } else {
[email protected]d37231fa2010-04-09 21:16:022215 return context_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022216 }
[email protected]246a70452010-03-05 21:53:502217}
2218
[email protected]6217d392010-03-25 22:08:352219bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]34ff8b0c2010-10-01 20:06:022220 if (offscreen_size_ == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:352221 return true;
2222
[email protected]34ff8b0c2010-10-01 20:06:022223 offscreen_size_ = pending_offscreen_size_;
2224
[email protected]6217d392010-03-25 22:08:352225 // Reallocate the offscreen target buffers.
[email protected]34ff8b0c2010-10-01 20:06:022226 DCHECK(offscreen_target_color_format_);
2227 if (IsOffscreenBufferMultisampled()) {
2228 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2229 pending_offscreen_size_, offscreen_target_color_format_,
2230 offscreen_target_samples_)) {
2231 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2232 << "to allocate storage for offscreen target color buffer.";
2233 return false;
2234 }
2235 } else {
2236 if (!offscreen_target_color_texture_->AllocateStorage(
2237 pending_offscreen_size_, offscreen_target_color_format_)) {
2238 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2239 << "to allocate storage for offscreen target color texture.";
2240 return false;
2241 }
2242 }
2243 if (offscreen_target_depth_format_ &&
2244 !offscreen_target_depth_render_buffer_->AllocateStorage(
2245 pending_offscreen_size_, offscreen_target_depth_format_,
2246 offscreen_target_samples_)) {
[email protected]d0498742010-09-20 20:27:012247 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
[email protected]34ff8b0c2010-10-01 20:06:022248 << "to allocate storage for offscreen target depth buffer.";
2249 return false;
2250 }
2251 if (offscreen_target_stencil_format_ &&
2252 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2253 pending_offscreen_size_, offscreen_target_stencil_format_,
2254 offscreen_target_samples_)) {
2255 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2256 << "to allocate storage for offscreen target stencil buffer.";
[email protected]6217d392010-03-25 22:08:352257 return false;
2258 }
2259
[email protected]2f2d7042010-04-14 21:45:582260 // Attach the offscreen target buffers to the target frame buffer.
[email protected]34ff8b0c2010-10-01 20:06:022261 if (IsOffscreenBufferMultisampled()) {
[email protected]b9363b22010-06-09 22:06:152262 offscreen_target_frame_buffer_->AttachRenderBuffer(
[email protected]34ff8b0c2010-10-01 20:06:022263 GL_COLOR_ATTACHMENT0,
2264 offscreen_target_color_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152265 } else {
[email protected]34ff8b0c2010-10-01 20:06:022266 offscreen_target_frame_buffer_->AttachRenderTexture(
2267 offscreen_target_color_texture_.get());
2268 }
2269 if (offscreen_target_depth_format_) {
2270 offscreen_target_frame_buffer_->AttachRenderBuffer(
2271 GL_DEPTH_ATTACHMENT,
2272 offscreen_target_depth_render_buffer_.get());
2273 }
2274 const bool packed_depth_stencil =
2275 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2276 if (packed_depth_stencil) {
[email protected]b9363b22010-06-09 22:06:152277 offscreen_target_frame_buffer_->AttachRenderBuffer(
2278 GL_STENCIL_ATTACHMENT,
2279 offscreen_target_depth_render_buffer_.get());
[email protected]34ff8b0c2010-10-01 20:06:022280 } else if (offscreen_target_stencil_format_) {
2281 offscreen_target_frame_buffer_->AttachRenderBuffer(
2282 GL_STENCIL_ATTACHMENT,
2283 offscreen_target_stencil_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152284 }
[email protected]34ff8b0c2010-10-01 20:06:022285
[email protected]6217d392010-03-25 22:08:352286 if (offscreen_target_frame_buffer_->CheckStatus() !=
2287 GL_FRAMEBUFFER_COMPLETE) {
[email protected]d0498742010-09-20 20:27:012288 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2289 << "because offscreen FBO was incomplete.";
[email protected]6217d392010-03-25 22:08:352290 return false;
2291 }
2292
[email protected]c007aa02010-09-02 22:22:402293 // Clear the target frame buffer.
2294 {
2295 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]3f0add5e2010-09-13 20:16:282296 glClearColor(0, 0, 0, 0);
[email protected]c007aa02010-09-02 22:22:402297 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2298 glClearStencil(0);
2299 glStencilMaskSeparate(GL_FRONT, GL_TRUE);
2300 glStencilMaskSeparate(GL_BACK, GL_TRUE);
2301 glClearDepth(0);
2302 glDepthMask(GL_TRUE);
2303 glDisable(GL_SCISSOR_TEST);
[email protected]2f2d7042010-04-14 21:45:582304 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402305 RestoreClearState();
[email protected]2f2d7042010-04-14 21:45:582306 }
[email protected]2f2d7042010-04-14 21:45:582307
[email protected]34ff8b0c2010-10-01 20:06:022308 if (parent_ || IsOffscreenBufferMultisampled()) {
[email protected]97872062010-11-03 19:07:052309 DCHECK(offscreen_saved_color_format_);
2310 offscreen_saved_color_texture_->AllocateStorage(
2311 pending_offscreen_size_, offscreen_saved_color_format_);
[email protected]d37231fa2010-04-09 21:16:022312
[email protected]34ff8b0c2010-10-01 20:06:022313 offscreen_saved_frame_buffer_->AttachRenderTexture(
2314 offscreen_saved_color_texture_.get());
2315 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2316 GL_FRAMEBUFFER_COMPLETE) {
2317 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2318 << "because offscreen saved FBO was incomplete.";
2319 return false;
2320 }
2321 }
2322
2323 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582324 // Update the info about the offscreen saved color texture in the parent.
2325 // The reference to the parent is a weak pointer and will become null if the
2326 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352327 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142328 GLuint client_id;
2329 CHECK(parent_->texture_manager()->GetClientId(service_id, &client_id));
2330 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352331 DCHECK(info);
2332
[email protected]ef526492010-06-02 23:12:252333 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:112334 feature_info_,
[email protected]ef526492010-06-02 23:12:252335 info,
2336 GL_TEXTURE_2D,
2337 0, // level
2338 GL_RGBA,
2339 pending_offscreen_size_.width(),
2340 pending_offscreen_size_.height(),
2341 1, // depth
2342 0, // border
2343 GL_RGBA,
2344 GL_UNSIGNED_BYTE);
[email protected]8c515f82010-11-09 03:40:042345 texture_manager()->SetParameter(
2346 feature_info_,
2347 info,
2348 GL_TEXTURE_MAG_FILTER,
2349 GL_NEAREST);
2350 texture_manager()->SetParameter(
2351 feature_info_,
2352 info,
2353 GL_TEXTURE_MIN_FILTER,
2354 GL_NEAREST);
2355 texture_manager()->SetParameter(
2356 feature_info_,
2357 info,
2358 GL_TEXTURE_WRAP_S,
2359 GL_CLAMP_TO_EDGE);
2360 texture_manager()->SetParameter(
2361 feature_info_,
2362 info,
2363 GL_TEXTURE_WRAP_T,
2364 GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:352365
[email protected]c007aa02010-09-02 22:22:402366 // Clear the offscreen color texture.
2367 {
[email protected]34ff8b0c2010-10-01 20:06:022368 ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:402369 glClearColor(0, 0, 0, 0);
2370 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2371 glDisable(GL_SCISSOR_TEST);
[email protected]0c8c9d22010-06-25 17:36:392372 glClear(GL_COLOR_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402373 RestoreClearState();
[email protected]0c8c9d22010-06-25 17:36:392374 }
[email protected]0c8c9d22010-06-25 17:36:392375 }
[email protected]e566b955d2010-06-22 19:26:512376
[email protected]6217d392010-03-25 22:08:352377 return true;
2378}
2379
[email protected]43f28f832010-02-03 02:28:482380void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
2381 swap_buffers_callback_.reset(callback);
2382}
2383
[email protected]1318e922010-09-17 22:03:162384bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2385 uint32* service_texture_id) {
2386 TextureManager::TextureInfo* texture =
2387 texture_manager()->GetTextureInfo(client_texture_id);
2388 if (texture) {
2389 *service_texture_id = texture->service_id();
2390 return true;
2391 }
2392 return false;
2393}
2394
[email protected]96449d2c2009-11-25 00:01:322395void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392396 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052397
2398 if (group_.get())
2399 group_->set_have_context(have_context);
2400
[email protected]eadc96792010-10-27 19:39:392401 if (have_context) {
[email protected]b1122982010-05-17 23:04:242402 if (attrib_0_buffer_id_) {
2403 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2404 }
2405
[email protected]4bedba72010-04-20 22:08:542406 // Remove the saved frame buffer mapping from the parent decoder. The
2407 // parent pointer is a weak pointer so it will be null if the parent has
2408 // already been destroyed.
2409 if (parent_) {
2410 // First check the texture has been mapped into the parent. This might not
2411 // be the case if initialization failed midway through.
2412 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]ae51d192010-04-27 00:48:032413 GLuint client_id = 0;
2414 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]915a59a12010-09-30 21:29:112415 parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]4bedba72010-04-20 22:08:542416 }
[email protected]a3a93e7b2010-08-28 00:48:562417
2418 glDeleteFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:352419 }
[email protected]6217d392010-03-25 22:08:352420
[email protected]97872062010-11-03 19:07:052421 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542422 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052423 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542424 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052425 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022426 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052427 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152428 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052429 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152430 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052431 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022432 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052433 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542434 offscreen_saved_color_texture_->Destroy();
[email protected]66791e382010-07-14 20:48:302435
[email protected]eadc96792010-10-27 19:39:392436 // must release the ContextGroup before destroying the context as its
2437 // destructor uses GL.
2438 group_ = NULL;
2439
[email protected]66791e382010-07-14 20:48:302440 context_->Destroy();
2441 context_.reset();
[email protected]97872062010-11-03 19:07:052442 } else {
2443 if (offscreen_target_frame_buffer_.get())
2444 offscreen_target_frame_buffer_->Invalidate();
2445 if (offscreen_target_color_texture_.get())
2446 offscreen_target_color_texture_->Invalidate();
2447 if (offscreen_target_color_render_buffer_.get())
2448 offscreen_target_color_render_buffer_->Invalidate();
2449 if (offscreen_target_depth_render_buffer_.get())
2450 offscreen_target_depth_render_buffer_->Invalidate();
2451 if (offscreen_target_stencil_render_buffer_.get())
2452 offscreen_target_stencil_render_buffer_->Invalidate();
2453 if (offscreen_saved_frame_buffer_.get())
2454 offscreen_saved_frame_buffer_->Invalidate();
2455 if (offscreen_saved_color_texture_.get())
2456 offscreen_saved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022457 }
[email protected]97872062010-11-03 19:07:052458
2459 offscreen_target_frame_buffer_.reset();
2460 offscreen_target_color_texture_.reset();
2461 offscreen_target_color_render_buffer_.reset();
2462 offscreen_target_depth_render_buffer_.reset();
2463 offscreen_target_stencil_render_buffer_.reset();
2464 offscreen_saved_frame_buffer_.reset();
2465 offscreen_saved_color_texture_.reset();
[email protected]96449d2c2009-11-25 00:01:322466}
2467
[email protected]6217d392010-03-25 22:08:352468void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2469 // We can't resize the render buffers immediately because there might be a
2470 // partial frame rendered into them and we don't want the tail end of that
2471 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:022472 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352473}
2474
[email protected]c007aa02010-09-02 22:22:402475void GLES2DecoderImpl::DoCopyTextureToParentTexture(
2476 GLuint client_texture_id,
2477 GLuint parent_client_texture_id) {
[email protected]a3a93e7b2010-08-28 00:48:562478 if (parent_) {
[email protected]c007aa02010-09-02 22:22:402479 TextureManager::TextureInfo* texture = texture_manager()->GetTextureInfo(
2480 client_texture_id);
2481 TextureManager::TextureInfo* parent_texture =
2482 parent_->texture_manager()->GetTextureInfo(parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:562483 if (!texture || !parent_texture) {
2484 current_decoder_error_ = error::kInvalidArguments;
2485 return;
2486 }
2487 ScopedFrameBufferBinder fb_binder(this, copy_texture_to_parent_texture_fb_);
2488 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2489 GL_COLOR_ATTACHMENT0,
2490 GL_TEXTURE_2D,
2491 texture->service_id(),
2492 0);
2493 ScopedTexture2DBinder tex_binder(this, parent_texture->service_id());
2494 GLsizei width, height;
2495 parent_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
2496 glCopyTexImage2D(GL_TEXTURE_2D,
2497 0, // level
2498 GL_RGBA,
[email protected]c007aa02010-09-02 22:22:402499 0, 0, // x, y
[email protected]a3a93e7b2010-08-28 00:48:562500 width,
2501 height,
2502 0); // border
2503 }
2504}
2505
[email protected]96449d2c2009-11-25 00:01:322506const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2507 if (command_id > kStartPoint && command_id < kNumCommands) {
2508 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2509 }
2510 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2511}
2512
2513// Decode command with its arguments, and call the corresponding GL function.
2514// Note: args is a pointer to the command buffer. As such, it could be changed
2515// by a (malicious) client at any time, so if validation has to happen, it
2516// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142517error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322518 unsigned int command,
2519 unsigned int arg_count,
2520 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142521 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192522 if (debug()) {
2523 // TODO(gman): Change output to something useful for NaCl.
[email protected]d366c482010-10-20 00:11:272524 DVLOG(1) << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192525 }
[email protected]96449d2c2009-11-25 00:01:322526 unsigned int command_index = command - kStartPoint - 1;
2527 if (command_index < arraysize(g_command_info)) {
2528 const CommandInfo& info = g_command_info[command_index];
2529 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2530 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2531 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192532 uint32 immediate_data_size =
2533 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322534 switch (command) {
2535 #define GLES2_CMD_OP(name) \
2536 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192537 result = Handle ## name( \
2538 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322539 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192540 break; \
[email protected]96449d2c2009-11-25 00:01:322541
2542 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322543 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382544 }
2545 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302546 GLenum error;
2547 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382548 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292549 SetGLError(error, NULL);
[email protected]d366c482010-10-20 00:11:272550 DVLOG(1) << "GL ERROR: " << error << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192551 }
[email protected]96449d2c2009-11-25 00:01:322552 }
2553 } else {
[email protected]f7a64ee2010-02-01 22:24:142554 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322555 }
[email protected]b9849abf2009-11-25 19:13:192556 } else {
2557 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322558 }
[email protected]a3a93e7b2010-08-28 00:48:562559 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
2560 result = current_decoder_error_;
2561 current_decoder_error_ = error::kNoError;
2562 }
[email protected]b9849abf2009-11-25 19:13:192563 return result;
[email protected]96449d2c2009-11-25 00:01:322564}
2565
[email protected]ae51d192010-04-27 00:48:032566void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2567 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502568}
2569
[email protected]ae51d192010-04-27 00:48:032570bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2571 if (GetProgramInfo(client_id)) {
2572 return false;
2573 }
[email protected]96449d2c2009-11-25 00:01:322574 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032575 if (service_id != 0) {
2576 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322577 }
[email protected]ae51d192010-04-27 00:48:032578 return true;
[email protected]96449d2c2009-11-25 00:01:322579}
2580
[email protected]ae51d192010-04-27 00:48:032581bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2582 if (GetShaderInfo(client_id)) {
2583 return false;
[email protected]96449d2c2009-11-25 00:01:322584 }
[email protected]ae51d192010-04-27 00:48:032585 GLuint service_id = glCreateShader(type);
2586 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382587 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032588 }
2589 return true;
[email protected]96449d2c2009-11-25 00:01:322590}
2591
[email protected]3916c97e2010-02-25 03:20:502592void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452593 GLuint texture_index = texture_unit - GL_TEXTURE0;
2594 if (texture_index > group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292595 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502596 return;
2597 }
[email protected]36cef8ce2010-03-16 07:34:452598 active_texture_unit_ = texture_index;
2599 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502600}
2601
[email protected]051b1372010-04-12 02:42:082602void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502603 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082604 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032605 if (client_id != 0) {
2606 info = GetBufferInfo(client_id);
2607 if (!info) {
2608 // It's a new id so make a buffer info for it.
2609 glGenBuffersARB(1, &service_id);
2610 CreateBufferInfo(client_id, service_id);
2611 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102612 IdAllocator* id_allocator =
2613 group_->GetIdAllocator(id_namespaces::kBuffers);
2614 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032615 }
[email protected]051b1372010-04-12 02:42:082616 }
[email protected]ae51d192010-04-27 00:48:032617 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102618 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292619 SetGLError(GL_INVALID_OPERATION,
2620 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472621 return;
2622 }
[email protected]ae51d192010-04-27 00:48:032623 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472624 }
[email protected]96449d2c2009-11-25 00:01:322625 switch (target) {
2626 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502627 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322628 break;
2629 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502630 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322631 break;
2632 default:
[email protected]a93bb842010-02-16 23:03:472633 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322634 break;
2635 }
[email protected]051b1372010-04-12 02:42:082636 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322637}
2638
[email protected]051b1372010-04-12 02:42:082639void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2640 FramebufferManager::FramebufferInfo* info = NULL;
2641 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032642 if (client_id != 0) {
2643 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082644 if (!info) {
[email protected]ae51d192010-04-27 00:48:032645 // It's a new id so make a framebuffer info for it.
2646 glGenFramebuffersEXT(1, &service_id);
2647 CreateFramebufferInfo(client_id, service_id);
2648 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102649 IdAllocator* id_allocator =
2650 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2651 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032652 } else {
2653 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082654 }
2655 }
[email protected]8e3e0662010-08-23 18:46:302656
2657 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
2658 bound_draw_framebuffer_ = info;
2659 }
2660 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
2661 bound_read_framebuffer_ = info;
2662 }
[email protected]6217d392010-03-25 22:08:352663
2664 // When rendering to an offscreen frame buffer, instead of unbinding from
2665 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:082666 if (info == NULL && offscreen_target_frame_buffer_.get())
2667 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:352668
[email protected]051b1372010-04-12 02:42:082669 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562670}
2671
[email protected]051b1372010-04-12 02:42:082672void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2673 RenderbufferManager::RenderbufferInfo* info = NULL;
2674 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032675 if (client_id != 0) {
2676 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082677 if (!info) {
[email protected]ae51d192010-04-27 00:48:032678 // It's a new id so make a renderbuffer info for it.
2679 glGenRenderbuffersEXT(1, &service_id);
2680 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102681 info = GetRenderbufferInfo(client_id);
2682 IdAllocator* id_allocator =
2683 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2684 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032685 } else {
2686 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082687 }
2688 }
2689 bound_renderbuffer_ = info;
2690 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562691}
2692
[email protected]051b1372010-04-12 02:42:082693void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032694 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082695 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032696 if (client_id != 0) {
2697 info = GetTextureInfo(client_id);
2698 if (!info) {
2699 // It's a new id so make a texture info for it.
2700 glGenTextures(1, &service_id);
2701 CreateTextureInfo(client_id, service_id);
2702 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:102703 IdAllocator* id_allocator =
2704 group_->GetIdAllocator(id_namespaces::kTextures);
2705 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032706 }
2707 } else {
2708 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082709 }
[email protected]ae51d192010-04-27 00:48:032710
[email protected]1958e0e2010-04-22 05:17:152711 // Check the texture exists
2712 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032713 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292714 SetGLError(GL_INVALID_OPERATION,
2715 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152716 return;
2717 }
2718 if (info->target() == 0) {
2719 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472720 }
[email protected]ae51d192010-04-27 00:48:032721 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502722 TextureUnit& unit = texture_units_[active_texture_unit_];
2723 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472724 switch (target) {
2725 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502726 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472727 break;
2728 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502729 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472730 break;
2731 default:
2732 NOTREACHED(); // Validation should prevent us getting here.
2733 break;
2734 }
2735}
2736
[email protected]07f54fcc2009-12-22 02:46:302737void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082738 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]b1122982010-05-17 23:04:242739 if (index != 0) {
2740 glDisableVertexAttribArray(index);
2741 }
[email protected]07f54fcc2009-12-22 02:46:302742 } else {
[email protected]8eee29c2010-04-29 03:38:292743 SetGLError(GL_INVALID_VALUE,
2744 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302745 }
2746}
2747
2748void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082749 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302750 glEnableVertexAttribArray(index);
2751 } else {
[email protected]8eee29c2010-04-29 03:38:292752 SetGLError(GL_INVALID_VALUE,
2753 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302754 }
2755}
2756
[email protected]a93bb842010-02-16 23:03:472757void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502758 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]915a59a12010-09-30 21:29:112759 if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) {
[email protected]8eee29c2010-04-29 03:38:292760 SetGLError(GL_INVALID_OPERATION,
2761 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472762 return;
2763 }
2764 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:472765}
2766
[email protected]b273e432010-04-12 17:23:582767bool GLES2DecoderImpl::GetHelper(
2768 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582769 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152770 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2771 switch (pname) {
[email protected]b273e432010-04-12 17:23:582772 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2773 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102774 if (params) {
[email protected]5094b0f2010-11-09 19:45:242775 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:102776 }
[email protected]b273e432010-04-12 17:23:582777 return true;
2778 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2779 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102780 if (params) {
[email protected]5094b0f2010-11-09 19:45:242781 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:102782 }
[email protected]b273e432010-04-12 17:23:582783 return true;
2784 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2785 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102786 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482787 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102788 }
[email protected]b273e432010-04-12 17:23:582789 return true;
2790 case GL_MAX_VARYING_VECTORS:
2791 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102792 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482793 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102794 }
[email protected]b273e432010-04-12 17:23:582795 return true;
2796 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2797 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102798 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482799 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102800 }
[email protected]b273e432010-04-12 17:23:582801 return true;
[email protected]5094b0f2010-11-09 19:45:242802 case GL_MAX_VIEWPORT_DIMS:
2803 if (offscreen_target_frame_buffer_.get()) {
2804 *num_written = 2;
2805 if (params) {
2806 params[0] = renderbuffer_manager()->max_renderbuffer_size();
2807 params[1] = renderbuffer_manager()->max_renderbuffer_size();
2808 }
2809 return true;
2810 }
[email protected]b9363b22010-06-09 22:06:152811 }
2812 }
2813 switch (pname) {
[email protected]656dcaad2010-05-07 17:18:372814 case GL_COMPRESSED_TEXTURE_FORMATS:
2815 *num_written = 0;
2816 // We don't support compressed textures.
2817 return true;
[email protected]b273e432010-04-12 17:23:582818 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
2819 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102820 if (params) {
2821 *params = 0; // We don't support compressed textures.
2822 }
[email protected]b273e432010-04-12 17:23:582823 return true;
2824 case GL_NUM_SHADER_BINARY_FORMATS:
2825 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102826 if (params) {
2827 *params = 0; // We don't support binary shader formats.
2828 }
[email protected]b273e432010-04-12 17:23:582829 return true;
2830 case GL_SHADER_BINARY_FORMATS:
2831 *num_written = 0;
2832 return true; // We don't support binary shader format.s
2833 case GL_SHADER_COMPILER:
2834 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102835 if (params) {
2836 *params = GL_TRUE;
2837 }
[email protected]b273e432010-04-12 17:23:582838 return true;
[email protected]6b8cf1a2010-05-06 16:13:582839 case GL_ARRAY_BUFFER_BINDING:
2840 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102841 if (params) {
2842 if (bound_array_buffer_) {
2843 GLuint client_id = 0;
2844 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
2845 &client_id);
2846 *params = client_id;
2847 } else {
2848 *params = 0;
2849 }
[email protected]6b8cf1a2010-05-06 16:13:582850 }
2851 return true;
2852 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
2853 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102854 if (params) {
2855 if (bound_element_array_buffer_) {
2856 GLuint client_id = 0;
2857 buffer_manager()->GetClientId(
2858 bound_element_array_buffer_->service_id(),
2859 &client_id);
2860 *params = client_id;
2861 } else {
2862 *params = 0;
2863 }
[email protected]6b8cf1a2010-05-06 16:13:582864 }
2865 return true;
2866 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:302867 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:582868 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102869 if (params) {
[email protected]8e3e0662010-08-23 18:46:302870 if (bound_draw_framebuffer_) {
[email protected]4e8a5b122010-05-08 22:00:102871 GLuint client_id = 0;
2872 framebuffer_manager()->GetClientId(
[email protected]8e3e0662010-08-23 18:46:302873 bound_draw_framebuffer_->service_id(), &client_id);
2874 *params = client_id;
2875 } else {
2876 *params = 0;
2877 }
2878 }
2879 return true;
2880 case GL_READ_FRAMEBUFFER_BINDING:
2881 *num_written = 1;
2882 if (params) {
2883 if (bound_read_framebuffer_) {
2884 GLuint client_id = 0;
2885 framebuffer_manager()->GetClientId(
2886 bound_read_framebuffer_->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:102887 *params = client_id;
2888 } else {
2889 *params = 0;
2890 }
[email protected]6b8cf1a2010-05-06 16:13:582891 }
2892 return true;
2893 case GL_RENDERBUFFER_BINDING:
2894 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102895 if (params) {
2896 if (bound_renderbuffer_) {
2897 GLuint client_id = 0;
2898 renderbuffer_manager()->GetClientId(
2899 bound_renderbuffer_->service_id(), &client_id);
2900 *params = client_id;
2901 } else {
2902 *params = 0;
2903 }
[email protected]6b8cf1a2010-05-06 16:13:582904 }
2905 return true;
2906 case GL_CURRENT_PROGRAM:
2907 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102908 if (params) {
2909 if (current_program_) {
2910 GLuint client_id = 0;
2911 program_manager()->GetClientId(
2912 current_program_->service_id(), &client_id);
2913 *params = client_id;
2914 } else {
2915 *params = 0;
2916 }
[email protected]6b8cf1a2010-05-06 16:13:582917 }
2918 return true;
[email protected]4e8a5b122010-05-08 22:00:102919 case GL_TEXTURE_BINDING_2D:
2920 *num_written = 1;
2921 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582922 TextureUnit& unit = texture_units_[active_texture_unit_];
2923 if (unit.bound_texture_2d) {
2924 GLuint client_id = 0;
2925 texture_manager()->GetClientId(
2926 unit.bound_texture_2d->service_id(), &client_id);
2927 *params = client_id;
2928 } else {
2929 *params = 0;
2930 }
[email protected]6b8cf1a2010-05-06 16:13:582931 }
[email protected]4e8a5b122010-05-08 22:00:102932 return true;
2933 case GL_TEXTURE_BINDING_CUBE_MAP:
2934 *num_written = 1;
2935 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582936 TextureUnit& unit = texture_units_[active_texture_unit_];
2937 if (unit.bound_texture_cube_map) {
2938 GLuint client_id = 0;
2939 texture_manager()->GetClientId(
2940 unit.bound_texture_cube_map->service_id(), &client_id);
2941 *params = client_id;
2942 } else {
2943 *params = 0;
2944 }
[email protected]6b8cf1a2010-05-06 16:13:582945 }
[email protected]4e8a5b122010-05-08 22:00:102946 return true;
[email protected]b273e432010-04-12 17:23:582947 default:
[email protected]4e8a5b122010-05-08 22:00:102948 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:532949 return false;
[email protected]b273e432010-04-12 17:23:582950 }
2951}
2952
[email protected]4e8a5b122010-05-08 22:00:102953bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
2954 GLenum pname, GLsizei* num_values) {
2955 return GetHelper(pname, NULL, num_values);
2956}
2957
[email protected]b273e432010-04-12 17:23:582958void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
2959 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:102960 GLsizei num_written = 0;
2961 if (GetHelper(pname, NULL, &num_written)) {
2962 scoped_array<GLint> values(new GLint[num_written]);
2963 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:582964 for (GLsizei ii = 0; ii < num_written; ++ii) {
2965 params[ii] = static_cast<GLboolean>(values[ii]);
2966 }
2967 } else {
2968 glGetBooleanv(pname, params);
2969 }
2970}
2971
2972void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
2973 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:102974 GLsizei num_written = 0;
2975 if (GetHelper(pname, NULL, &num_written)) {
2976 scoped_array<GLint> values(new GLint[num_written]);
2977 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:582978 for (GLsizei ii = 0; ii < num_written; ++ii) {
2979 params[ii] = static_cast<GLfloat>(values[ii]);
2980 }
2981 } else {
2982 glGetFloatv(pname, params);
2983 }
2984}
2985
2986void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
2987 DCHECK(params);
2988 GLsizei num_written;
2989 if (!GetHelper(pname, params, &num_written)) {
2990 glGetIntegerv(pname, params);
2991 }
2992}
2993
[email protected]a0c3e972010-04-21 00:49:132994void GLES2DecoderImpl::DoGetProgramiv(
2995 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:582996 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2997 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:132998 if (!info) {
[email protected]a0c3e972010-04-21 00:49:132999 return;
3000 }
3001 info->GetProgramiv(pname, params);
3002}
3003
[email protected]558847a2010-03-24 07:02:543004error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3005 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:583006 GLuint program = static_cast<GLuint>(c.program);
3007 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3008 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033009 if (!info) {
[email protected]558847a2010-03-24 07:02:543010 return error::kNoError;
3011 }
3012 GLuint index = static_cast<GLuint>(c.index);
3013 uint32 name_size = c.data_size;
3014 const char* name = GetSharedMemoryAs<const char*>(
3015 c.name_shm_id, c.name_shm_offset, name_size);
3016 if (name == NULL) {
3017 return error::kOutOfBounds;
3018 }
3019 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033020 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543021 return error::kNoError;
3022}
3023
3024error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3025 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583026 GLuint program = static_cast<GLuint>(c.program);
3027 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3028 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033029 if (!info) {
[email protected]558847a2010-03-24 07:02:543030 return error::kNoError;
3031 }
3032 GLuint index = static_cast<GLuint>(c.index);
3033 uint32 name_size = c.data_size;
3034 const char* name = GetImmediateDataAs<const char*>(
3035 c, name_size, immediate_data_size);
3036 if (name == NULL) {
3037 return error::kOutOfBounds;
3038 }
3039 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033040 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543041 return error::kNoError;
3042}
3043
3044error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3045 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583046 GLuint program = static_cast<GLuint>(c.program);
3047 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3048 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033049 if (!info) {
[email protected]558847a2010-03-24 07:02:543050 return error::kNoError;
3051 }
3052 GLuint index = static_cast<GLuint>(c.index);
3053 Bucket* bucket = GetBucket(c.name_bucket_id);
3054 if (!bucket || bucket->size() == 0) {
3055 return error::kInvalidArguments;
3056 }
3057 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183058 if (!bucket->GetAsString(&name_str)) {
3059 return error::kInvalidArguments;
3060 }
[email protected]ae51d192010-04-27 00:48:033061 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543062 return error::kNoError;
3063}
3064
[email protected]f7a64ee2010-02-01 22:24:143065error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463066 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033067 GLuint client_id = c.shader;
3068 if (client_id) {
3069 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3070 if (info) {
3071 glDeleteShader(info->service_id());
3072 RemoveShaderInfo(client_id);
3073 } else {
[email protected]8eee29c2010-04-29 03:38:293074 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033075 }
[email protected]96449d2c2009-11-25 00:01:323076 }
[email protected]f7a64ee2010-02-01 22:24:143077 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323078}
3079
[email protected]f7a64ee2010-02-01 22:24:143080error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463081 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033082 GLuint client_id = c.program;
3083 if (client_id) {
3084 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3085 if (info) {
3086 glDeleteProgram(info->service_id());
3087 RemoveProgramInfo(client_id);
3088 } else {
[email protected]8eee29c2010-04-29 03:38:293089 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033090 }
[email protected]96449d2c2009-11-25 00:01:323091 }
[email protected]f7a64ee2010-02-01 22:24:143092 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323093}
3094
[email protected]066849e32010-05-03 19:14:103095void GLES2DecoderImpl::DoDeleteSharedIds(
3096 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3097 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3098 for (GLsizei ii = 0; ii < n; ++ii) {
3099 id_allocator->FreeID(ids[ii]);
3100 }
3101}
3102
3103error::Error GLES2DecoderImpl::HandleDeleteSharedIds(
3104 uint32 immediate_data_size, const gles2::DeleteSharedIds& c) {
3105 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3106 GLsizei n = static_cast<GLsizei>(c.n);
3107 uint32 data_size;
3108 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3109 return error::kOutOfBounds;
3110 }
3111 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3112 c.ids_shm_id, c.ids_shm_offset, data_size);
3113 if (n < 0) {
3114 SetGLError(GL_INVALID_VALUE, "DeleteSharedIds: n < 0");
3115 return error::kNoError;
3116 }
3117 if (ids == NULL) {
3118 return error::kOutOfBounds;
3119 }
3120 DoDeleteSharedIds(namespace_id, n, ids);
3121 return error::kNoError;
3122}
3123
3124void GLES2DecoderImpl::DoGenSharedIds(
3125 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
3126 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3127 if (id_offset == 0) {
3128 for (GLsizei ii = 0; ii < n; ++ii) {
3129 ids[ii] = id_allocator->AllocateID();
3130 }
3131 } else {
3132 for (GLsizei ii = 0; ii < n; ++ii) {
3133 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3134 id_offset = ids[ii] + 1;
3135 }
3136 }
3137}
3138
3139error::Error GLES2DecoderImpl::HandleGenSharedIds(
3140 uint32 immediate_data_size, const gles2::GenSharedIds& c) {
3141 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3142 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3143 GLsizei n = static_cast<GLsizei>(c.n);
3144 uint32 data_size;
3145 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3146 return error::kOutOfBounds;
3147 }
3148 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3149 c.ids_shm_id, c.ids_shm_offset, data_size);
3150 if (n < 0) {
3151 SetGLError(GL_INVALID_VALUE, "GenSharedIds: n < 0");
3152 return error::kNoError;
3153 }
3154 if (ids == NULL) {
3155 return error::kOutOfBounds;
3156 }
3157 DoGenSharedIds(namespace_id, id_offset, n, ids);
3158 return error::kNoError;
3159}
3160
3161void GLES2DecoderImpl::DoRegisterSharedIds(
3162 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3163 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3164 for (GLsizei ii = 0; ii < n; ++ii) {
3165 if (!id_allocator->MarkAsUsed(ids[ii])) {
3166 for (GLsizei jj = 0; jj < ii; ++jj) {
3167 id_allocator->FreeID(ids[jj]);
3168 }
3169 SetGLError(
3170 GL_INVALID_VALUE,
3171 "RegisterSharedIds: attempt to register id that already exists");
3172 return;
3173 }
3174 }
3175}
3176
3177error::Error GLES2DecoderImpl::HandleRegisterSharedIds(
3178 uint32 immediate_data_size, const gles2::RegisterSharedIds& c) {
3179 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3180 GLsizei n = static_cast<GLsizei>(c.n);
3181 uint32 data_size;
3182 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3183 return error::kOutOfBounds;
3184 }
3185 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3186 c.ids_shm_id, c.ids_shm_offset, data_size);
3187 if (n < 0) {
3188 SetGLError(GL_INVALID_VALUE, "RegisterSharedIds: n < 0");
3189 return error::kNoError;
3190 }
3191 if (ids == NULL) {
3192 return error::kOutOfBounds;
3193 }
3194 DoRegisterSharedIds(namespace_id, n, ids);
3195 return error::kNoError;
3196}
3197
[email protected]07f54fcc2009-12-22 02:46:303198void GLES2DecoderImpl::DoDrawArrays(
3199 GLenum mode, GLint first, GLsizei count) {
[email protected]d81e8c52010-06-07 17:58:323200 // We have to check this here because the prototype for glDrawArrays
3201 // is GLint not GLsizei.
3202 if (first < 0) {
3203 SetGLError(GL_INVALID_ENUM, "glDrawArrays: first < 0");
3204 return;
3205 }
[email protected]6c788fb72010-08-26 02:16:313206
3207 if (count == 0) {
3208 return;
3209 }
3210
[email protected]07f54fcc2009-12-22 02:46:303211 if (IsDrawValid(first + count - 1)) {
[email protected]b1122982010-05-17 23:04:243212 bool simulated_attrib_0 = SimulateAttrib0(first + count - 1);
[email protected]ef526492010-06-02 23:12:253213 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]07f54fcc2009-12-22 02:46:303214 glDrawArrays(mode, first, count);
[email protected]ef526492010-06-02 23:12:253215 if (textures_set) {
[email protected]3916c97e2010-02-25 03:20:503216 RestoreStateForNonRenderableTextures();
3217 }
[email protected]b1122982010-05-17 23:04:243218 if (simulated_attrib_0) {
3219 RestoreStateForSimulatedAttrib0();
3220 }
[email protected]07f54fcc2009-12-22 02:46:303221 }
3222}
3223
[email protected]36cef8ce2010-03-16 07:34:453224void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3225 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033226 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303227 FramebufferManager::FramebufferInfo* framebuffer_info =
3228 GetFramebufferInfoForTarget(target);
3229 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293230 SetGLError(GL_INVALID_OPERATION,
3231 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453232 return;
3233 }
[email protected]ae51d192010-04-27 00:48:033234 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283235 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033236 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283237 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033238 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293239 SetGLError(GL_INVALID_OPERATION,
3240 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033241 return;
3242 }
3243 service_id = info->service_id();
3244 }
3245 glFramebufferRenderbufferEXT(
3246 target, attachment, renderbuffertarget, service_id);
[email protected]3a2e7c7b2010-08-06 01:12:283247 if (service_id == 0 ||
3248 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
[email protected]8e3e0662010-08-23 18:46:303249 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:283250 if (info) {
[email protected]8e3e0662010-08-23 18:46:303251 ClearUnclearedRenderbuffers(target, framebuffer_info);
[email protected]3a2e7c7b2010-08-06 01:12:283252 }
3253 }
3254}
3255
3256void GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
3257 switch (cap) {
3258 case GL_SCISSOR_TEST:
3259 enable_scissor_test_ = enabled;
3260 break;
3261 default:
3262 break;
3263 }
3264}
3265
3266void GLES2DecoderImpl::DoDisable(GLenum cap) {
3267 SetCapabilityState(cap, false);
3268 glDisable(cap);
3269}
3270
3271void GLES2DecoderImpl::DoEnable(GLenum cap) {
3272 SetCapabilityState(cap, true);
3273 glEnable(cap);
3274}
3275
3276void GLES2DecoderImpl::DoClearColor(
3277 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
3278 clear_red_ = red;
3279 clear_green_ = green;
3280 clear_blue_ = blue;
3281 clear_alpha_ = alpha;
3282 glClearColor(red, green, blue, alpha);
3283}
3284
3285void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
3286 clear_depth_ = depth;
3287 glClearDepth(depth);
3288}
3289
3290void GLES2DecoderImpl::DoClearStencil(GLint s) {
3291 clear_stencil_ = s;
3292 glClearStencil(s);
3293}
3294
3295void GLES2DecoderImpl::DoColorMask(
3296 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
3297 mask_red_ = red;
3298 mask_green_ = green;
3299 mask_blue_ = blue;
3300 mask_alpha_ = alpha;
3301 glColorMask(red, green, blue, alpha);
3302}
3303
3304void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
3305 mask_depth_ = depth;
3306 glDepthMask(depth);
3307}
3308
3309void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
3310 mask_stencil_front_ = mask;
3311 mask_stencil_back_ = mask;
3312 glStencilMask(mask);
3313}
3314
3315void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
3316 if (face == GL_FRONT) {
3317 mask_stencil_front_ = mask;
3318 } else {
3319 mask_stencil_back_ = mask;
3320 }
3321 glStencilMaskSeparate(face, mask);
3322}
3323
3324// NOTE: There's an assumption here that Texture attachments
3325// are cleared because they are textures so we only need to clear
3326// the renderbuffers.
3327void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
[email protected]8e3e0662010-08-23 18:46:303328 GLenum target, FramebufferManager::FramebufferInfo* info) {
3329 if (target == GL_READ_FRAMEBUFFER_EXT) {
3330 // TODO(gman): bind this to the DRAW point, clear then bind back to READ
3331 }
[email protected]3a2e7c7b2010-08-06 01:12:283332 GLbitfield clear_bits = 0;
3333 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
3334 glClearColor(0, 0, 0, 0);
3335 glColorMask(true, true, true, true);
3336 clear_bits |= GL_COLOR_BUFFER_BIT;
3337 }
3338
3339 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
3340 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3341 glClearStencil(0);
3342 glStencilMask(-1);
3343 clear_bits |= GL_STENCIL_BUFFER_BIT;
3344 }
3345
3346 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
3347 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3348 glClearDepth(1.0f);
3349 glDepthMask(true);
3350 clear_bits |= GL_DEPTH_BUFFER_BIT;
3351 }
3352
3353 glDisable(GL_SCISSOR_TEST);
3354 glClear(clear_bits);
3355
3356 info->MarkAttachedRenderbuffersAsCleared();
3357
[email protected]c007aa02010-09-02 22:22:403358 RestoreClearState();
3359
3360 if (target == GL_READ_FRAMEBUFFER_EXT) {
3361 // TODO(gman): rebind draw.
3362 }
3363}
3364
3365void GLES2DecoderImpl::RestoreClearState() {
[email protected]3a2e7c7b2010-08-06 01:12:283366 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
3367 glColorMask(mask_red_, mask_green_, mask_blue_, mask_alpha_);
3368 glClearStencil(clear_stencil_);
3369 glStencilMaskSeparate(GL_FRONT, mask_stencil_front_);
3370 glStencilMaskSeparate(GL_BACK, mask_stencil_back_);
3371 glClearDepth(clear_depth_);
3372 glDepthMask(mask_depth_);
3373 if (enable_scissor_test_) {
3374 glEnable(GL_SCISSOR_TEST);
3375 }
[email protected]36cef8ce2010-03-16 07:34:453376}
3377
3378GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]8e3e0662010-08-23 18:46:303379 FramebufferManager::FramebufferInfo* info =
3380 GetFramebufferInfoForTarget(target);
3381 if (!info) {
[email protected]36cef8ce2010-03-16 07:34:453382 return GL_FRAMEBUFFER_COMPLETE;
3383 }
3384 return glCheckFramebufferStatusEXT(target);
3385}
3386
3387void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033388 GLenum target, GLenum attachment, GLenum textarget,
3389 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303390 FramebufferManager::FramebufferInfo* framebuffer_info =
3391 GetFramebufferInfoForTarget(target);
3392 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293393 SetGLError(GL_INVALID_OPERATION,
3394 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453395 return;
3396 }
[email protected]ae51d192010-04-27 00:48:033397 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283398 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033399 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283400 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033401 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293402 SetGLError(GL_INVALID_OPERATION,
3403 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033404 return;
3405 }
3406 service_id = info->service_id();
3407 }
3408 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]3a2e7c7b2010-08-06 01:12:283409 if (service_id != 0 &&
3410 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
[email protected]8e3e0662010-08-23 18:46:303411 ClearUnclearedRenderbuffers(target, framebuffer_info);
[email protected]3a2e7c7b2010-08-06 01:12:283412 }
[email protected]36cef8ce2010-03-16 07:34:453413}
3414
3415void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3416 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303417 FramebufferManager::FramebufferInfo* framebuffer_info =
3418 GetFramebufferInfoForTarget(target);
3419 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293420 SetGLError(GL_INVALID_OPERATION,
3421 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453422 return;
3423 }
3424 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573425 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3426 GLint type = 0;
3427 GLuint client_id = 0;
3428 glGetFramebufferAttachmentParameterivEXT(
3429 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3430 switch (type) {
3431 case GL_RENDERBUFFER: {
3432 renderbuffer_manager()->GetClientId(*params, &client_id);
3433 break;
3434 }
3435 case GL_TEXTURE: {
3436 texture_manager()->GetClientId(*params, &client_id);
3437 break;
3438 }
3439 default:
3440 break;
3441 }
3442 *params = client_id;
3443 }
[email protected]36cef8ce2010-03-16 07:34:453444}
3445
3446void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
3447 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:083448 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293449 SetGLError(GL_INVALID_OPERATION,
3450 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453451 return;
3452 }
[email protected]b71f52c2010-06-18 22:20:203453 if (pname == GL_RENDERBUFFER_INTERNAL_FORMAT) {
3454 *params = bound_renderbuffer_->internal_format();
3455 return;
3456 }
[email protected]36cef8ce2010-03-16 07:34:453457 glGetRenderbufferParameterivEXT(target, pname, params);
3458}
3459
[email protected]8e3e0662010-08-23 18:46:303460void GLES2DecoderImpl::DoBlitFramebufferEXT(
3461 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3462 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3463 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:393464 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303465 SetGLError(GL_INVALID_OPERATION,
3466 "glBlitFramebufferEXT: function not available");
3467 }
[email protected]5094b0f2010-11-09 19:45:243468 if (IsAngle()) {
3469 glBlitFramebufferANGLE(
3470 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3471 } else {
3472 glBlitFramebufferEXT(
3473 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3474 }
[email protected]8e3e0662010-08-23 18:46:303475}
3476
3477void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
3478 GLenum target, GLsizei samples, GLenum internalformat,
3479 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:393480 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303481 SetGLError(GL_INVALID_OPERATION,
3482 "glRenderbufferStorageMultisampleEXT: function not available");
3483 return;
3484 }
3485 bound_renderbuffer_->set_internal_format(internalformat);
3486
3487 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3488 switch (internalformat) {
3489 case GL_DEPTH_COMPONENT16:
3490 internalformat = GL_DEPTH_COMPONENT;
3491 break;
3492 case GL_RGBA4:
3493 case GL_RGB5_A1:
3494 internalformat = GL_RGBA;
3495 break;
3496 case GL_RGB565:
3497 internalformat = GL_RGB;
3498 break;
3499 }
3500 }
3501
3502 glRenderbufferStorageMultisampleEXT(
3503 target, samples, internalformat, width, height);
3504 // TODO(gman) should not set internal format unless this succeeds
3505}
3506
[email protected]36cef8ce2010-03-16 07:34:453507void GLES2DecoderImpl::DoRenderbufferStorage(
3508 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:083509 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293510 SetGLError(GL_INVALID_OPERATION,
3511 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453512 return;
3513 }
[email protected]b71f52c2010-06-18 22:20:203514 bound_renderbuffer_->set_internal_format(internalformat);
[email protected]876f6fee2010-08-02 23:10:323515
3516 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3517 switch (internalformat) {
3518 case GL_DEPTH_COMPONENT16:
3519 internalformat = GL_DEPTH_COMPONENT;
3520 break;
3521 case GL_RGBA4:
3522 case GL_RGB5_A1:
3523 internalformat = GL_RGBA;
3524 break;
3525 case GL_RGB565:
3526 internalformat = GL_RGB;
3527 break;
3528 }
[email protected]b71f52c2010-06-18 22:20:203529 }
[email protected]876f6fee2010-08-02 23:10:323530
[email protected]36cef8ce2010-03-16 07:34:453531 glRenderbufferStorageEXT(target, internalformat, width, height);
[email protected]8e3e0662010-08-23 18:46:303532 // TODO(gman) should not set internal format unless this succeeds
[email protected]36cef8ce2010-03-16 07:34:453533}
3534
[email protected]07f54fcc2009-12-22 02:46:303535void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]6b8cf1a2010-05-06 16:13:583536 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3537 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:473538 if (!info) {
[email protected]a93bb842010-02-16 23:03:473539 return;
3540 }
[email protected]d81e8c52010-06-07 17:58:323541 if (!info->CanLink()) {
[email protected]d81e8c52010-06-07 17:58:323542 return;
3543 }
[email protected]ae51d192010-04-27 00:48:033544 glLinkProgram(info->service_id());
[email protected]6b8cf1a2010-05-06 16:13:583545 GLint success = 0;
3546 glGetProgramiv(info->service_id(), GL_LINK_STATUS, &success);
3547 if (success) {
[email protected]a93bb842010-02-16 23:03:473548 info->Update();
[email protected]6b8cf1a2010-05-06 16:13:583549 } else {
3550 info->Reset();
[email protected]07f54fcc2009-12-22 02:46:303551 }
3552};
3553
[email protected]3916c97e2010-02-25 03:20:503554void GLES2DecoderImpl::DoTexParameterf(
3555 GLenum target, GLenum pname, GLfloat param) {
3556 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:303557 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293558 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]07f54fcc2009-12-22 02:46:303559 } else {
[email protected]915a59a12010-09-30 21:29:113560 texture_manager()->SetParameter(
3561 feature_info_, info, pname, static_cast<GLint>(param));
[email protected]3916c97e2010-02-25 03:20:503562 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:303563 }
3564}
3565
[email protected]3916c97e2010-02-25 03:20:503566void GLES2DecoderImpl::DoTexParameteri(
3567 GLenum target, GLenum pname, GLint param) {
3568 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3569 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293570 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503571 } else {
[email protected]915a59a12010-09-30 21:29:113572 texture_manager()->SetParameter(feature_info_, info, pname, param);
[email protected]3916c97e2010-02-25 03:20:503573 glTexParameteri(target, pname, param);
3574 }
3575}
3576
3577void GLES2DecoderImpl::DoTexParameterfv(
3578 GLenum target, GLenum pname, const GLfloat* params) {
3579 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3580 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293581 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503582 } else {
[email protected]ef526492010-06-02 23:12:253583 texture_manager()->SetParameter(
[email protected]915a59a12010-09-30 21:29:113584 feature_info_, info, pname, *reinterpret_cast<const GLint*>(params));
[email protected]3916c97e2010-02-25 03:20:503585 glTexParameterfv(target, pname, params);
3586 }
3587}
3588
3589void GLES2DecoderImpl::DoTexParameteriv(
3590 GLenum target, GLenum pname, const GLint* params) {
3591 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3592 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293593 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503594 } else {
[email protected]915a59a12010-09-30 21:29:113595 texture_manager()->SetParameter(feature_info_, info, pname, *params);
[email protected]3916c97e2010-02-25 03:20:503596 glTexParameteriv(target, pname, params);
3597 }
3598}
3599
[email protected]939e7362010-05-13 20:49:103600bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]3916c97e2010-02-25 03:20:503601 if (!current_program_ || current_program_->IsDeleted()) {
[email protected]939e7362010-05-13 20:49:103602 // The program does not exist.
3603 SetGLError(GL_INVALID_OPERATION,
3604 (std::string(function_name) + ": no program in use").c_str());
3605 return false;
3606 }
3607 if (!current_program_->IsValid()) {
3608 SetGLError(GL_INVALID_OPERATION,
3609 (std::string(function_name) + ": program not linked").c_str());
3610 return false;
3611 }
3612 return true;
3613}
3614
3615bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
3616 GLint location, const char* function_name) {
3617 if (!CheckCurrentProgram(function_name)) {
3618 return false;
3619 }
3620 return location != -1;
3621}
3622
3623bool GLES2DecoderImpl::GetUniformTypeByLocation(
3624 GLint location, const char* function_name, GLenum* type) {
3625 if (!CheckCurrentProgramForUniform(location, function_name)) {
3626 return false;
3627 }
3628 if (!current_program_->GetUniformTypeByLocation(location, type)) {
3629 SetGLError(GL_INVALID_OPERATION,
3630 (std::string(function_name) + ": program not linked").c_str());
3631 return false;
3632 }
3633 return true;
3634}
3635
3636
3637void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
3638 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:503639 return;
3640 }
3641 current_program_->SetSamplers(location, 1, &v0);
3642 glUniform1i(location, v0);
3643}
3644
3645void GLES2DecoderImpl::DoUniform1iv(
3646 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:103647 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:503648 return;
3649 }
3650 current_program_->SetSamplers(location, count, value);
3651 glUniform1iv(location, count, value);
3652}
3653
[email protected]939e7362010-05-13 20:49:103654void GLES2DecoderImpl::DoUniform1fv(
3655 GLint location, GLsizei count, const GLfloat* value) {
3656 GLenum type;
3657 if (!GetUniformTypeByLocation(location, "glUniform1fv", &type)) {
3658 return;
3659 }
3660 if (type == GL_BOOL) {
3661 scoped_array<GLint> temp(new GLint[count]);
3662 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:533663 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103664 }
3665 DoUniform1iv(location, count, temp.get());
3666 } else {
3667 glUniform1fv(location, count, value);
3668 }
3669}
3670
3671void GLES2DecoderImpl::DoUniform2fv(
3672 GLint location, GLsizei count, const GLfloat* value) {
3673 GLenum type;
3674 if (!GetUniformTypeByLocation(location, "glUniform2fv", &type)) {
3675 return;
3676 }
3677 if (type == GL_BOOL_VEC2) {
3678 GLsizei num_values = count * 2;
3679 scoped_array<GLint> temp(new GLint[num_values]);
3680 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533681 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103682 }
3683 glUniform2iv(location, count, temp.get());
3684 } else {
3685 glUniform2fv(location, count, value);
3686 }
3687}
3688
3689void GLES2DecoderImpl::DoUniform3fv(
3690 GLint location, GLsizei count, const GLfloat* value) {
3691 GLenum type;
3692 if (!GetUniformTypeByLocation(location, "glUniform3fv", &type)) {
3693 return;
3694 }
3695 if (type == GL_BOOL_VEC3) {
3696 GLsizei num_values = count * 3;
3697 scoped_array<GLint> temp(new GLint[num_values]);
3698 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533699 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103700 }
3701 glUniform3iv(location, count, temp.get());
3702 } else {
3703 glUniform3fv(location, count, value);
3704 }
3705}
3706
3707void GLES2DecoderImpl::DoUniform4fv(
3708 GLint location, GLsizei count, const GLfloat* value) {
3709 GLenum type;
3710 if (!GetUniformTypeByLocation(location, "glUniform4fv", &type)) {
3711 return;
3712 }
3713 if (type == GL_BOOL_VEC4) {
3714 GLsizei num_values = count * 4;
3715 scoped_array<GLint> temp(new GLint[num_values]);
3716 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533717 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103718 }
3719 glUniform4iv(location, count, temp.get());
3720 } else {
3721 glUniform4fv(location, count, value);
3722 }
3723}
3724
[email protected]3916c97e2010-02-25 03:20:503725void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:033726 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:503727 ProgramManager::ProgramInfo* info = NULL;
3728 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:583729 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:503730 if (!info) {
[email protected]ae51d192010-04-27 00:48:033731 return;
3732 }
3733 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:503734 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:293735 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:503736 return;
3737 }
[email protected]ae51d192010-04-27 00:48:033738 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:503739 }
3740 current_program_ = info;
[email protected]ae51d192010-04-27 00:48:033741 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:503742}
3743
[email protected]96449d2c2009-11-25 00:01:323744GLenum GLES2DecoderImpl::GetGLError() {
3745 // Check the GL error first, then our wrapped error.
3746 GLenum error = glGetError();
3747 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:373748 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:323749 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:293750 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:323751 break;
3752 }
3753 }
3754 }
3755
3756 if (error != GL_NO_ERROR) {
3757 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:293758 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:323759 }
3760 return error;
3761}
3762
[email protected]8eee29c2010-04-29 03:38:293763void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
3764 if (msg) {
3765 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:013766 LOG(ERROR) << last_error_;
[email protected]8eee29c2010-04-29 03:38:293767 }
[email protected]ddd968b82010-03-02 00:44:293768 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:323769}
3770
[email protected]07f54fcc2009-12-22 02:46:303771void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
3772 GLenum error;
3773 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:293774 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:303775 }
3776}
3777
[email protected]6217d392010-03-25 22:08:353778void GLES2DecoderImpl::ClearRealGLErrors() {
3779 GLenum error;
3780 while ((error = glGetError()) != GL_NO_ERROR) {
3781 NOTREACHED() << "GL error " << error << " was unhandled.";
3782 }
3783}
3784
[email protected]ef526492010-06-02 23:12:253785bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:503786 DCHECK(current_program_);
3787 DCHECK(!current_program_->IsDeleted());
[email protected]ef526492010-06-02 23:12:253788 // Only check if there are some unrenderable textures.
3789 if (!texture_manager()->HaveUnrenderableTextures()) {
3790 return false;
3791 }
3792 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:503793 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
3794 current_program_->sampler_indices();
3795 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
3796 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
3797 current_program_->GetUniformInfo(sampler_indices[ii]);
3798 DCHECK(uniform_info);
3799 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
3800 GLuint texture_unit_index = uniform_info->texture_units[jj];
3801 if (texture_unit_index < group_->max_texture_units()) {
3802 TextureUnit& texture_unit = texture_units_[texture_unit_index];
3803 TextureManager::TextureInfo* texture_info =
3804 uniform_info->type == GL_SAMPLER_2D ?
3805 texture_unit.bound_texture_2d :
3806 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:113807 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]ef526492010-06-02 23:12:253808 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:503809 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
3810 glBindTexture(
3811 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
3812 GL_TEXTURE_CUBE_MAP,
[email protected]00f893d2010-08-24 18:55:493813 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:503814 }
3815 }
3816 // else: should this be an error?
3817 }
3818 }
[email protected]ef526492010-06-02 23:12:253819 return textures_set;
[email protected]3916c97e2010-02-25 03:20:503820}
3821
3822void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
3823 DCHECK(current_program_);
3824 DCHECK(!current_program_->IsDeleted());
3825 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
3826 current_program_->sampler_indices();
3827 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
3828 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
3829 current_program_->GetUniformInfo(sampler_indices[ii]);
3830 DCHECK(uniform_info);
3831 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
3832 GLuint texture_unit_index = uniform_info->texture_units[jj];
3833 if (texture_unit_index < group_->max_texture_units()) {
3834 TextureUnit& texture_unit = texture_units_[texture_unit_index];
3835 TextureManager::TextureInfo* texture_info =
3836 uniform_info->type == GL_SAMPLER_2D ?
3837 texture_unit.bound_texture_2d :
3838 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:113839 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]3916c97e2010-02-25 03:20:503840 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
3841 // Get the texture info that was previously bound here.
3842 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
3843 texture_unit.bound_texture_2d :
3844 texture_unit.bound_texture_cube_map;
3845 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:033846 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:503847 }
3848 }
3849 }
3850 }
3851 // Set the active texture back to whatever the user had it as.
3852 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:303853}
3854
3855bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:033856 // NOTE: We specifically do not check current_program->IsValid() because
3857 // it could never be invalid since glUseProgram would have failed. While
3858 // glLinkProgram could later mark the program as invalid the previous
3859 // valid program will still function if it is still the current program.
3860 if (!current_program_ || current_program_->IsDeleted()) {
[email protected]3916c97e2010-02-25 03:20:503861 // The program does not exist.
3862 // But GL says no ERROR.
3863 return false;
3864 }
[email protected]f39f4b3f2010-05-12 17:04:083865 // Validate all attribs currently enabled. If they are used by the current
3866 // program then check that they have enough elements to handle the draw call.
3867 // If they are not used by the current program check that they have a buffer
3868 // assigned.
3869 const VertexAttribManager::VertexAttribInfoList& infos =
3870 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
3871 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
3872 infos.begin(); it != infos.end(); ++it) {
3873 const VertexAttribManager::VertexAttribInfo* info = *it;
3874 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
3875 current_program_->GetAttribInfoByLocation(info->index());
3876 if (attrib_info) {
3877 // This attrib is used in the current program.
3878 if (!info->CanAccess(max_vertex_accessed)) {
3879 SetGLError(GL_INVALID_OPERATION,
3880 "glDrawXXX: attempt to access out of range vertices");
3881 return false;
3882 }
3883 } else {
3884 // This attrib is not used in the current program.
3885 if (!info->buffer() || info->buffer()->IsDeleted()) {
3886 SetGLError(
3887 GL_INVALID_OPERATION,
3888 "glDrawXXX: attempt to render with no buffer attached to enabled "
3889 "attrib");
3890 return false;
3891 }
[email protected]1d32bc82010-01-13 22:06:463892 }
[email protected]07f54fcc2009-12-22 02:46:303893 }
[email protected]3916c97e2010-02-25 03:20:503894 return true;
[email protected]b1122982010-05-17 23:04:243895}
3896
3897bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
[email protected]876f6fee2010-08-02 23:10:323898 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
3899 return false;
3900
[email protected]b1122982010-05-17 23:04:243901 const VertexAttribManager::VertexAttribInfo* info =
3902 vertex_attrib_manager_.GetVertexAttribInfo(0);
3903 // If it's enabled or it's not used then we don't need to do anything.
3904 if (info->enabled() || !current_program_->GetAttribInfoByLocation(0)) {
3905 return false;
3906 }
3907
3908 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
3909
3910 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
3911
3912 // Make a buffer with a single repeated vec4 value enough to
3913 // simulate the constant value that is supposed to be here.
3914 // This is required to emulate GLES2 on GL.
3915 GLsizei num_vertices = max_vertex_accessed + 1;
3916 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
3917 if (size_needed > attrib_0_size_ ||
3918 info->value().v[0] != attrib_0_value_.v[0] ||
3919 info->value().v[1] != attrib_0_value_.v[1] ||
3920 info->value().v[2] != attrib_0_value_.v[2] ||
3921 info->value().v[3] != attrib_0_value_.v[3]) {
3922 scoped_array<Vec4> temp(new Vec4[num_vertices]);
3923 for (GLsizei ii = 0; ii < num_vertices; ++ii) {
3924 temp[ii] = info->value();
3925 }
3926 glBufferData(
3927 GL_ARRAY_BUFFER,
3928 size_needed,
3929 &temp[0].v[0],
3930 GL_DYNAMIC_DRAW);
3931 attrib_0_value_ = info->value();
3932 attrib_0_size_ = size_needed;
3933 }
3934
3935 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
3936
3937 return true;
[email protected]b1122982010-05-17 23:04:243938}
3939
3940void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
3941 const VertexAttribManager::VertexAttribInfo* info =
3942 vertex_attrib_manager_.GetVertexAttribInfo(0);
3943 const void* ptr = reinterpret_cast<const void*>(info->offset());
3944 BufferManager::BufferInfo* buffer_info = info->buffer();
3945 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
3946 glVertexAttribPointer(
3947 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
3948 ptr);
3949 glBindBuffer(GL_ARRAY_BUFFER,
3950 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
3951}
[email protected]07f54fcc2009-12-22 02:46:303952
[email protected]f7a64ee2010-02-01 22:24:143953error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:193954 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:503955 if (!bound_element_array_buffer_ ||
3956 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:293957 SetGLError(GL_INVALID_OPERATION,
3958 "glDrawElements: No element array buffer bound");
3959 return error::kNoError;
3960 }
3961
3962 GLenum mode = c.mode;
3963 GLsizei count = c.count;
3964 GLenum type = c.type;
3965 int32 offset = c.index_offset;
3966 if (count < 0) {
3967 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
3968 return error::kNoError;
3969 }
3970 if (offset < 0) {
3971 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
3972 return error::kNoError;
3973 }
[email protected]9438b012010-06-15 22:55:053974 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:293975 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
3976 return error::kNoError;
3977 }
[email protected]9438b012010-06-15 22:55:053978 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:293979 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
3980 return error::kNoError;
3981 }
3982
[email protected]6c788fb72010-08-26 02:16:313983 if (count == 0) {
3984 return error::kNoError;
3985 }
3986
[email protected]8eee29c2010-04-29 03:38:293987 GLuint max_vertex_accessed;
3988 if (!bound_element_array_buffer_->GetMaxValueForRange(
3989 offset, count, type, &max_vertex_accessed)) {
3990 SetGLError(GL_INVALID_OPERATION,
3991 "glDrawElements: range out of bounds for buffer");
3992 return error::kNoError;
3993 }
3994
3995 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:243996 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]ef526492010-06-02 23:12:253997 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]8eee29c2010-04-29 03:38:293998 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
3999 glDrawElements(mode, count, type, indices);
[email protected]ef526492010-06-02 23:12:254000 if (textures_set) {
[email protected]8eee29c2010-04-29 03:38:294001 RestoreStateForNonRenderableTextures();
[email protected]ba3176a2009-12-16 18:19:464002 }
[email protected]b1122982010-05-17 23:04:244003 if (simulated_attrib_0) {
4004 RestoreStateForSimulatedAttrib0();
4005 }
[email protected]96449d2c2009-11-25 00:01:324006 }
[email protected]f7a64ee2010-02-01 22:24:144007 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324008}
4009
[email protected]29a9eb52010-04-13 09:04:234010GLuint GLES2DecoderImpl::DoGetMaxValueInBuffer(
4011 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
4012 GLuint max_vertex_accessed = 0;
4013 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:294014 if (!info) {
[email protected]ae51d192010-04-27 00:48:034015 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294016 SetGLError(GL_INVALID_VALUE,
4017 "GetMaxValueInBuffer: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:234018 } else {
4019 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:034020 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294021 SetGLError(GL_INVALID_OPERATION,
4022 "GetMaxValueInBuffer: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:234023 }
4024 }
4025 return max_vertex_accessed;
4026}
4027
[email protected]96449d2c2009-11-25 00:01:324028// Calls glShaderSource for the various versions of the ShaderSource command.
4029// Assumes that data / data_size points to a piece of memory that is in range
4030// of whatever context it came from (shared memory, immediate memory, bucket
4031// memory.)
[email protected]45bf5152010-02-12 00:11:314032error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034033 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:584034 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4035 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:314036 if (!info) {
[email protected]45bf5152010-02-12 00:11:314037 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324038 }
[email protected]45bf5152010-02-12 00:11:314039 // Note: We don't actually call glShaderSource here. We wait until
4040 // the call to glCompileShader.
4041 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:144042 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324043}
4044
[email protected]f7a64ee2010-02-01 22:24:144045error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:194046 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:324047 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314048 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:324049 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:464050 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144051 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324052 }
[email protected]ae51d192010-04-27 00:48:034053 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:324054}
4055
[email protected]f7a64ee2010-02-01 22:24:144056error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:194057 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:324058 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314059 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:304060 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464061 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144062 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324063 }
[email protected]ae51d192010-04-27 00:48:034064 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:314065}
4066
[email protected]558847a2010-03-24 07:02:544067error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
4068 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:544069 Bucket* bucket = GetBucket(c.data_bucket_id);
4070 if (!bucket || bucket->size() == 0) {
4071 return error::kInvalidArguments;
4072 }
4073 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034074 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:544075 bucket->size() - 1);
4076}
4077
[email protected]ae51d192010-04-27 00:48:034078void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584079 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4080 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:314081 if (!info) {
[email protected]45bf5152010-02-12 00:11:314082 return;
4083 }
[email protected]de17df392010-04-23 21:09:414084 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
4085 // glShaderSource and then glCompileShader.
4086 const char* shader_src = info->source().c_str();
[email protected]f57bb282010-11-12 00:51:344087 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:184088 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:344089 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:454090 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:234091
[email protected]a550584e2010-09-17 18:01:454092 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:344093 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:184094 return;
4095 }
[email protected]a550584e2010-09-17 18:01:454096 shader_src = translator->translated_shader();
[email protected]de17df392010-04-23 21:09:414097 }
[email protected]de17df392010-04-23 21:09:414098
[email protected]ae51d192010-04-27 00:48:034099 glShaderSource(info->service_id(), 1, &shader_src, NULL);
4100 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:414101 GLint status = GL_FALSE;
4102 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
4103 if (status) {
[email protected]f57bb282010-11-12 00:51:344104 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:414105 } else {
[email protected]d9977d42010-09-01 20:27:024106 // We cannot reach here if we are using the shader translator.
4107 // All invalid shaders must be rejected by the translator.
4108 // All translated shaders must compile.
4109 LOG_IF(ERROR, use_shader_translator_)
4110 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:334111 GLint max_len = 0;
4112 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
4113 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:414114 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:334115 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
4116 DCHECK(max_len == 0 || len < max_len);
4117 DCHECK(len ==0 || temp[len] == '\0');
[email protected]f57bb282010-11-12 00:51:344118 info->SetStatus(false, std::string(temp.get(), len), NULL);
[email protected]e5186162010-06-14 18:54:414119 }
[email protected]45bf5152010-02-12 00:11:314120};
4121
[email protected]ddd968b82010-03-02 00:44:294122void GLES2DecoderImpl::DoGetShaderiv(
4123 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:584124 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4125 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:294126 if (!info) {
[email protected]ddd968b82010-03-02 00:44:294127 return;
4128 }
[email protected]8f1ccdac2010-05-19 21:01:484129 switch (pname) {
4130 case GL_SHADER_SOURCE_LENGTH:
4131 *params = info->source().size();
4132 return;
4133 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:414134 *params = info->IsValid();
4135 return;
[email protected]8f1ccdac2010-05-19 21:01:484136 case GL_INFO_LOG_LENGTH:
[email protected]e5186162010-06-14 18:54:414137 *params = info->log_info().size() + 1;
4138 return;
[email protected]8f1ccdac2010-05-19 21:01:484139 default:
4140 break;
[email protected]ddd968b82010-03-02 00:44:294141 }
[email protected]8f1ccdac2010-05-19 21:01:484142 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:294143}
4144
[email protected]ae51d192010-04-27 00:48:034145error::Error GLES2DecoderImpl::HandleGetShaderSource(
4146 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
4147 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:034148 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4149 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:584150 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4151 shader, "glGetShaderSource");
[email protected]8eee29c2010-04-29 03:38:294152 if (!info) {
4153 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:294154 return error::kNoError;
4155 }
[email protected]ae51d192010-04-27 00:48:034156 bucket->SetFromString(info->source());
4157 return error::kNoError;
4158}
4159
4160error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
4161 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
4162 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:584163 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4164 Bucket* bucket = CreateBucket(bucket_id);
4165 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4166 program, "glGetProgramInfoLog");
[email protected]ae51d192010-04-27 00:48:034167 if (!info) {
[email protected]ae51d192010-04-27 00:48:034168 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:314169 }
[email protected]e5186162010-06-14 18:54:414170 bucket->SetFromString(info->log_info());
[email protected]ae51d192010-04-27 00:48:034171 return error::kNoError;
4172}
4173
4174error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
4175 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
4176 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:584177 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4178 Bucket* bucket = CreateBucket(bucket_id);
4179 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4180 shader, "glGetShaderInfoLog");
[email protected]ae51d192010-04-27 00:48:034181 if (!info) {
[email protected]6b8cf1a2010-05-06 16:13:584182 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034183 return error::kNoError;
4184 }
[email protected]e5186162010-06-14 18:54:414185 bucket->SetFromString(info->log_info());
[email protected]ae51d192010-04-27 00:48:034186 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324187}
4188
[email protected]1958e0e2010-04-22 05:17:154189bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:034190 return GetBufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154191}
4192
4193bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:034194 return GetFramebufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154195}
4196
4197bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:034198 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154199}
4200
4201bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:034202 return GetRenderbufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154203}
4204
4205bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:034206 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154207}
4208
4209bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:034210 return GetTextureInfo(client_id) != NULL;
4211}
4212
4213void GLES2DecoderImpl::DoAttachShader(
4214 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584215 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4216 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034217 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034218 return;
[email protected]1958e0e2010-04-22 05:17:154219 }
[email protected]6b8cf1a2010-05-06 16:13:584220 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4221 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034222 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034223 return;
4224 }
[email protected]fb96c8e2010-08-12 04:10:314225 if (!program_info->AttachShader(shader_info)) {
4226 SetGLError(GL_INVALID_OPERATION,
4227 "glAttachShader: can not attach more than"
4228 " one shader of the same type.");
4229 return;
4230 }
[email protected]ae51d192010-04-27 00:48:034231 glAttachShader(program_info->service_id(), shader_info->service_id());
4232}
4233
4234void GLES2DecoderImpl::DoDetachShader(
4235 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584236 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4237 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034238 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034239 return;
4240 }
[email protected]6b8cf1a2010-05-06 16:13:584241 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4242 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034243 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034244 return;
4245 }
[email protected]d81e8c52010-06-07 17:58:324246 program_info->DetachShader(shader_info);
[email protected]ae51d192010-04-27 00:48:034247 glDetachShader(program_info->service_id(), shader_info->service_id());
4248}
4249
4250void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584251 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4252 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:034253 if (!info) {
[email protected]ae51d192010-04-27 00:48:034254 return;
4255 }
[email protected]e5186162010-06-14 18:54:414256 if (!info->CanLink()) {
4257 info->set_log_info("Missing Shader");
4258 return;
4259 }
[email protected]ae51d192010-04-27 00:48:034260 glValidateProgram(info->service_id());
[email protected]e5186162010-06-14 18:54:414261 info->UpdateLogInfo();
[email protected]1958e0e2010-04-22 05:17:154262}
4263
[email protected]b1122982010-05-17 23:04:244264void GLES2DecoderImpl::DoGetVertexAttribfv(
4265 GLuint index, GLenum pname, GLfloat* params) {
4266 VertexAttribManager::VertexAttribInfo* info =
4267 vertex_attrib_manager_.GetVertexAttribInfo(index);
4268 if (!info) {
4269 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
4270 return;
4271 }
4272 switch (pname) {
4273 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4274 BufferManager::BufferInfo* buffer = info->buffer();
4275 if (buffer && !buffer->IsDeleted()) {
4276 GLuint client_id;
4277 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4278 *params = static_cast<GLfloat>(client_id);
4279 }
4280 break;
4281 }
4282 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4283 *params = static_cast<GLfloat>(info->enabled());
4284 break;
4285 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4286 *params = static_cast<GLfloat>(info->size());
4287 break;
4288 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4289 *params = static_cast<GLfloat>(info->gl_stride());
4290 break;
4291 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4292 *params = static_cast<GLfloat>(info->type());
4293 break;
4294 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4295 *params = static_cast<GLfloat>(info->normalized());
4296 break;
4297 case GL_CURRENT_VERTEX_ATTRIB:
4298 params[0] = info->value().v[0];
4299 params[1] = info->value().v[1];
4300 params[2] = info->value().v[2];
4301 params[3] = info->value().v[3];
4302 break;
4303 default:
4304 NOTREACHED();
4305 break;
4306 }
4307}
4308
4309void GLES2DecoderImpl::DoGetVertexAttribiv(
4310 GLuint index, GLenum pname, GLint* params) {
4311 VertexAttribManager::VertexAttribInfo* info =
4312 vertex_attrib_manager_.GetVertexAttribInfo(index);
4313 if (!info) {
4314 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
4315 return;
4316 }
4317 switch (pname) {
4318 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4319 BufferManager::BufferInfo* buffer = info->buffer();
4320 if (buffer && !buffer->IsDeleted()) {
4321 GLuint client_id;
4322 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4323 *params = client_id;
4324 }
4325 break;
4326 }
4327 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4328 *params = info->enabled();
4329 break;
4330 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4331 *params = info->size();
4332 break;
4333 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4334 *params = info->gl_stride();
4335 break;
4336 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4337 *params = info->type();
4338 break;
4339 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4340 *params = static_cast<GLint>(info->normalized());
4341 break;
4342 case GL_CURRENT_VERTEX_ATTRIB:
4343 params[0] = static_cast<GLint>(info->value().v[0]);
4344 params[1] = static_cast<GLint>(info->value().v[1]);
4345 params[2] = static_cast<GLint>(info->value().v[2]);
4346 params[3] = static_cast<GLint>(info->value().v[3]);
4347 break;
4348 default:
4349 NOTREACHED();
4350 break;
4351 }
4352}
4353
4354void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
4355 VertexAttribManager::VertexAttribInfo* info =
4356 vertex_attrib_manager_.GetVertexAttribInfo(index);
4357 if (!info) {
4358 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
4359 return;
4360 }
4361 VertexAttribManager::VertexAttribInfo::Vec4 value;
4362 value.v[0] = v0;
4363 value.v[1] = 0.0f;
4364 value.v[2] = 0.0f;
4365 value.v[3] = 1.0f;
4366 info->set_value(value);
4367 glVertexAttrib1f(index, v0);
4368}
4369
4370void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
4371 VertexAttribManager::VertexAttribInfo* info =
4372 vertex_attrib_manager_.GetVertexAttribInfo(index);
4373 if (!info) {
4374 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
4375 return;
4376 }
4377 VertexAttribManager::VertexAttribInfo::Vec4 value;
4378 value.v[0] = v0;
4379 value.v[1] = v1;
4380 value.v[2] = 0.0f;
4381 value.v[3] = 1.0f;
4382 info->set_value(value);
4383 glVertexAttrib2f(index, v0, v1);
4384}
4385
4386void GLES2DecoderImpl::DoVertexAttrib3f(
4387 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
4388 VertexAttribManager::VertexAttribInfo* info =
4389 vertex_attrib_manager_.GetVertexAttribInfo(index);
4390 if (!info) {
4391 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
4392 return;
4393 }
4394 VertexAttribManager::VertexAttribInfo::Vec4 value;
4395 value.v[0] = v0;
4396 value.v[1] = v1;
4397 value.v[2] = v2;
4398 value.v[3] = 1.0f;
4399 info->set_value(value);
4400 glVertexAttrib3f(index, v0, v1, v2);
4401}
4402
4403void GLES2DecoderImpl::DoVertexAttrib4f(
4404 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
4405 VertexAttribManager::VertexAttribInfo* info =
4406 vertex_attrib_manager_.GetVertexAttribInfo(index);
4407 if (!info) {
4408 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
4409 return;
4410 }
4411 VertexAttribManager::VertexAttribInfo::Vec4 value;
4412 value.v[0] = v0;
4413 value.v[1] = v1;
4414 value.v[2] = v2;
4415 value.v[3] = v3;
4416 info->set_value(value);
4417 glVertexAttrib4f(index, v0, v1, v2, v3);
4418}
4419
4420void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
4421 VertexAttribManager::VertexAttribInfo* info =
4422 vertex_attrib_manager_.GetVertexAttribInfo(index);
4423 if (!info) {
4424 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
4425 return;
4426 }
4427 VertexAttribManager::VertexAttribInfo::Vec4 value;
4428 value.v[0] = v[0];
4429 value.v[1] = 0.0f;
4430 value.v[2] = 0.0f;
4431 value.v[3] = 1.0f;
4432 info->set_value(value);
4433 glVertexAttrib1fv(index, v);
4434}
4435
4436void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
4437 VertexAttribManager::VertexAttribInfo* info =
4438 vertex_attrib_manager_.GetVertexAttribInfo(index);
4439 if (!info) {
4440 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
4441 return;
4442 }
4443 VertexAttribManager::VertexAttribInfo::Vec4 value;
4444 value.v[0] = v[0];
4445 value.v[1] = v[1];
4446 value.v[2] = 0.0f;
4447 value.v[3] = 1.0f;
4448 info->set_value(value);
4449 glVertexAttrib2fv(index, v);
4450}
4451
4452void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
4453 VertexAttribManager::VertexAttribInfo* info =
4454 vertex_attrib_manager_.GetVertexAttribInfo(index);
4455 if (!info) {
4456 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
4457 return;
4458 }
4459 VertexAttribManager::VertexAttribInfo::Vec4 value;
4460 value.v[0] = v[0];
4461 value.v[1] = v[1];
4462 value.v[2] = v[2];
4463 value.v[3] = 1.0f;
4464 info->set_value(value);
4465 glVertexAttrib3fv(index, v);
4466}
4467
4468void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
4469 VertexAttribManager::VertexAttribInfo* info =
4470 vertex_attrib_manager_.GetVertexAttribInfo(index);
4471 if (!info) {
4472 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
4473 return;
4474 }
4475 VertexAttribManager::VertexAttribInfo::Vec4 value;
4476 value.v[0] = v[0];
4477 value.v[1] = v[1];
4478 value.v[2] = v[2];
4479 value.v[3] = v[3];
4480 info->set_value(value);
4481 glVertexAttrib4fv(index, v);
4482}
4483
[email protected]f7a64ee2010-02-01 22:24:144484error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:194485 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:294486 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
4487 SetGLError(GL_INVALID_VALUE,
4488 "glVertexAttribPointer: no array buffer bound");
4489 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324490 }
[email protected]8eee29c2010-04-29 03:38:294491
4492 GLuint indx = c.indx;
4493 GLint size = c.size;
4494 GLenum type = c.type;
4495 GLboolean normalized = c.normalized;
4496 GLsizei stride = c.stride;
4497 GLsizei offset = c.offset;
4498 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:054499 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294500 SetGLError(GL_INVALID_ENUM,
4501 "glVertexAttribPointer: type GL_INVALID_ENUM");
4502 return error::kNoError;
4503 }
[email protected]9438b012010-06-15 22:55:054504 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]8eee29c2010-04-29 03:38:294505 SetGLError(GL_INVALID_ENUM,
4506 "glVertexAttribPointer: size GL_INVALID_VALUE");
4507 return error::kNoError;
4508 }
4509 if (indx >= group_->max_vertex_attribs()) {
4510 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
4511 return error::kNoError;
4512 }
4513 if (stride < 0) {
4514 SetGLError(GL_INVALID_VALUE,
4515 "glVertexAttribPointer: stride < 0");
4516 return error::kNoError;
4517 }
4518 if (stride > 255) {
4519 SetGLError(GL_INVALID_VALUE,
4520 "glVertexAttribPointer: stride > 255");
4521 return error::kNoError;
4522 }
4523 if (offset < 0) {
4524 SetGLError(GL_INVALID_VALUE,
4525 "glVertexAttribPointer: offset < 0");
4526 return error::kNoError;
4527 }
4528 GLsizei component_size =
4529 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:294530 if (offset % component_size > 0) {
4531 SetGLError(GL_INVALID_VALUE,
4532 "glVertexAttribPointer: stride not valid for type");
4533 return error::kNoError;
4534 }
[email protected]f39f4b3f2010-05-12 17:04:084535 vertex_attrib_manager_.GetVertexAttribInfo(indx)->SetInfo(
[email protected]8eee29c2010-04-29 03:38:294536 bound_array_buffer_,
4537 size,
4538 type,
[email protected]b1122982010-05-17 23:04:244539 normalized,
4540 stride,
4541 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:294542 offset);
4543 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
[email protected]f7a64ee2010-02-01 22:24:144544 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324545}
4546
[email protected]f7a64ee2010-02-01 22:24:144547error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:194548 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:314549 GLint x = c.x;
4550 GLint y = c.y;
4551 GLsizei width = c.width;
4552 GLsizei height = c.height;
4553 GLenum format = c.format;
4554 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:564555 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:294556 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:564557 return error::kNoError;
4558 }
[email protected]a51788e2010-02-24 21:54:254559 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:184560 uint32 pixels_size;
4561 if (!GLES2Util::ComputeImageDataSize(
4562 width, height, format, type, pack_alignment_, &pixels_size)) {
4563 return error::kOutOfBounds;
4564 }
[email protected]612d2f82009-12-08 20:49:314565 void* pixels = GetSharedMemoryAs<void*>(
4566 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:254567 Result* result = GetSharedMemoryAs<Result*>(
4568 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4569 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:144570 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464571 }
[email protected]a51788e2010-02-24 21:54:254572
[email protected]9438b012010-06-15 22:55:054573 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:294574 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
4575 return error::kNoError;
4576 }
[email protected]9438b012010-06-15 22:55:054577 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294578 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:124579 return error::kNoError;
4580 }
[email protected]57f223832010-03-19 01:57:564581 if (width == 0 || height == 0) {
4582 return error::kNoError;
4583 }
4584
4585 CopyRealGLErrorsToWrapper();
4586
[email protected]34ff8b0c2010-10-01 20:06:024587 ScopedResolvedFrameBufferBinder binder(this);
4588
[email protected]57f223832010-03-19 01:57:564589 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:304590 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:564591
4592 GLint max_x;
4593 GLint max_y;
4594 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:294595 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:144596 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:314597 }
[email protected]57f223832010-03-19 01:57:564598
[email protected]d37231fa2010-04-09 21:16:024599 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:564600 // The user requested an out of range area. Get the results 1 line
4601 // at a time.
4602 uint32 temp_size;
4603 if (!GLES2Util::ComputeImageDataSize(
4604 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:294605 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564606 return error::kNoError;
4607 }
4608 GLsizei unpadded_row_size = temp_size;
4609 if (!GLES2Util::ComputeImageDataSize(
4610 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:294611 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564612 return error::kNoError;
4613 }
4614 GLsizei padded_row_size = temp_size - unpadded_row_size;
4615 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:294616 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564617 return error::kNoError;
4618 }
4619
4620 GLint dest_x_offset = std::max(-x, 0);
4621 uint32 dest_row_offset;
4622 if (!GLES2Util::ComputeImageDataSize(
4623 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:294624 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564625 return error::kNoError;
4626 }
4627
4628 // Copy each row into the larger dest rect.
4629 int8* dst = static_cast<int8*>(pixels);
4630 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:024631 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:564632 GLint read_width = read_end_x - read_x;
4633 for (GLint yy = 0; yy < height; ++yy) {
4634 GLint ry = y + yy;
4635
4636 // Clear the row.
4637 memset(dst, 0, unpadded_row_size);
4638
4639 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:024640 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:564641 glReadPixels(
4642 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
4643 }
4644 dst += padded_row_size;
4645 }
4646 } else {
4647 glReadPixels(x, y, width, height, format, type, pixels);
4648 }
[email protected]a51788e2010-02-24 21:54:254649 GLenum error = glGetError();
4650 if (error == GL_NO_ERROR) {
4651 *result = true;
4652 } else {
[email protected]8eee29c2010-04-29 03:38:294653 SetGLError(error, NULL);
[email protected]a51788e2010-02-24 21:54:254654 }
[email protected]f7a64ee2010-02-01 22:24:144655 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324656}
4657
[email protected]f7a64ee2010-02-01 22:24:144658error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:194659 uint32 immediate_data_size, const gles2::PixelStorei& c) {
4660 GLenum pname = c.pname;
4661 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:054662 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:294663 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:124664 return error::kNoError;
4665 }
[email protected]9438b012010-06-15 22:55:054666 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:294667 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:144668 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194669 }
4670 glPixelStorei(pname, param);
4671 switch (pname) {
4672 case GL_PACK_ALIGNMENT:
4673 pack_alignment_ = param;
4674 break;
4675 case GL_UNPACK_ALIGNMENT:
4676 unpack_alignment_ = param;
4677 break;
4678 default:
4679 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:374680 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:194681 break;
4682 }
[email protected]f7a64ee2010-02-01 22:24:144683 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194684}
4685
[email protected]558847a2010-03-24 07:02:544686error::Error GLES2DecoderImpl::GetAttribLocationHelper(
4687 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
4688 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:584689 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4690 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:034691 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:144692 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194693 }
[email protected]ae51d192010-04-27 00:48:034694 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:294695 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:254696 return error::kNoError;
4697 }
[email protected]b9849abf2009-11-25 19:13:194698 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:544699 location_shm_id, location_shm_offset, sizeof(GLint));
4700 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:144701 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194702 }
[email protected]558847a2010-03-24 07:02:544703 // Require the client to init this incase the context is lost and we are no
4704 // longer executing commands.
4705 if (*location != -1) {
4706 return error::kGenericError;
4707 }
[email protected]0bfd9882010-02-05 23:02:254708 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:144709 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194710}
4711
[email protected]558847a2010-03-24 07:02:544712error::Error GLES2DecoderImpl::HandleGetAttribLocation(
4713 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
4714 uint32 name_size = c.data_size;
4715 const char* name = GetSharedMemoryAs<const char*>(
4716 c.name_shm_id, c.name_shm_offset, name_size);
4717 if (!name) {
4718 return error::kOutOfBounds;
4719 }
4720 String name_str(name, name_size);
4721 return GetAttribLocationHelper(
4722 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4723}
4724
[email protected]f7a64ee2010-02-01 22:24:144725error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:194726 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:544727 uint32 name_size = c.data_size;
4728 const char* name = GetImmediateDataAs<const char*>(
4729 c, name_size, immediate_data_size);
4730 if (!name) {
4731 return error::kOutOfBounds;
4732 }
4733 String name_str(name, name_size);
4734 return GetAttribLocationHelper(
4735 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4736}
4737
4738error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
4739 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
4740 Bucket* bucket = GetBucket(c.name_bucket_id);
4741 if (!bucket) {
4742 return error::kInvalidArguments;
4743 }
4744 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184745 if (!bucket->GetAsString(&name_str)) {
4746 return error::kInvalidArguments;
4747 }
[email protected]558847a2010-03-24 07:02:544748 return GetAttribLocationHelper(
4749 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4750}
4751
4752error::Error GLES2DecoderImpl::GetUniformLocationHelper(
4753 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
4754 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:584755 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4756 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:034757 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:144758 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194759 }
[email protected]ae51d192010-04-27 00:48:034760 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:294761 SetGLError(GL_INVALID_OPERATION,
4762 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:254763 return error::kNoError;
4764 }
[email protected]b9849abf2009-11-25 19:13:194765 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:544766 location_shm_id, location_shm_offset, sizeof(GLint));
4767 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:144768 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194769 }
[email protected]558847a2010-03-24 07:02:544770 // Require the client to init this incase the context is lost an we are no
4771 // longer executing commands.
4772 if (*location != -1) {
4773 return error::kGenericError;
4774 }
4775 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:144776 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194777}
4778
[email protected]f7a64ee2010-02-01 22:24:144779error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:194780 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:194781 uint32 name_size = c.data_size;
4782 const char* name = GetSharedMemoryAs<const char*>(
4783 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:544784 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:144785 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194786 }
4787 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:544788 return GetUniformLocationHelper(
4789 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:194790}
4791
[email protected]f7a64ee2010-02-01 22:24:144792error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:194793 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:194794 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:304795 const char* name = GetImmediateDataAs<const char*>(
4796 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:544797 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:144798 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194799 }
4800 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:544801 return GetUniformLocationHelper(
4802 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4803}
4804
4805error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
4806 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
4807 Bucket* bucket = GetBucket(c.name_bucket_id);
4808 if (!bucket) {
4809 return error::kInvalidArguments;
4810 }
4811 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184812 if (!bucket->GetAsString(&name_str)) {
4813 return error::kInvalidArguments;
4814 }
[email protected]558847a2010-03-24 07:02:544815 return GetUniformLocationHelper(
4816 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:194817}
4818
[email protected]ddd968b82010-03-02 00:44:294819error::Error GLES2DecoderImpl::HandleGetString(
4820 uint32 immediate_data_size, const gles2::GetString& c) {
4821 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:054822 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:294823 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:294824 return error::kNoError;
4825 }
[email protected]1958e0e2010-04-22 05:17:154826 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
4827 const char* str = NULL;
4828 switch (name) {
4829 case GL_VERSION:
4830 str = "OpenGL ES 2.0 Chromium";
4831 break;
4832 case GL_SHADING_LANGUAGE_VERSION:
4833 str = "OpenGL ES GLSL ES 1.0 Chromium";
4834 break;
4835 case GL_EXTENSIONS:
[email protected]915a59a12010-09-30 21:29:114836 str = feature_info_->extensions().c_str();
[email protected]1958e0e2010-04-22 05:17:154837 break;
4838 default:
4839 str = gl_str;
4840 break;
4841 }
[email protected]ddd968b82010-03-02 00:44:294842 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:154843 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:294844 return error::kNoError;
4845}
4846
[email protected]0c86dbf2010-03-05 08:14:114847void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:154848 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:054849 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:294850 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
4851 return;
4852 }
[email protected]9438b012010-06-15 22:55:054853 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:294854 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:114855 return;
[email protected]3b6ec202010-03-05 05:16:234856 }
4857 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:294858 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:284859 return;
[email protected]3b6ec202010-03-05 05:16:234860 }
4861 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
4862 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294863 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:284864 return;
[email protected]3b6ec202010-03-05 05:16:234865 }
4866 // Clear the buffer to 0 if no initial data was passed in.
4867 scoped_array<int8> zero;
4868 if (!data) {
4869 zero.reset(new int8[size]);
4870 memset(zero.get(), 0, size);
4871 data = zero.get();
4872 }
4873 CopyRealGLErrorsToWrapper();
4874 glBufferData(target, size, data, usage);
4875 GLenum error = glGetError();
4876 if (error != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294877 SetGLError(error, NULL);
[email protected]3b6ec202010-03-05 05:16:234878 } else {
[email protected]4e8a5b122010-05-08 22:00:104879 buffer_manager()->SetSize(info, size);
[email protected]0c86dbf2010-03-05 08:14:114880 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:234881 }
[email protected]0c86dbf2010-03-05 08:14:114882}
4883
4884error::Error GLES2DecoderImpl::HandleBufferData(
4885 uint32 immediate_data_size, const gles2::BufferData& c) {
4886 GLenum target = static_cast<GLenum>(c.target);
4887 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
4888 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
4889 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
4890 GLenum usage = static_cast<GLenum>(c.usage);
4891 const void* data = NULL;
4892 if (data_shm_id != 0 || data_shm_offset != 0) {
4893 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
4894 if (!data) {
4895 return error::kOutOfBounds;
4896 }
4897 }
4898 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:144899 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194900}
4901
[email protected]f7a64ee2010-02-01 22:24:144902error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:194903 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
4904 GLenum target = static_cast<GLenum>(c.target);
4905 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:304906 const void* data = GetImmediateDataAs<const void*>(
4907 c, size, immediate_data_size);
4908 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144909 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:304910 }
[email protected]b9849abf2009-11-25 19:13:194911 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:114912 DoBufferData(target, size, data, usage);
4913 return error::kNoError;
4914}
4915
4916void GLES2DecoderImpl::DoBufferSubData(
4917 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:504918 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474919 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294920 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:284921 return;
[email protected]a93bb842010-02-16 23:03:474922 }
[email protected]0c86dbf2010-03-05 08:14:114923 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:294924 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]07f54fcc2009-12-22 02:46:304925 } else {
[email protected]0c86dbf2010-03-05 08:14:114926 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:304927 }
[email protected]b9849abf2009-11-25 19:13:194928}
4929
[email protected]a93bb842010-02-16 23:03:474930error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
4931 GLenum target,
4932 GLint level,
4933 GLenum internal_format,
4934 GLsizei width,
4935 GLsizei height,
4936 GLint border,
4937 GLsizei image_size,
4938 const void* data) {
[email protected]a93bb842010-02-16 23:03:474939 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:054940 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:294941 SetGLError(GL_INVALID_ENUM,
4942 "glCompressedTexImage2D: target GL_INVALID_ENUM");
4943 return error::kNoError;
4944 }
[email protected]9438b012010-06-15 22:55:054945 if (!validators_->compressed_texture_format.IsValid(
4946 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:294947 SetGLError(GL_INVALID_ENUM,
4948 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:474949 return error::kNoError;
4950 }
[email protected]915a59a12010-09-30 21:29:114951 if (!texture_manager()->ValidForTarget(
4952 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:474953 border != 0) {
[email protected]8eee29c2010-04-29 03:38:294954 SetGLError(GL_INVALID_VALUE,
4955 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:474956 return error::kNoError;
4957 }
[email protected]3916c97e2010-02-25 03:20:504958 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474959 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294960 SetGLError(GL_INVALID_VALUE,
4961 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:474962 return error::kNoError;
4963 }
4964 scoped_array<int8> zero;
4965 if (!data) {
4966 zero.reset(new int8[image_size]);
4967 memset(zero.get(), 0, image_size);
4968 data = zero.get();
4969 }
[email protected]cadde4a2010-07-31 17:10:434970 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:474971 glCompressedTexImage2D(
4972 target, level, internal_format, width, height, border, image_size, data);
[email protected]cadde4a2010-07-31 17:10:434973 GLenum error = glGetError();
4974 if (error == GL_NO_ERROR) {
4975 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:114976 feature_info_,
[email protected]cadde4a2010-07-31 17:10:434977 info, target, level, internal_format, width, height, 1, border, 0, 0);
4978 }
[email protected]a93bb842010-02-16 23:03:474979 return error::kNoError;
4980}
4981
[email protected]f7a64ee2010-02-01 22:24:144982error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194983 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
4984 GLenum target = static_cast<GLenum>(c.target);
4985 GLint level = static_cast<GLint>(c.level);
4986 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4987 GLsizei width = static_cast<GLsizei>(c.width);
4988 GLsizei height = static_cast<GLsizei>(c.height);
4989 GLint border = static_cast<GLint>(c.border);
4990 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
4991 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
4992 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
4993 const void* data = NULL;
4994 if (data_shm_id != 0 || data_shm_offset != 0) {
4995 data = GetSharedMemoryAs<const void*>(
4996 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:464997 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144998 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194999 }
5000 }
[email protected]a93bb842010-02-16 23:03:475001 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195002 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:195003}
5004
[email protected]f7a64ee2010-02-01 22:24:145005error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195006 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
5007 GLenum target = static_cast<GLenum>(c.target);
5008 GLint level = static_cast<GLint>(c.level);
5009 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5010 GLsizei width = static_cast<GLsizei>(c.width);
5011 GLsizei height = static_cast<GLsizei>(c.height);
5012 GLint border = static_cast<GLint>(c.border);
5013 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:305014 const void* data = GetImmediateDataAs<const void*>(
5015 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465016 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145017 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465018 }
[email protected]a93bb842010-02-16 23:03:475019 return DoCompressedTexImage2D(
5020 target, level, internal_format, width, height, border, image_size, data);
5021}
5022
[email protected]b6140d02010-05-17 14:47:165023error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
5024 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
5025 GLenum target = static_cast<GLenum>(c.target);
5026 GLint level = static_cast<GLint>(c.level);
5027 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5028 GLsizei width = static_cast<GLsizei>(c.width);
5029 GLsizei height = static_cast<GLsizei>(c.height);
5030 GLint border = static_cast<GLint>(c.border);
5031 Bucket* bucket = GetBucket(c.bucket_id);
5032 return DoCompressedTexImage2D(
5033 target, level, internal_format, width, height, border,
5034 bucket->size(), bucket->GetData(0, bucket->size()));
5035}
5036
5037error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
5038 uint32 immediate_data_size,
5039 const gles2::CompressedTexSubImage2DBucket& c) {
5040 GLenum target = static_cast<GLenum>(c.target);
5041 GLint level = static_cast<GLint>(c.level);
5042 GLint xoffset = static_cast<GLint>(c.xoffset);
5043 GLint yoffset = static_cast<GLint>(c.yoffset);
5044 GLsizei width = static_cast<GLsizei>(c.width);
5045 GLsizei height = static_cast<GLsizei>(c.height);
5046 GLenum format = static_cast<GLenum>(c.format);
5047 Bucket* bucket = GetBucket(c.bucket_id);
5048 uint32 data_size = bucket->size();
5049 GLsizei imageSize = data_size;
5050 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:055051 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:165052 SetGLError(
5053 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
5054 return error::kNoError;
5055 }
[email protected]9438b012010-06-15 22:55:055056 if (!validators_->compressed_texture_format.IsValid(format)) {
5057 SetGLError(GL_INVALID_ENUM,
5058 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
5059 return error::kNoError;
5060 }
[email protected]b6140d02010-05-17 14:47:165061 if (width < 0) {
5062 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
5063 return error::kNoError;
5064 }
5065 if (height < 0) {
5066 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
5067 return error::kNoError;
5068 }
5069 if (imageSize < 0) {
5070 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
5071 return error::kNoError;
5072 }
[email protected]cadde4a2010-07-31 17:10:435073 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:165074 target, level, xoffset, yoffset, width, height, format, imageSize, data);
5075 return error::kNoError;
5076}
5077
[email protected]a93bb842010-02-16 23:03:475078error::Error GLES2DecoderImpl::DoTexImage2D(
5079 GLenum target,
5080 GLint level,
5081 GLenum internal_format,
5082 GLsizei width,
5083 GLsizei height,
5084 GLint border,
5085 GLenum format,
5086 GLenum type,
5087 const void* pixels,
5088 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:055089 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295090 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
5091 return error::kNoError;
5092 }
[email protected]9438b012010-06-15 22:55:055093 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295094 SetGLError(GL_INVALID_ENUM,
5095 "glTexImage2D: internal_format GL_INVALID_ENUM");
5096 return error::kNoError;
5097 }
[email protected]9438b012010-06-15 22:55:055098 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295099 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
5100 return error::kNoError;
5101 }
[email protected]9438b012010-06-15 22:55:055102 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295103 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145104 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195105 }
[email protected]7b92c412010-07-20 17:48:255106 if (format != internal_format) {
5107 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
5108 return error::kNoError;
5109 }
[email protected]915a59a12010-09-30 21:29:115110 if (!texture_manager()->ValidForTarget(
5111 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475112 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295113 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475114 return error::kNoError;
5115 }
[email protected]3916c97e2010-02-25 03:20:505116 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475117 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295118 SetGLError(GL_INVALID_OPERATION,
5119 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:475120 return error::kNoError;
5121 }
5122 scoped_array<int8> zero;
5123 if (!pixels) {
5124 zero.reset(new int8[pixels_size]);
5125 memset(zero.get(), 0, pixels_size);
5126 pixels = zero.get();
5127 }
[email protected]876f6fee2010-08-02 23:10:325128
[email protected]f5719fb2010-08-04 18:27:185129 GLenum gl_internal_format = internal_format;
[email protected]876f6fee2010-08-02 23:10:325130 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
5131 if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
[email protected]f5719fb2010-08-04 18:27:185132 gl_internal_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:325133 } else if (type == GL_FLOAT) {
5134 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:185135 gl_internal_format = GL_RGBA32F_ARB;
[email protected]876f6fee2010-08-02 23:10:325136 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:185137 gl_internal_format = GL_RGB32F_ARB;
[email protected]876f6fee2010-08-02 23:10:325138 }
5139 } else if (type == GL_HALF_FLOAT_OES) {
5140 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:185141 gl_internal_format = GL_RGBA16F_ARB;
[email protected]876f6fee2010-08-02 23:10:325142 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:185143 gl_internal_format = GL_RGB16F_ARB;
[email protected]876f6fee2010-08-02 23:10:325144 }
[email protected]7b92c412010-07-20 17:48:255145 }
[email protected]7488d962010-07-16 02:41:585146 }
[email protected]876f6fee2010-08-02 23:10:325147
[email protected]cadde4a2010-07-31 17:10:435148 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475149 glTexImage2D(
[email protected]f5719fb2010-08-04 18:27:185150 target, level, gl_internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475151 pixels);
[email protected]cadde4a2010-07-31 17:10:435152 GLenum error = glGetError();
5153 if (error == GL_NO_ERROR) {
[email protected]915a59a12010-09-30 21:29:115154 texture_manager()->SetLevelInfo(feature_info_, info,
[email protected]cadde4a2010-07-31 17:10:435155 target, level, internal_format, width, height, 1, border, format, type);
5156 }
[email protected]f7a64ee2010-02-01 22:24:145157 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195158}
5159
[email protected]f7a64ee2010-02-01 22:24:145160error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195161 uint32 immediate_data_size, const gles2::TexImage2D& c) {
5162 GLenum target = static_cast<GLenum>(c.target);
5163 GLint level = static_cast<GLint>(c.level);
5164 GLint internal_format = static_cast<GLint>(c.internalformat);
5165 GLsizei width = static_cast<GLsizei>(c.width);
5166 GLsizei height = static_cast<GLsizei>(c.height);
5167 GLint border = static_cast<GLint>(c.border);
5168 GLenum format = static_cast<GLenum>(c.format);
5169 GLenum type = static_cast<GLenum>(c.type);
5170 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
5171 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:185172 uint32 pixels_size;
5173 if (!GLES2Util::ComputeImageDataSize(
5174 width, height, format, type, unpack_alignment_, &pixels_size)) {
5175 return error::kOutOfBounds;
5176 }
[email protected]b9849abf2009-11-25 19:13:195177 const void* pixels = NULL;
5178 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
5179 pixels = GetSharedMemoryAs<const void*>(
5180 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:465181 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145182 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195183 }
5184 }
[email protected]a93bb842010-02-16 23:03:475185 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195186 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475187 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:195188}
5189
[email protected]f7a64ee2010-02-01 22:24:145190error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195191 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
5192 GLenum target = static_cast<GLenum>(c.target);
5193 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:465194 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:195195 GLsizei width = static_cast<GLsizei>(c.width);
5196 GLsizei height = static_cast<GLsizei>(c.height);
5197 GLint border = static_cast<GLint>(c.border);
5198 GLenum format = static_cast<GLenum>(c.format);
5199 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:185200 uint32 size;
5201 if (!GLES2Util::ComputeImageDataSize(
5202 width, height, format, type, unpack_alignment_, &size)) {
5203 return error::kOutOfBounds;
5204 }
[email protected]07f54fcc2009-12-22 02:46:305205 const void* pixels = GetImmediateDataAs<const void*>(
5206 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465207 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145208 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465209 }
[email protected]a93bb842010-02-16 23:03:475210 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:465211 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475212 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:145213 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325214}
5215
[email protected]cadde4a2010-07-31 17:10:435216void GLES2DecoderImpl::DoCompressedTexSubImage2D(
5217 GLenum target,
5218 GLint level,
5219 GLint xoffset,
5220 GLint yoffset,
5221 GLsizei width,
5222 GLsizei height,
5223 GLenum format,
5224 GLsizei image_size,
5225 const void * data) {
5226 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5227 if (!info) {
5228 SetGLError(GL_INVALID_OPERATION,
5229 "glCompressedTexSubImage2D: unknown texture for target");
5230 return;
5231 }
5232 GLenum type = 0;
5233 GLenum dummy = 0;
5234 if (!info->GetLevelType(target, level, &type, &dummy) ||
5235 !info->ValidForTexture(
5236 target, level, xoffset, yoffset, width, height, format, type)) {
5237 SetGLError(GL_INVALID_VALUE,
5238 "glCompressdTexSubImage2D: bad dimensions.");
5239 return;
5240 }
5241 glCompressedTexSubImage2D(
5242 target, level, xoffset, yoffset, width, height, format, image_size, data);
5243}
5244
5245void GLES2DecoderImpl::DoCopyTexImage2D(
5246 GLenum target,
5247 GLint level,
5248 GLenum internal_format,
5249 GLint x,
5250 GLint y,
5251 GLsizei width,
5252 GLsizei height,
5253 GLint border) {
5254 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5255 if (!info) {
5256 SetGLError(GL_INVALID_OPERATION,
5257 "glCopyTexImage2D: unknown texture for target");
5258 return;
5259 }
[email protected]915a59a12010-09-30 21:29:115260 if (!texture_manager()->ValidForTarget(
5261 feature_info_, target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:185262 border != 0) {
5263 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
5264 return;
5265 }
5266
[email protected]cadde4a2010-07-31 17:10:435267 // TODO(gman): Need to check that current FBO is compatible with
5268 // internal_format.
5269 // TODO(gman): Type needs to match format for FBO.
5270 CopyRealGLErrorsToWrapper();
[email protected]34ff8b0c2010-10-01 20:06:025271 ScopedResolvedFrameBufferBinder binder(this);
[email protected]cadde4a2010-07-31 17:10:435272 glCopyTexImage2D(target, level, internal_format, x, y, width, height, border);
5273 GLenum error = glGetError();
5274 if (error == GL_NO_ERROR) {
5275 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115276 feature_info_, info, target, level, internal_format, width, height, 1,
5277 border, internal_format, GL_UNSIGNED_BYTE);
[email protected]cadde4a2010-07-31 17:10:435278 }
5279}
5280
5281void GLES2DecoderImpl::DoCopyTexSubImage2D(
5282 GLenum target,
5283 GLint level,
5284 GLint xoffset,
5285 GLint yoffset,
5286 GLint x,
5287 GLint y,
5288 GLsizei width,
5289 GLsizei height) {
5290 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5291 if (!info) {
5292 SetGLError(GL_INVALID_OPERATION,
5293 "glCopyTexSubImage2D: unknown texture for target");
5294 return;
5295 }
5296 GLenum type = 0;
5297 GLenum format = 0;
5298 if (!info->GetLevelType(target, level, &type, &format) ||
5299 !info->ValidForTexture(
5300 target, level, xoffset, yoffset, width, height, format, type)) {
5301 SetGLError(GL_INVALID_VALUE,
5302 "glCopyTexSubImage2D: bad dimensions.");
5303 return;
5304 }
5305 // TODO(gman): Should we check that x, y, width, and height are in range
5306 // for current FBO?
[email protected]34ff8b0c2010-10-01 20:06:025307 ScopedResolvedFrameBufferBinder binder(this);
[email protected]cadde4a2010-07-31 17:10:435308 glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
5309}
5310
5311void GLES2DecoderImpl::DoTexSubImage2D(
5312 GLenum target,
5313 GLint level,
5314 GLint xoffset,
5315 GLint yoffset,
5316 GLsizei width,
5317 GLsizei height,
5318 GLenum format,
5319 GLenum type,
5320 const void * data) {
5321 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5322 if (!info) {
5323 SetGLError(GL_INVALID_OPERATION,
5324 "glTexSubImage2D: unknown texture for target");
5325 return;
5326 }
5327 if (!info->ValidForTexture(
5328 target, level, xoffset, yoffset, width, height, format, type)) {
5329 SetGLError(GL_INVALID_VALUE,
5330 "glTexSubImage2D: bad dimensions.");
5331 return;
5332 }
5333 glTexSubImage2D(
5334 target, level, xoffset, yoffset, width, height, format, type, data);
5335}
5336
[email protected]f7a64ee2010-02-01 22:24:145337error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:195338 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:365339 GLuint index = static_cast<GLuint>(c.index);
5340 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:255341 typedef gles2::GetVertexAttribPointerv::Result Result;
5342 Result* result = GetSharedMemoryAs<Result*>(
5343 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:365344 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:145345 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:365346 }
[email protected]07d0cc82010-02-17 04:51:405347 // Check that the client initialized the result.
5348 if (result->size != 0) {
5349 return error::kInvalidArguments;
5350 }
[email protected]9438b012010-06-15 22:55:055351 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295352 SetGLError(GL_INVALID_ENUM,
5353 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145354 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:365355 }
[email protected]3916c97e2010-02-25 03:20:505356 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:295357 SetGLError(GL_INVALID_VALUE,
5358 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:145359 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:365360 }
[email protected]0bfd9882010-02-05 23:02:255361 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:085362 *result->GetData() =
5363 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:145364 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325365}
5366
[email protected]f7b85372010-02-03 01:11:375367bool GLES2DecoderImpl::GetUniformSetup(
5368 GLuint program, GLint location,
5369 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:105370 error::Error* error, GLuint* service_id, void** result_pointer,
5371 GLenum* result_type) {
5372 DCHECK(error);
5373 DCHECK(service_id);
5374 DCHECK(result_pointer);
5375 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:375376 *error = error::kNoError;
5377 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:255378 SizedResult<GLint>* result;
5379 result = GetSharedMemoryAs<SizedResult<GLint>*>(
5380 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
5381 if (!result) {
[email protected]f7b85372010-02-03 01:11:375382 *error = error::kOutOfBounds;
5383 return false;
5384 }
[email protected]0bfd9882010-02-05 23:02:255385 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:375386 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:255387 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:585388 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5389 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:375390 if (!info) {
[email protected]ae51d192010-04-27 00:48:035391 return false;
5392 }
5393 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:375394 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:295395 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:375396 return false;
5397 }
[email protected]ae51d192010-04-27 00:48:035398 *service_id = info->service_id();
[email protected]0bfd9882010-02-05 23:02:255399 GLenum type;
5400 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:375401 // No such location.
[email protected]8eee29c2010-04-29 03:38:295402 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:375403 return false;
5404 }
[email protected]3916c97e2010-02-25 03:20:505405 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:375406 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:295407 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:375408 return false;
5409 }
[email protected]0bfd9882010-02-05 23:02:255410 result = GetSharedMemoryAs<SizedResult<GLint>*>(
5411 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
5412 if (!result) {
[email protected]f7b85372010-02-03 01:11:375413 *error = error::kOutOfBounds;
5414 return false;
5415 }
[email protected]0bfd9882010-02-05 23:02:255416 result->size = size;
[email protected]939e7362010-05-13 20:49:105417 *result_type = type;
[email protected]f7b85372010-02-03 01:11:375418 return true;
5419}
5420
[email protected]f7a64ee2010-02-01 22:24:145421error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:195422 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:375423 GLuint program = c.program;
5424 GLint location = c.location;
5425 GLuint service_id;
[email protected]939e7362010-05-13 20:49:105426 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:375427 Error error;
[email protected]0bfd9882010-02-05 23:02:255428 void* result;
[email protected]f7b85372010-02-03 01:11:375429 if (GetUniformSetup(
5430 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:105431 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:255432 glGetUniformiv(
5433 service_id, location,
5434 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:375435 }
5436 return error;
[email protected]96449d2c2009-11-25 00:01:325437}
5438
[email protected]f7a64ee2010-02-01 22:24:145439error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:195440 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:375441 GLuint program = c.program;
5442 GLint location = c.location;
5443 GLuint service_id;
5444 Error error;
[email protected]0bfd9882010-02-05 23:02:255445 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:105446 Result* result;
5447 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:375448 if (GetUniformSetup(
5449 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:105450 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
5451 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
5452 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
5453 GLsizei num_values = result->GetNumResults();
5454 scoped_array<GLint> temp(new GLint[num_values]);
5455 glGetUniformiv(service_id, location, temp.get());
5456 GLfloat* dst = result->GetData();
5457 for (GLsizei ii = 0; ii < num_values; ++ii) {
5458 dst[ii] = (temp[ii] != 0);
5459 }
5460 } else {
5461 glGetUniformfv(service_id, location, result->GetData());
5462 }
[email protected]f7b85372010-02-03 01:11:375463 }
5464 return error;
[email protected]96449d2c2009-11-25 00:01:325465}
5466
[email protected]f7a64ee2010-02-01 22:24:145467error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:195468 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:255469 GLenum shader_type = static_cast<GLenum>(c.shadertype);
5470 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
5471 typedef gles2::GetShaderPrecisionFormat::Result Result;
5472 Result* result = GetSharedMemoryAs<Result*>(
5473 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5474 if (!result) {
5475 return error::kOutOfBounds;
5476 }
[email protected]07d0cc82010-02-17 04:51:405477 // Check that the client initialized the result.
5478 if (result->success != 0) {
5479 return error::kInvalidArguments;
5480 }
[email protected]9438b012010-06-15 22:55:055481 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:295482 SetGLError(GL_INVALID_ENUM,
5483 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
5484 return error::kNoError;
5485 }
[email protected]9438b012010-06-15 22:55:055486 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:295487 SetGLError(GL_INVALID_ENUM,
5488 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
5489 return error::kNoError;
5490 }
5491
5492 result->success = 1; // true
5493 switch (precision_type) {
5494 case GL_LOW_INT:
5495 case GL_MEDIUM_INT:
5496 case GL_HIGH_INT:
5497 result->min_range = -31;
5498 result->max_range = 31;
5499 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:105500 break;
[email protected]8eee29c2010-04-29 03:38:295501 case GL_LOW_FLOAT:
5502 case GL_MEDIUM_FLOAT:
5503 case GL_HIGH_FLOAT:
5504 result->min_range = -62;
5505 result->max_range = 62;
5506 result->precision = -16;
5507 break;
5508 default:
5509 NOTREACHED();
5510 break;
[email protected]0bfd9882010-02-05 23:02:255511 }
[email protected]f7a64ee2010-02-01 22:24:145512 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325513}
5514
[email protected]f7a64ee2010-02-01 22:24:145515error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:195516 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:255517 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:585518 GLuint program = static_cast<GLuint>(c.program);
5519 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5520 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:035521 if (!info) {
[email protected]0bfd9882010-02-05 23:02:255522 return error::kNoError;
5523 }
5524 typedef gles2::GetAttachedShaders::Result Result;
5525 uint32 max_count = Result::ComputeMaxResults(result_size);
5526 Result* result = GetSharedMemoryAs<Result*>(
5527 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
5528 if (!result) {
5529 return error::kOutOfBounds;
5530 }
[email protected]07d0cc82010-02-17 04:51:405531 // Check that the client initialized the result.
5532 if (result->size != 0) {
5533 return error::kInvalidArguments;
5534 }
[email protected]0bfd9882010-02-05 23:02:255535 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:035536 glGetAttachedShaders(
5537 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:255538 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:035539 if (!shader_manager()->GetClientId(result->GetData()[ii],
5540 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:255541 NOTREACHED();
5542 return error::kGenericError;
5543 }
5544 }
5545 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:145546 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325547}
5548
[email protected]f7a64ee2010-02-01 22:24:145549error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:195550 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:255551 GLuint program = c.program;
5552 GLuint index = c.index;
5553 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:255554 typedef gles2::GetActiveUniform::Result Result;
5555 Result* result = GetSharedMemoryAs<Result*>(
5556 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5557 if (!result) {
5558 return error::kOutOfBounds;
5559 }
[email protected]07d0cc82010-02-17 04:51:405560 // Check that the client initialized the result.
5561 if (result->success != 0) {
5562 return error::kInvalidArguments;
5563 }
[email protected]6b8cf1a2010-05-06 16:13:585564 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5565 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:035566 if (!info) {
[email protected]0bfd9882010-02-05 23:02:255567 return error::kNoError;
5568 }
5569 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
5570 info->GetUniformInfo(index);
5571 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:295572 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:255573 return error::kNoError;
5574 }
5575 result->success = 1; // true.
5576 result->size = uniform_info->size;
5577 result->type = uniform_info->type;
5578 Bucket* bucket = CreateBucket(name_bucket_id);
5579 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:145580 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325581}
5582
[email protected]f7a64ee2010-02-01 22:24:145583error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:195584 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:255585 GLuint program = c.program;
5586 GLuint index = c.index;
5587 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:255588 typedef gles2::GetActiveAttrib::Result Result;
5589 Result* result = GetSharedMemoryAs<Result*>(
5590 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5591 if (!result) {
5592 return error::kOutOfBounds;
5593 }
[email protected]07d0cc82010-02-17 04:51:405594 // Check that the client initialized the result.
5595 if (result->success != 0) {
5596 return error::kInvalidArguments;
5597 }
[email protected]6b8cf1a2010-05-06 16:13:585598 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5599 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:035600 if (!info) {
[email protected]0bfd9882010-02-05 23:02:255601 return error::kNoError;
5602 }
5603 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5604 info->GetAttribInfo(index);
5605 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:295606 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:255607 return error::kNoError;
5608 }
5609 result->success = 1; // true.
5610 result->size = attrib_info->size;
5611 result->type = attrib_info->type;
5612 Bucket* bucket = CreateBucket(name_bucket_id);
5613 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:145614 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325615}
5616
[email protected]b273e432010-04-12 17:23:585617error::Error GLES2DecoderImpl::HandleShaderBinary(
5618 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
5619#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:295620 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:585621 return error::kNoError;
5622#else
5623 GLsizei n = static_cast<GLsizei>(c.n);
5624 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:295625 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:585626 return error::kNoError;
5627 }
5628 GLsizei length = static_cast<GLsizei>(c.length);
5629 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:295630 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:585631 return error::kNoError;
5632 }
5633 uint32 data_size;
5634 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
5635 return error::kOutOfBounds;
5636 }
5637 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
5638 c.shaders_shm_id, c.shaders_shm_offset, data_size);
5639 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
5640 const void* binary = GetSharedMemoryAs<const void*>(
5641 c.binary_shm_id, c.binary_shm_offset, length);
5642 if (shaders == NULL || binary == NULL) {
5643 return error::kOutOfBounds;
5644 }
5645 scoped_array<GLuint> service_ids(new GLuint[n]);
5646 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:035647 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
5648 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295649 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:585650 return error::kNoError;
5651 }
[email protected]ae51d192010-04-27 00:48:035652 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:585653 }
5654 // TODO(gman): call glShaderBinary
5655 return error::kNoError;
5656#endif
5657}
5658
[email protected]6217d392010-03-25 22:08:355659error::Error GLES2DecoderImpl::HandleSwapBuffers(
5660 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]6217d392010-03-25 22:08:355661 // If offscreen then don't actually SwapBuffers to the display. Just copy
5662 // the rendered frame to another frame buffer.
5663 if (offscreen_target_frame_buffer_.get()) {
5664 ScopedGLErrorSuppressor suppressor(this);
5665
5666 // First check to see if a deferred offscreen render buffer resize is
5667 // pending.
[email protected]d0498742010-09-20 20:27:015668 if (!UpdateOffscreenFrameBufferSize()) {
5669 LOG(ERROR) << "Context lost because reallocation of offscreen FBO "
5670 << "failed.";
[email protected]6217d392010-03-25 22:08:355671 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:015672 }
[email protected]6217d392010-03-25 22:08:355673
[email protected]34ff8b0c2010-10-01 20:06:025674 if (IsOffscreenBufferMultisampled()) {
5675 // For multisampled buffers, bind the resolved frame buffer so that
5676 // callbacks can call ReadPixels or CopyTexImage2D.
5677 ScopedResolvedFrameBufferBinder binder(this);
5678 if (swap_buffers_callback_.get()) {
5679 swap_buffers_callback_->Run();
5680 }
5681 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:485682 } else {
[email protected]0c8c9d22010-06-25 17:36:395683 ScopedFrameBufferBinder binder(this,
5684 offscreen_target_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:405685
[email protected]b86b14982010-10-11 18:45:485686 if (parent_) {
5687 // Copy the target frame buffer to the saved offscreen texture.
5688 offscreen_saved_color_texture_->Copy(
5689 offscreen_saved_color_texture_->size());
5690
[email protected]a3ded6d2010-10-19 06:44:395691 // Ensure the side effects of the copy are visible to the parent
5692 // context. There is no need to do this for ANGLE because it uses a
5693 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:485694 if (!IsAngle())
5695 glFlush();
5696 }
5697
5698 // Run the callback with |binder| in scope, so that the callback can call
5699 // ReadPixels or CopyTexImage2D.
5700 if (swap_buffers_callback_.get()) {
5701 swap_buffers_callback_->Run();
5702 }
5703 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:395704 }
[email protected]6217d392010-03-25 22:08:355705 } else {
[email protected]d0498742010-09-20 20:27:015706 if (!context_->SwapBuffers()) {
5707 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:025708 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:015709 }
[email protected]6217d392010-03-25 22:08:355710 }
5711
5712 if (swap_buffers_callback_.get()) {
5713 swap_buffers_callback_->Run();
5714 }
5715
5716 return error::kNoError;
5717}
5718
[email protected]b1d2dcb2010-05-17 19:24:185719error::Error GLES2DecoderImpl::HandleCommandBufferEnable(
5720 uint32 immediate_data_size, const gles2::CommandBufferEnable& c) {
5721 Bucket* bucket = GetBucket(c.bucket_id);
5722 typedef gles2::CommandBufferEnable::Result Result;
5723 Result* result = GetSharedMemoryAs<Result*>(
5724 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5725 if (!result) {
5726 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:105727 }
[email protected]b1d2dcb2010-05-17 19:24:185728 // Check that the client initialized the result.
5729 if (*result != 0) {
5730 return error::kInvalidArguments;
5731 }
5732 std::string feature_str;
5733 if (!bucket->GetAsString(&feature_str)) {
5734 return error::kInvalidArguments;
5735 }
5736
5737 // TODO(gman): make this some kind of table to function pointer thingy.
5738 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
5739 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
5740 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
5741 use_shader_translator_ = false;
5742 } else {
5743 return error::kNoError;
5744 }
5745
5746 *result = 1; // true.
5747 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:105748}
5749
[email protected]96449d2c2009-11-25 00:01:325750// Include the auto-generated part of this file. We split this because it means
5751// we can easily edit the non-auto generated parts right here in this file
5752// instead of having to edit some template or the code generator.
5753#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
5754
5755} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:255756} // namespace gpu