blob: 97029028696b353a40732762db462d119b753a89 [file] [log] [blame]
[email protected]4874aae2011-03-18 01:19:561// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]96449d2c2009-11-25 00:01:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]8a837bb2010-01-05 00:21:245#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
[email protected]74470702010-01-06 18:51:166
7#include <stdio.h>
8
[email protected]1aef98132010-02-23 18:00:079#include <algorithm>
[email protected]f39f4b3f2010-05-12 17:04:0810#include <list>
[email protected]96449d2c2009-11-25 00:01:3211#include <map>
[email protected]f39f4b3f2010-05-12 17:04:0812#include <string>
13#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0614
[email protected]1e6f58d2011-03-24 00:00:4015#include "base/atomicops.h"
[email protected]00eb49a2010-08-12 20:46:5716#include "base/at_exit.h"
[email protected]2041cf342010-02-19 03:15:5917#include "base/callback.h"
[email protected]3b63f8f42011-03-28 01:54:1518#include "base/memory/scoped_ptr.h"
19#include "base/memory/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0220#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3221#define GLES2_GPU_SERVICE 1
22#include "gpu/command_buffer/common/gles2_cmd_format.h"
23#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1024#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5025#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3226#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5027#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1128#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5829#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3230#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4631#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4732#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5833#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4734#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4535#include "gpu/command_buffer/service/shader_translator.h"
[email protected]a93bb842010-02-16 23:03:4736#include "gpu/command_buffer/service/texture_manager.h"
[email protected]4e8a5b122010-05-08 22:00:1037#include "gpu/GLES2/gles2_command_buffer.h"
[email protected]5ae0b282011-03-28 19:24:4938#include "ui/gfx/gl/gl_context.h"
39#include "ui/gfx/gl/gl_implementation.h"
[email protected]de17df392010-04-23 21:09:4140
[email protected]6217d392010-03-25 22:08:3541#if !defined(GL_DEPTH24_STENCIL8)
42#define GL_DEPTH24_STENCIL8 0x88F0
43#endif
44
[email protected]a7a27ace2009-12-12 00:11:2545namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3246namespace gles2 {
47
[email protected]6217d392010-03-25 22:08:3548class GLES2DecoderImpl;
49
[email protected]07f54fcc2009-12-22 02:46:3050// Check that certain assumptions the code makes are true. There are places in
51// the code where shared memory is passed direclty to GL. Example, glUniformiv,
52// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
53// a few others) are 32bits. If they are not 32bits the code will have to change
54// to call those GL functions with service side memory and then copy the results
55// to shared memory, converting the sizes.
56COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
57 GLint_not_same_size_as_uint32);
58COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
59 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3760COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
61 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3062
[email protected]43f28f832010-02-03 02:28:4863// TODO(kbr): the use of this anonymous namespace core dumps the
64// linker on Mac OS X 10.6 when the symbol ordering file is used
65// namespace {
[email protected]96449d2c2009-11-25 00:01:3266
67// Returns the address of the first byte after a struct.
68template <typename T>
69const void* AddressAfterStruct(const T& pod) {
70 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
71}
72
[email protected]07f54fcc2009-12-22 02:46:3073// Returns the address of the frst byte after the struct or NULL if size >
74// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3275template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3076RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
77 uint32 size,
78 uint32 immediate_data_size) {
79 return (size <= immediate_data_size) ?
80 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
81 NULL;
[email protected]96449d2c2009-11-25 00:01:3282}
83
[email protected]07f54fcc2009-12-22 02:46:3084// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1885bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3286 GLuint count,
87 size_t size,
[email protected]a76b0052010-03-05 00:33:1888 unsigned int elements_per_unit,
89 uint32* dst) {
90 uint32 value;
91 if (!SafeMultiplyUint32(count, size, &value)) {
92 return false;
93 }
94 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
95 return false;
96 }
97 *dst = value;
98 return true;
[email protected]96449d2c2009-11-25 00:01:3299}
100
101// A struct to hold info about each command.
102struct CommandInfo {
103 int arg_flags; // How to handle the arguments for this command
104 int arg_count; // How many arguments are expected for this command.
105};
106
107// A table of CommandInfo for all the commands.
108const CommandInfo g_command_info[] = {
109 #define GLES2_CMD_OP(name) { \
110 name::kArgFlags, \
111 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
112
113 GLES2_COMMAND_LIST(GLES2_CMD_OP)
114
115 #undef GLES2_CMD_OP
116};
117
[email protected]34ff8b0c2010-10-01 20:06:02118static bool IsAngle() {
119#if defined(OS_WIN)
120 return gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
121#else
122 return false;
123#endif
124}
125
[email protected]6217d392010-03-25 22:08:35126// This class prevents any GL errors that occur when it is in scope from
127// being reported to the client.
128class ScopedGLErrorSuppressor {
129 public:
130 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
131 ~ScopedGLErrorSuppressor();
132 private:
133 GLES2DecoderImpl* decoder_;
134 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
135};
136
137// Temporarily changes a decoder's bound 2D texture and restore it when this
138// object goes out of scope. Also temporarily switches to using active texture
139// unit zero in case the client has changed that to something invalid.
140class ScopedTexture2DBinder {
141 public:
142 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
143 ~ScopedTexture2DBinder();
144
145 private:
146 GLES2DecoderImpl* decoder_;
147 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
148};
149
150// Temporarily changes a decoder's bound render buffer and restore it when this
151// object goes out of scope.
152class ScopedRenderBufferBinder {
153 public:
154 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
155 ~ScopedRenderBufferBinder();
156
157 private:
158 GLES2DecoderImpl* decoder_;
159 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
160};
161
162// Temporarily changes a decoder's bound frame buffer and restore it when this
163// object goes out of scope.
164class ScopedFrameBufferBinder {
165 public:
166 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
167 ~ScopedFrameBufferBinder();
168
169 private:
170 GLES2DecoderImpl* decoder_;
171 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
172};
173
[email protected]34ff8b0c2010-10-01 20:06:02174// Temporarily changes a decoder's bound frame buffer to a resolved version of
175// the multisampled offscreen render buffer if and only if that buffer is
176// currently bound and is multisampled.
177class ScopedResolvedFrameBufferBinder {
178 public:
179 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder);
180 ~ScopedResolvedFrameBufferBinder();
181
182 private:
183 GLES2DecoderImpl* decoder_;
184 bool resolve_and_bind_;
185 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
186};
187
[email protected]6217d392010-03-25 22:08:35188// Encapsulates an OpenGL texture.
189class Texture {
190 public:
191 explicit Texture(GLES2DecoderImpl* decoder);
192 ~Texture();
193
194 // Create a new render texture.
195 void Create();
196
197 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02198 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35199
200 // Copy the contents of the currently bound frame buffer.
201 void Copy(const gfx::Size& size);
202
203 // Destroy the render texture. This must be explicitly called before
204 // destroying this object.
205 void Destroy();
206
[email protected]97872062010-11-03 19:07:05207 // Invalidate the texture. This can be used when a context is lost and it is
208 // not possible to make it current in order to free the resource.
209 void Invalidate();
210
[email protected]6217d392010-03-25 22:08:35211 GLuint id() const {
212 return id_;
213 }
214
[email protected]d37231fa2010-04-09 21:16:02215 gfx::Size size() const {
216 return size_;
217 }
218
[email protected]6217d392010-03-25 22:08:35219 private:
220 GLES2DecoderImpl* decoder_;
221 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02222 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35223 DISALLOW_COPY_AND_ASSIGN(Texture);
224};
225
226// Encapsulates an OpenGL render buffer of any format.
227class RenderBuffer {
228 public:
229 explicit RenderBuffer(GLES2DecoderImpl* decoder);
230 ~RenderBuffer();
231
232 // Create a new render buffer.
233 void Create();
234
235 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02236 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35237
238 // Destroy the render buffer. This must be explicitly called before destroying
239 // this object.
240 void Destroy();
241
[email protected]97872062010-11-03 19:07:05242 // Invalidate the render buffer. This can be used when a context is lost and
243 // it is not possible to make it current in order to free the resource.
244 void Invalidate();
245
[email protected]6217d392010-03-25 22:08:35246 GLuint id() const {
247 return id_;
248 }
249
250 private:
251 GLES2DecoderImpl* decoder_;
252 GLuint id_;
253 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
254};
255
256// Encapsulates an OpenGL frame buffer.
257class FrameBuffer {
258 public:
259 explicit FrameBuffer(GLES2DecoderImpl* decoder);
260 ~FrameBuffer();
261
262 // Create a new frame buffer.
263 void Create();
264
265 // Attach a color render buffer to a frame buffer.
266 void AttachRenderTexture(Texture* texture);
267
[email protected]b9363b22010-06-09 22:06:15268 // Attach a render buffer to a frame buffer. Note that this unbinds any
269 // currently bound frame buffer.
270 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35271
272 // Clear the given attached buffers.
273 void Clear(GLbitfield buffers);
274
275 // Destroy the frame buffer. This must be explicitly called before destroying
276 // this object.
277 void Destroy();
278
[email protected]97872062010-11-03 19:07:05279 // Invalidate the frame buffer. This can be used when a context is lost and it
280 // is not possible to make it current in order to free the resource.
281 void Invalidate();
282
[email protected]6217d392010-03-25 22:08:35283 // See glCheckFramebufferStatusEXT.
284 GLenum CheckStatus();
285
286 GLuint id() const {
287 return id_;
288 }
289
290 private:
291 GLES2DecoderImpl* decoder_;
292 GLuint id_;
293 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
294};
[email protected]34ff8b0c2010-10-01 20:06:02295
296class ContextCreationAttribParser {
297 public:
298 ContextCreationAttribParser();
299 bool Parse(const std::vector<int32>& attribs);
300
301 // -1 if invalid or unspecified.
302 int32 alpha_size_;
303 int32 blue_size_;
304 int32 green_size_;
305 int32 red_size_;
306 int32 depth_size_;
307 int32 stencil_size_;
308 int32 samples_;
309 int32 sample_buffers_;
310};
311
312ContextCreationAttribParser::ContextCreationAttribParser()
313 : alpha_size_(-1),
314 blue_size_(-1),
315 green_size_(-1),
316 red_size_(-1),
317 depth_size_(-1),
318 stencil_size_(-1),
319 samples_(-1),
320 sample_buffers_(-1) {
321}
322
323bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
324 // From <EGL/egl.h>.
325 const int32 EGL_ALPHA_SIZE = 0x3021;
326 const int32 EGL_BLUE_SIZE = 0x3022;
327 const int32 EGL_GREEN_SIZE = 0x3023;
328 const int32 EGL_RED_SIZE = 0x3024;
329 const int32 EGL_DEPTH_SIZE = 0x3025;
330 const int32 EGL_STENCIL_SIZE = 0x3026;
331 const int32 EGL_SAMPLES = 0x3031;
332 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
333 const int32 EGL_NONE = 0x3038;
334
335 for (size_t i = 0; i < attribs.size(); i += 2) {
336 const int32 attrib = attribs[i];
337 if (i + 1 >= attribs.size()) {
338 if (attrib == EGL_NONE)
339 return true;
340
341 DLOG(ERROR) << "Missing value after context creation attribute: "
342 << attrib;
343 return false;
344 }
345
346 const int32 value = attribs[i+1];
347 switch (attrib) {
348 case EGL_ALPHA_SIZE:
349 alpha_size_ = value;
350 break;
351 case EGL_BLUE_SIZE:
352 blue_size_ = value;
353 break;
354 case EGL_GREEN_SIZE:
355 green_size_ = value;
356 break;
357 case EGL_RED_SIZE:
358 red_size_ = value;
359 break;
360 case EGL_DEPTH_SIZE:
361 depth_size_ = value;
362 break;
363 case EGL_STENCIL_SIZE:
364 stencil_size_ = value;
365 break;
366 case EGL_SAMPLES:
367 samples_ = value;
368 break;
369 case EGL_SAMPLE_BUFFERS:
370 sample_buffers_ = value;
371 break;
372 case EGL_NONE:
373 // Terminate list, even if more attributes.
374 return true;
375 default:
376 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
377 return false;
378 }
379 }
380
381 return true;
382}
383
[email protected]43f28f832010-02-03 02:28:48384// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32385
[email protected]ddb1e5a2010-12-13 20:10:45386bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
387 uint32* service_texture_id) {
388 return false;
389}
390
[email protected]a3ded6d2010-10-19 06:44:39391GLES2Decoder::GLES2Decoder()
392 : debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32393}
394
[email protected]3916c97e2010-02-25 03:20:50395GLES2Decoder::~GLES2Decoder() {
396}
397
[email protected]f39f4b3f2010-05-12 17:04:08398class VertexAttribManager {
[email protected]96449d2c2009-11-25 00:01:32399 public:
[email protected]07f54fcc2009-12-22 02:46:30400 // Info about Vertex Attributes. This is used to track what the user currently
401 // has bound on each Vertex Attribute so that checking can be done at
402 // glDrawXXX time.
403 class VertexAttribInfo {
404 public:
[email protected]f39f4b3f2010-05-12 17:04:08405 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
[email protected]b1122982010-05-17 23:04:24406 struct Vec4 {
407 float v[4];
408 };
[email protected]f39f4b3f2010-05-12 17:04:08409
[email protected]07f54fcc2009-12-22 02:46:30410 VertexAttribInfo()
[email protected]f39f4b3f2010-05-12 17:04:08411 : index_(0),
412 enabled_(false),
413 size_(4),
414 type_(GL_FLOAT),
[email protected]07f54fcc2009-12-22 02:46:30415 offset_(0),
[email protected]b1122982010-05-17 23:04:24416 normalized_(GL_FALSE),
417 gl_stride_(0),
[email protected]f39f4b3f2010-05-12 17:04:08418 real_stride_(16),
419 list_(NULL) {
[email protected]b1122982010-05-17 23:04:24420 value_.v[0] = 0.0f;
421 value_.v[1] = 0.0f;
422 value_.v[2] = 0.0f;
423 value_.v[3] = 1.0f;
[email protected]07f54fcc2009-12-22 02:46:30424 }
[email protected]3916c97e2010-02-25 03:20:50425
[email protected]07f54fcc2009-12-22 02:46:30426 // Returns true if this VertexAttrib can access index.
[email protected]f39f4b3f2010-05-12 17:04:08427 bool CanAccess(GLuint index) const;
[email protected]07f54fcc2009-12-22 02:46:30428
[email protected]3916c97e2010-02-25 03:20:50429 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30430 return buffer_;
431 }
432
[email protected]8bf5a3e2010-01-29 04:21:36433 GLsizei offset() const {
434 return offset_;
435 }
436
[email protected]f39f4b3f2010-05-12 17:04:08437 GLuint index() const {
438 return index_;
439 }
440
[email protected]b1122982010-05-17 23:04:24441 GLint size() const {
442 return size_;
443 }
444
445 GLenum type() const {
446 return type_;
447 }
448
449 GLboolean normalized() const {
450 return normalized_;
451 }
452
453 GLsizei gl_stride() const {
454 return gl_stride_;
455 }
456
[email protected]f39f4b3f2010-05-12 17:04:08457 bool enabled() const {
458 return enabled_;
459 }
460
[email protected]b1122982010-05-17 23:04:24461 void set_value(const Vec4& value) {
462 value_ = value;
463 }
464
465 const Vec4& value() const {
466 return value_;
467 }
468
[email protected]07f54fcc2009-12-22 02:46:30469 private:
[email protected]f39f4b3f2010-05-12 17:04:08470 friend class VertexAttribManager;
471
472 void set_enabled(bool enabled) {
473 enabled_ = enabled;
474 }
475
476 void set_index(GLuint index) {
477 index_ = index;
478 }
479
480 void SetList(VertexAttribInfoList* new_list) {
481 DCHECK(new_list);
482
483 if (list_) {
484 list_->erase(it_);
485 }
486
487 it_ = new_list->insert(new_list->end(), this);
488 list_ = new_list;
489 }
490
[email protected]8fbedc02010-11-18 18:43:40491 void SetInfo(
492 BufferManager::BufferInfo* buffer,
493 GLint size,
494 GLenum type,
495 GLboolean normalized,
496 GLsizei gl_stride,
497 GLsizei real_stride,
498 GLsizei offset) {
499 DCHECK_GT(real_stride, 0);
500 buffer_ = buffer;
501 size_ = size;
502 type_ = type;
503 normalized_ = normalized;
504 gl_stride_ = gl_stride;
505 real_stride_ = real_stride;
506 offset_ = offset;
507 }
508
[email protected]f39f4b3f2010-05-12 17:04:08509 // The index of this attrib.
510 GLuint index_;
511
[email protected]07f54fcc2009-12-22 02:46:30512 // Whether or not this attribute is enabled.
513 bool enabled_;
514
515 // number of components (1, 2, 3, 4)
516 GLint size_;
517
518 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
519 GLenum type_;
520
521 // The offset into the buffer.
522 GLsizei offset_;
523
[email protected]b1122982010-05-17 23:04:24524 GLboolean normalized_;
525
526 // The stride passed to glVertexAttribPointer.
527 GLsizei gl_stride_;
528
[email protected]07f54fcc2009-12-22 02:46:30529 // The stride that will be used to access the buffer. This is the actual
530 // stide, NOT the GL bogus stride. In other words there is never a stride
531 // of 0.
532 GLsizei real_stride_;
533
[email protected]b1122982010-05-17 23:04:24534 // The current value of the attrib.
535 Vec4 value_;
536
[email protected]3916c97e2010-02-25 03:20:50537 // The buffer bound to this attribute.
538 BufferManager::BufferInfo::Ref buffer_;
[email protected]f39f4b3f2010-05-12 17:04:08539
540 // List this info is on.
541 VertexAttribInfoList* list_;
542
543 // Iterator for list this info is on. Enabled/Disabled
544 VertexAttribInfoList::iterator it_;
[email protected]07f54fcc2009-12-22 02:46:30545 };
546
[email protected]f39f4b3f2010-05-12 17:04:08547 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
548
549 VertexAttribManager()
[email protected]8fbedc02010-11-18 18:43:40550 : max_vertex_attribs_(0),
551 num_fixed_attribs_(0) {
[email protected]f39f4b3f2010-05-12 17:04:08552 }
553
554 void Initialize(uint32 num_vertex_attribs);
555
556 bool Enable(GLuint index, bool enable);
557
[email protected]8fbedc02010-11-18 18:43:40558 bool HaveFixedAttribs() const {
559 return num_fixed_attribs_ != 0;
560 }
561
[email protected]f39f4b3f2010-05-12 17:04:08562 const VertexAttribInfoList& GetEnabledVertexAttribInfos() const {
563 return enabled_vertex_attribs_;
564 }
565
566 VertexAttribInfo* GetVertexAttribInfo(GLuint index) {
[email protected]b1122982010-05-17 23:04:24567 if (index < max_vertex_attribs_) {
568 return &vertex_attrib_infos_[index];
569 }
570 return NULL;
[email protected]f39f4b3f2010-05-12 17:04:08571 }
572
[email protected]8fbedc02010-11-18 18:43:40573 void SetAttribInfo(
574 GLuint index,
575 BufferManager::BufferInfo* buffer,
576 GLint size,
577 GLenum type,
578 GLboolean normalized,
579 GLsizei gl_stride,
580 GLsizei real_stride,
581 GLsizei offset) {
582 VertexAttribInfo* info = GetVertexAttribInfo(index);
583 if (info) {
584 if (info->type() == GL_FIXED) {
585 --num_fixed_attribs_;
586 }
587 if (type == GL_FIXED) {
588 ++num_fixed_attribs_;
589 }
590 info->SetInfo(
591 buffer, size, type, normalized, gl_stride, real_stride, offset);
592 }
593 }
594
595
[email protected]f39f4b3f2010-05-12 17:04:08596 private:
597 uint32 max_vertex_attribs_;
598
[email protected]8fbedc02010-11-18 18:43:40599 // number of attribs using type GL_FIXED.
600 int num_fixed_attribs_;
601
[email protected]f39f4b3f2010-05-12 17:04:08602 // Info for each vertex attribute saved so we can check at glDrawXXX time
603 // if it is safe to draw.
604 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
605
606 // Lists for which vertex attribs are enabled, disabled.
607 VertexAttribInfoList enabled_vertex_attribs_;
608 VertexAttribInfoList disabled_vertex_attribs_;
609};
610
611bool VertexAttribManager::VertexAttribInfo::CanAccess(GLuint index) const {
612 if (!enabled_) {
613 return true;
614 }
615
616 if (!buffer_ || buffer_->IsDeleted()) {
617 return false;
618 }
619
620 // The number of elements that can be accessed.
621 GLsizeiptr buffer_size = buffer_->size();
622 if (offset_ > buffer_size || real_stride_ == 0) {
623 return false;
624 }
625
626 uint32 usable_size = buffer_size - offset_;
627 GLuint num_elements = usable_size / real_stride_ +
628 ((usable_size % real_stride_) >=
629 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
630 return index < num_elements;
631}
632
633
634void VertexAttribManager::Initialize(uint32 max_vertex_attribs) {
635 max_vertex_attribs_ = max_vertex_attribs;
636 vertex_attrib_infos_.reset(
637 new VertexAttribInfo[max_vertex_attribs]);
638 for (uint32 vv = 0; vv < max_vertex_attribs; ++vv) {
639 vertex_attrib_infos_[vv].set_index(vv);
640 vertex_attrib_infos_[vv].SetList(&disabled_vertex_attribs_);
641 }
642}
643
644bool VertexAttribManager::Enable(GLuint index, bool enable) {
645 if (index >= max_vertex_attribs_) {
646 return false;
647 }
648 VertexAttribInfo& info = vertex_attrib_infos_[index];
649 if (info.enabled() != enable) {
650 info.set_enabled(enable);
651 info.SetList(enable ? &enabled_vertex_attribs_ : &disabled_vertex_attribs_);
652 }
653 return true;
654}
655
656// This class implements GLES2Decoder so we don't have to expose all the GLES2
657// cmd stuff to outside this class.
658class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
659 public GLES2Decoder {
660 public:
661 explicit GLES2DecoderImpl(ContextGroup* group);
662
[email protected]96449d2c2009-11-25 00:01:32663 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14664 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50665 unsigned int arg_count,
666 const void* args);
[email protected]96449d2c2009-11-25 00:01:32667
668 // Overridden from AsyncAPIInterface.
669 virtual const char* GetCommandName(unsigned int command_id) const;
670
671 // Overridden from GLES2Decoder.
[email protected]5a6db6c2010-04-22 18:32:06672 virtual bool Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:35673 const gfx::Size& size,
[email protected]c410da802011-03-14 19:17:41674 const DisallowedExtensions& disallowed_extensions,
[email protected]a3ded6d2010-10-19 06:44:39675 const char* allowed_extensions,
[email protected]34ff8b0c2010-10-01 20:06:02676 const std::vector<int32>& attribs,
[email protected]d37231fa2010-04-09 21:16:02677 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35678 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32679 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35680 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]c71caa82010-06-02 23:25:45681 virtual bool UpdateOffscreenFrameBufferSize();
[email protected]eb54a562010-01-20 21:55:18682 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55683 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30684 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39685 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48686
[email protected]7ff86b92010-11-25 17:50:00687 virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
[email protected]43f28f832010-02-03 02:28:48688 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
[email protected]1318e922010-09-17 22:03:16689 virtual bool GetServiceTextureId(uint32 client_texture_id,
690 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48691
[email protected]8e3e0662010-08-23 18:46:30692 // Restores the current state to the user's settings.
693 void RestoreCurrentFramebufferBindings();
694 void RestoreCurrentRenderbufferBindings();
695 void RestoreCurrentTexture2DBindings();
696
[email protected]96449d2c2009-11-25 00:01:32697 private:
[email protected]6217d392010-03-25 22:08:35698 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02699 friend class ScopedResolvedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35700 friend class RenderBuffer;
701 friend class FrameBuffer;
702
[email protected]3916c97e2010-02-25 03:20:50703 // State associated with each texture unit.
704 struct TextureUnit {
705 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
706
707 // The last target that was bound to this texture unit.
708 GLenum bind_target;
709
710 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
711 TextureManager::TextureInfo::Ref bound_texture_2d;
712
713 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
714 // glBindTexture
715 TextureManager::TextureInfo::Ref bound_texture_cube_map;
716 };
717
[email protected]c2f8c8402010-12-06 18:07:24718 // Initialize or re-initialize the shader translator.
719 bool InitializeShaderTranslator();
720
[email protected]ae51d192010-04-27 00:48:03721 // Helpers for the glGen and glDelete functions.
722 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
723 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
724 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
725 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
726 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
727 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
728 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
729 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47730
[email protected]3916c97e2010-02-25 03:20:50731 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50732 BufferManager* buffer_manager() {
733 return group_->buffer_manager();
734 }
735
[email protected]a25fa872010-03-25 02:57:58736 RenderbufferManager* renderbuffer_manager() {
737 return group_->renderbuffer_manager();
738 }
739
740 FramebufferManager* framebuffer_manager() {
741 return group_->framebuffer_manager();
742 }
743
[email protected]3916c97e2010-02-25 03:20:50744 ProgramManager* program_manager() {
745 return group_->program_manager();
746 }
747
748 ShaderManager* shader_manager() {
749 return group_->shader_manager();
750 }
751
752 TextureManager* texture_manager() {
753 return group_->texture_manager();
754 }
755
[email protected]34ff8b0c2010-10-01 20:06:02756 bool IsOffscreenBufferMultisampled() const {
757 return offscreen_target_samples_ > 1;
758 }
759
[email protected]a93bb842010-02-16 23:03:47760 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03761 TextureManager::TextureInfo* CreateTextureInfo(
762 GLuint client_id, GLuint service_id) {
[email protected]915a59a12010-09-30 21:29:11763 return texture_manager()->CreateTextureInfo(
764 feature_info_, client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47765 }
766
767 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03768 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50769 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03770 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50771 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47772 }
773
774 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03775 void RemoveTextureInfo(GLuint client_id) {
[email protected]915a59a12010-09-30 21:29:11776 texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]3916c97e2010-02-25 03:20:50777 }
[email protected]a93bb842010-02-16 23:03:47778
[email protected]d37231fa2010-04-09 21:16:02779 // Get the size (in pixels) of the currently bound frame buffer (either FBO
780 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30781 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02782
[email protected]9edc6b22010-12-23 02:00:26783 // Get the format of the currently bound frame buffer (either FBO or regular
784 // back buffer)
785 GLenum GetBoundReadFrameBufferInternalFormat();
786
[email protected]a93bb842010-02-16 23:03:47787 // Wrapper for CompressedTexImage2D commands.
788 error::Error DoCompressedTexImage2D(
789 GLenum target,
790 GLint level,
791 GLenum internal_format,
792 GLsizei width,
793 GLsizei height,
794 GLint border,
795 GLsizei image_size,
796 const void* data);
797
[email protected]cadde4a2010-07-31 17:10:43798 // Wrapper for CompressedTexSubImage2D.
799 void DoCompressedTexSubImage2D(
800 GLenum target,
801 GLint level,
802 GLint xoffset,
803 GLint yoffset,
804 GLsizei width,
805 GLsizei height,
806 GLenum format,
807 GLsizei imageSize,
808 const void * data);
809
810 // Wrapper for CopyTexImage2D.
811 void DoCopyTexImage2D(
812 GLenum target,
813 GLint level,
814 GLenum internal_format,
815 GLint x,
816 GLint y,
817 GLsizei width,
818 GLsizei height,
819 GLint border);
820
821 // Wrapper for CopyTexSubImage2D.
822 void DoCopyTexSubImage2D(
823 GLenum target,
824 GLint level,
825 GLint xoffset,
826 GLint yoffset,
827 GLint x,
828 GLint y,
829 GLsizei width,
830 GLsizei height);
831
[email protected]a93bb842010-02-16 23:03:47832 // Wrapper for TexImage2D commands.
833 error::Error DoTexImage2D(
834 GLenum target,
835 GLint level,
836 GLenum internal_format,
837 GLsizei width,
838 GLsizei height,
839 GLint border,
840 GLenum format,
841 GLenum type,
842 const void* pixels,
843 uint32 pixels_size);
844
[email protected]cadde4a2010-07-31 17:10:43845 // Wrapper for TexSubImage2D.
846 void DoTexSubImage2D(
847 GLenum target,
848 GLint level,
849 GLint xoffset,
850 GLint yoffset,
851 GLsizei width,
852 GLsizei height,
853 GLenum format,
854 GLenum type,
855 const void * data);
856
[email protected]a93bb842010-02-16 23:03:47857 // Creates a ProgramInfo for the given program.
[email protected]ae51d192010-04-27 00:48:03858 void CreateProgramInfo(GLuint client_id, GLuint service_id) {
859 program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47860 }
861
[email protected]07f54fcc2009-12-22 02:46:30862 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03863 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14864 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46865 }
[email protected]07f54fcc2009-12-22 02:46:30866
[email protected]6b8cf1a2010-05-06 16:13:58867 // Gets the program info for the given program. If it's not a program
868 // generates a GL error. Returns NULL if not program.
869 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
870 GLuint client_id, const char* function_name) {
871 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
872 if (!info) {
873 if (GetShaderInfo(client_id)) {
874 SetGLError(GL_INVALID_OPERATION,
875 (std::string(function_name) +
876 ": shader passed for program").c_str());
877 } else {
878 SetGLError(GL_INVALID_VALUE,
879 (std::string(function_name) + ": unknown program").c_str());
880 }
881 }
882 return info;
883 }
884
885
[email protected]45bf5152010-02-12 00:11:31886 // Creates a ShaderInfo for the given shader.
[email protected]7cea56d92010-04-28 17:21:38887 void CreateShaderInfo(GLuint client_id,
888 GLuint service_id,
889 GLenum shader_type) {
890 shader_manager()->CreateShaderInfo(client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31891 }
892
893 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03894 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14895 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31896 }
897
[email protected]6b8cf1a2010-05-06 16:13:58898 // Gets the shader info for the given shader. If it's not a shader generates a
899 // GL error. Returns NULL if not shader.
900 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
901 GLuint client_id, const char* function_name) {
902 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
903 if (!info) {
904 if (GetProgramInfo(client_id)) {
905 SetGLError(
906 GL_INVALID_OPERATION,
907 (std::string(function_name) +
908 ": program passed for shader").c_str());
909 } else {
910 SetGLError(GL_INVALID_VALUE,
911 (std::string(function_name) + ": unknown shader").c_str());
912 }
913 }
914 return info;
915 }
916
[email protected]a93bb842010-02-16 23:03:47917 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03918 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
919 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47920 }
921
[email protected]07f54fcc2009-12-22 02:46:30922 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03923 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
924 BufferManager::BufferInfo* info =
925 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50926 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46927 }
[email protected]07f54fcc2009-12-22 02:46:30928
[email protected]a93bb842010-02-16 23:03:47929 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
930 // on glDeleteBuffers so we can make sure the user does not try to render
931 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03932 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47933
[email protected]a25fa872010-03-25 02:57:58934 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03935 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
936 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58937 }
938
939 // Gets the framebuffer info for the given framebuffer.
940 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03941 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58942 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03943 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58944 return (info && !info->IsDeleted()) ? info : NULL;
945 }
946
947 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03948 void RemoveFramebufferInfo(GLuint client_id) {
949 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58950 }
951
952 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03953 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
954 return renderbuffer_manager()->CreateRenderbufferInfo(
955 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58956 }
957
958 // Gets the renderbuffer info for the given renderbuffer.
959 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03960 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58961 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03962 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58963 return (info && !info->IsDeleted()) ? info : NULL;
964 }
965
966 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03967 void RemoveRenderbufferInfo(GLuint client_id) {
968 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58969 }
970
[email protected]558847a2010-03-24 07:02:54971 error::Error GetAttribLocationHelper(
972 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
973 const std::string& name_str);
974
975 error::Error GetUniformLocationHelper(
976 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
977 const std::string& name_str);
978
[email protected]3916c97e2010-02-25 03:20:50979 // Helper for glShaderSource.
980 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03981 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30982
[email protected]3a2e7c7b2010-08-06 01:12:28983 // Clears any uncleared render buffers attached to the given frame buffer.
[email protected]8e3e0662010-08-23 18:46:30984 void ClearUnclearedRenderbuffers(
985 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28986
[email protected]c007aa02010-09-02 22:22:40987 // Restore all GL state that affects clearing.
988 void RestoreClearState();
989
[email protected]3a2e7c7b2010-08-06 01:12:28990 // Remembers the state of some capabilities.
991 void SetCapabilityState(GLenum cap, bool enabled);
992
[email protected]3a03a8f2011-03-19 00:51:27993 // Check that the current frame buffer is complete. Generates error if not.
994 bool CheckFramebufferComplete(const char* func_name);
995
[email protected]939e7362010-05-13 20:49:10996 // Checks if the current program exists and is valid. If not generates the
997 // appropriate GL error. Returns true if the current program is in a usable
998 // state.
999 bool CheckCurrentProgram(const char* function_name);
1000
1001 // Checks if the current program exists and is valid and that location is not
1002 // -1. If the current program is not valid generates the appropriate GL
1003 // error. Returns true if the current program is in a usable state and
1004 // location is not -1.
1005 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1006
1007 // Gets the type of a uniform for a location in the current program. Sets GL
1008 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:361009 // program is valid and the location exists. Adjusts count so it
1010 // does not overflow the uniform.
1011 bool PrepForSetUniformByLocation(
1012 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:101013
[email protected]b273e432010-04-12 17:23:581014 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1015 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1016
[email protected]96449d2c2009-11-25 00:01:321017 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:031018 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321019
1020 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:031021 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321022
[email protected]3916c97e2010-02-25 03:20:501023 // Wrapper for glActiveTexture
1024 void DoActiveTexture(GLenum texture_unit);
1025
[email protected]ae51d192010-04-27 00:48:031026 // Wrapper for glAttachShader
1027 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1028
[email protected]96449d2c2009-11-25 00:01:321029 // Wrapper for glBindBuffer since we need to track the current targets.
1030 void DoBindBuffer(GLenum target, GLuint buffer);
1031
[email protected]86093972010-03-11 00:13:561032 // Wrapper for glBindFramebuffer since we need to track the current targets.
1033 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1034
1035 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1036 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1037
[email protected]a93bb842010-02-16 23:03:471038 // Wrapper for glBindTexture since we need to track the current targets.
1039 void DoBindTexture(GLenum target, GLuint texture);
1040
[email protected]8e3e0662010-08-23 18:46:301041 // Wrapper for glBlitFramebufferEXT.
1042 void DoBlitFramebufferEXT(
1043 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1044 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1045 GLbitfield mask, GLenum filter);
1046
[email protected]36cef8ce2010-03-16 07:34:451047 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111048 void DoBufferData(
1049 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1050
[email protected]36cef8ce2010-03-16 07:34:451051 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111052 void DoBufferSubData(
1053 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1054
[email protected]36cef8ce2010-03-16 07:34:451055 // Wrapper for glCheckFramebufferStatus
1056 GLenum DoCheckFramebufferStatus(GLenum target);
1057
[email protected]3a03a8f2011-03-19 00:51:271058 // Wrapper for glClear
1059 void DoClear(GLbitfield mask);
1060
[email protected]3a2e7c7b2010-08-06 01:12:281061 // Wrappers for clear and mask settings functions.
1062 void DoClearColor(
1063 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1064 void DoClearDepthf(GLclampf depth);
1065 void DoClearStencil(GLint s);
1066 void DoColorMask(
1067 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1068 void DoDepthMask(GLboolean depth);
1069 void DoStencilMask(GLuint mask);
1070 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1071
[email protected]45bf5152010-02-12 00:11:311072 // Wrapper for glCompileShader.
1073 void DoCompileShader(GLuint shader);
1074
[email protected]269200b12010-11-18 22:53:061075 // Helper for DeleteSharedIdsCHROMIUM commands.
1076 void DoDeleteSharedIdsCHROMIUM(
1077 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101078
[email protected]ae51d192010-04-27 00:48:031079 // Wrapper for glDetachShader
1080 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1081
[email protected]07f54fcc2009-12-22 02:46:301082 // Wrapper for glDrawArrays.
1083 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
1084
[email protected]3a2e7c7b2010-08-06 01:12:281085 // Wrapper for glDisable
1086 void DoDisable(GLenum cap);
1087
[email protected]07f54fcc2009-12-22 02:46:301088 // Wrapper for glDisableVertexAttribArray.
1089 void DoDisableVertexAttribArray(GLuint index);
1090
[email protected]3a2e7c7b2010-08-06 01:12:281091 // Wrapper for glEnable
1092 void DoEnable(GLenum cap);
1093
[email protected]07f54fcc2009-12-22 02:46:301094 // Wrapper for glEnableVertexAttribArray.
1095 void DoEnableVertexAttribArray(GLuint index);
1096
[email protected]36cef8ce2010-03-16 07:34:451097 // Wrapper for glFramebufferRenderbufffer.
1098 void DoFramebufferRenderbuffer(
1099 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1100 GLuint renderbuffer);
1101
1102 // Wrapper for glFramebufferTexture2D.
1103 void DoFramebufferTexture2D(
1104 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1105 GLint level);
1106
[email protected]a93bb842010-02-16 23:03:471107 // Wrapper for glGenerateMipmap
1108 void DoGenerateMipmap(GLenum target);
1109
[email protected]269200b12010-11-18 22:53:061110 // Helper for GenSharedIdsCHROMIUM commands.
1111 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101112 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1113
[email protected]b273e432010-04-12 17:23:581114 // Wrapper for DoGetBooleanv.
1115 void DoGetBooleanv(GLenum pname, GLboolean* params);
1116
1117 // Wrapper for DoGetFloatv.
1118 void DoGetFloatv(GLenum pname, GLfloat* params);
1119
[email protected]36cef8ce2010-03-16 07:34:451120 // Wrapper for glGetFramebufferAttachmentParameteriv.
1121 void DoGetFramebufferAttachmentParameteriv(
1122 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1123
[email protected]a0c3e972010-04-21 00:49:131124 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581125 void DoGetIntegerv(GLenum pname, GLint* params);
1126
[email protected]29a9eb52010-04-13 09:04:231127 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061128 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231129 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1130
[email protected]a0c3e972010-04-21 00:49:131131 // Wrapper for glGetProgramiv.
1132 void DoGetProgramiv(
1133 GLuint program_id, GLenum pname, GLint* params);
1134
[email protected]36cef8ce2010-03-16 07:34:451135 // Wrapper for glRenderbufferParameteriv.
1136 void DoGetRenderbufferParameteriv(
1137 GLenum target, GLenum pname, GLint* params);
1138
[email protected]ddd968b82010-03-02 00:44:291139 // Wrapper for glGetShaderiv
1140 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1141
[email protected]b1122982010-05-17 23:04:241142 // Wrappers for glGetVertexAttrib.
1143 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1144 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1145
[email protected]1958e0e2010-04-22 05:17:151146 // Wrappers for glIsXXX functions.
1147 bool DoIsBuffer(GLuint client_id);
1148 bool DoIsFramebuffer(GLuint client_id);
1149 bool DoIsProgram(GLuint client_id);
1150 bool DoIsRenderbuffer(GLuint client_id);
1151 bool DoIsShader(GLuint client_id);
1152 bool DoIsTexture(GLuint client_id);
1153
[email protected]07f54fcc2009-12-22 02:46:301154 // Wrapper for glLinkProgram
1155 void DoLinkProgram(GLuint program);
1156
[email protected]269200b12010-11-18 22:53:061157 // Helper for RegisterSharedIdsCHROMIUM.
1158 void DoRegisterSharedIdsCHROMIUM(
1159 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101160
[email protected]36cef8ce2010-03-16 07:34:451161 // Wrapper for glRenderbufferStorage.
1162 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031163 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451164
[email protected]8e3e0662010-08-23 18:46:301165 // Wrapper for glRenderbufferStorageMultisampleEXT.
1166 void DoRenderbufferStorageMultisample(
1167 GLenum target, GLsizei samples, GLenum internalformat,
1168 GLsizei width, GLsizei height);
1169
[email protected]b273e432010-04-12 17:23:581170 // Wrapper for glReleaseShaderCompiler.
1171 void DoReleaseShaderCompiler() { }
1172
[email protected]3916c97e2010-02-25 03:20:501173 // Wrappers for glTexParameter functions.
1174 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1175 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1176 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1177 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1178
1179 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1180 // spec only these 2 functions can be used to set sampler uniforms.
1181 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101182 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:361183 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
1184 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
1185 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101186
1187 // Wrappers for glUniformfv because some drivers don't correctly accept
1188 // bool uniforms.
1189 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1190 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1191 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1192 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501193
[email protected]43c2f1f2011-03-25 18:35:361194 void DoUniformMatrix2fv(
1195 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1196 void DoUniformMatrix3fv(
1197 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1198 void DoUniformMatrix4fv(
1199 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1200
[email protected]b1122982010-05-17 23:04:241201 // Wrappers for glVertexAttrib??
1202 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1203 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1204 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1205 void DoVertexAttrib4f(
1206 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1207 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1208 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1209 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1210 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1211
[email protected]07f54fcc2009-12-22 02:46:301212 // Wrapper for glUseProgram
1213 void DoUseProgram(GLuint program);
1214
[email protected]ae51d192010-04-27 00:48:031215 // Wrapper for glValidateProgram.
1216 void DoValidateProgram(GLuint program_client_id);
1217
[email protected]269200b12010-11-18 22:53:061218 void DoCopyTextureToParentTextureCHROMIUM(GLuint client_texture_id,
[email protected]c007aa02010-09-02 22:22:401219 GLuint parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:561220
[email protected]43ecf372010-11-16 19:19:391221 void DoResizeCHROMIUM(GLuint width, GLuint height);
1222
[email protected]4e8a5b122010-05-08 22:00:101223 // Gets the number of values that will be returned by glGetXXX. Returns
1224 // false if pname is unknown.
1225 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1226
[email protected]96449d2c2009-11-25 00:01:321227 // Gets the GLError through our wrapper.
1228 GLenum GetGLError();
1229
1230 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:291231 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:321232
[email protected]07f54fcc2009-12-22 02:46:301233 // Copies the real GL errors to the wrapper. This is so we can
1234 // make sure there are no native GL errors before calling some GL function
1235 // so that on return we know any error generated was for that specific
1236 // command.
1237 void CopyRealGLErrorsToWrapper();
1238
[email protected]6217d392010-03-25 22:08:351239 // Clear all real GL errors. This is to prevent the client from seeing any
1240 // errors caused by GL calls that it was not responsible for issuing.
1241 void ClearRealGLErrors();
1242
[email protected]07f54fcc2009-12-22 02:46:301243 // Checks if the current program and vertex attributes are valid for drawing.
1244 bool IsDrawValid(GLuint max_vertex_accessed);
1245
[email protected]b1122982010-05-17 23:04:241246 // Returns true if attrib0 was simulated.
1247 bool SimulateAttrib0(GLuint max_vertex_accessed);
1248 void RestoreStateForSimulatedAttrib0();
1249
[email protected]ef526492010-06-02 23:12:251250 // Returns true if textures were set.
1251 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501252 void RestoreStateForNonRenderableTextures();
1253
[email protected]8fbedc02010-11-18 18:43:401254 // Returns true if GL_FIXED attribs were simulated.
1255 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1256 void RestoreStateForSimulatedFixedAttribs();
1257
[email protected]07f54fcc2009-12-22 02:46:301258 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501259 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301260 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501261 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1262 bound_array_buffer_ : bound_element_array_buffer_;
1263 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301264 }
1265
[email protected]a93bb842010-02-16 23:03:471266 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501267 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1268 TextureUnit& unit = texture_units_[active_texture_unit_];
1269 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471270 switch (target) {
1271 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501272 info = unit.bound_texture_2d;
1273 break;
[email protected]a93bb842010-02-16 23:03:471274 case GL_TEXTURE_CUBE_MAP:
1275 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1276 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1277 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1278 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1279 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1280 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501281 info = unit.bound_texture_cube_map;
1282 break;
[email protected]1aef98132010-02-23 18:00:071283 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1284 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1285 // because |texture_| is used by the FBO rendering mechanism for readback
1286 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471287 default:
1288 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501289 return NULL;
[email protected]a93bb842010-02-16 23:03:471290 }
[email protected]3916c97e2010-02-25 03:20:501291 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471292 }
1293
[email protected]8e3e0662010-08-23 18:46:301294 // Gets the framebuffer info for a particular target.
1295 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1296 GLenum target) {
1297 FramebufferManager::FramebufferInfo* info = NULL;
1298 switch (target) {
1299 case GL_FRAMEBUFFER:
1300 case GL_DRAW_FRAMEBUFFER:
1301 info = bound_draw_framebuffer_;
1302 break;
1303 case GL_READ_FRAMEBUFFER:
1304 info = bound_read_framebuffer_;
1305 break;
1306 default:
1307 NOTREACHED();
1308 break;
1309 }
1310 return (info && !info->IsDeleted()) ? info : NULL;
1311 }
1312
[email protected]f7b85372010-02-03 01:11:371313 // Validates the program and location for a glGetUniform call and returns
1314 // a SizeResult setup to receive the result. Returns true if glGetUniform
1315 // should be called.
1316 bool GetUniformSetup(
1317 GLuint program, GLint location,
1318 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101319 error::Error* error, GLuint* service_id, void** result,
1320 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371321
[email protected]96449d2c2009-11-25 00:01:321322 // Generate a member function prototype for each command in an automated and
1323 // typesafe way.
1324 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141325 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191326 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321327 const gles2::name& args); \
1328
1329 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1330
1331 #undef GLES2_CMD_OP
1332
[email protected]2f2d7042010-04-14 21:45:581333 // The GL context this decoder renders to on behalf of the client.
[email protected]66791e382010-07-14 20:48:301334 scoped_ptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021335
[email protected]a3ded6d2010-10-19 06:44:391336 // The ContextGroup for this decoder uses to track resources.
1337 ContextGroup::Ref group_;
1338
[email protected]6217d392010-03-25 22:08:351339 // A parent decoder can access this decoders saved offscreen frame buffer.
1340 // The parent pointer is reset if the parent is destroyed.
1341 base::WeakPtr<GLES2DecoderImpl> parent_;
1342
1343 // Width and height to which an offscreen frame buffer should be resized on
1344 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021345 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351346
[email protected]34ff8b0c2010-10-01 20:06:021347 // Current width and height of the offscreen frame buffer.
1348 gfx::Size offscreen_size_;
1349
[email protected]96449d2c2009-11-25 00:01:321350 // Current GL error bits.
1351 uint32 error_bits_;
1352
[email protected]96449d2c2009-11-25 00:01:321353 // Util to help with GL.
1354 GLES2Util util_;
1355
1356 // pack alignment as last set by glPixelStorei
1357 GLint pack_alignment_;
1358
1359 // unpack alignment as last set by glPixelStorei
1360 GLint unpack_alignment_;
1361
1362 // The currently bound array buffer. If this is 0 it is illegal to call
1363 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501364 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321365
1366 // The currently bound element array buffer. If this is 0 it is illegal
1367 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501368 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301369
[email protected]f39f4b3f2010-05-12 17:04:081370 // Class that manages vertex attribs.
1371 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301372
[email protected]b1122982010-05-17 23:04:241373 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1374 GLuint attrib_0_buffer_id_;
1375
1376 // The value currently in attrib_0.
1377 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1378
[email protected]fc753442011-02-04 19:49:491379 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1380 bool attrib_0_buffer_matches_value_;
1381
[email protected]b1122982010-05-17 23:04:241382 // The size of attrib 0.
1383 GLsizei attrib_0_size_;
1384
[email protected]8fbedc02010-11-18 18:43:401385 // The buffer used to simulate GL_FIXED attribs.
1386 GLuint fixed_attrib_buffer_id_;
1387
1388 // The size of fiixed attrib buffer.
1389 GLsizei fixed_attrib_buffer_size_;
1390
[email protected]3916c97e2010-02-25 03:20:501391 // Current active texture by 0 - n index.
1392 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1393 // be 2.
1394 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301395
[email protected]3916c97e2010-02-25 03:20:501396 // Which textures are bound to texture units through glActiveTexture.
1397 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471398
[email protected]3a2e7c7b2010-08-06 01:12:281399 // state saved for clearing so we can clear render buffers and then
1400 // restore to these values.
1401 GLclampf clear_red_;
1402 GLclampf clear_green_;
1403 GLclampf clear_blue_;
1404 GLclampf clear_alpha_;
1405 GLboolean mask_red_;
1406 GLboolean mask_green_;
1407 GLboolean mask_blue_;
1408 GLboolean mask_alpha_;
1409 GLint clear_stencil_;
1410 GLuint mask_stencil_front_;
1411 GLuint mask_stencil_back_;
1412 GLclampf clear_depth_;
1413 GLboolean mask_depth_;
1414 bool enable_scissor_test_;
1415
[email protected]1d32bc82010-01-13 22:06:461416 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501417 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301418
[email protected]8e3e0662010-08-23 18:46:301419 // The currently bound framebuffers
1420 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1421 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561422
1423 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081424 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561425
[email protected]b9363b22010-06-09 22:06:151426 // The offscreen frame buffer that the client renders to. With EGL, the
1427 // depth and stencil buffers are separate. With regular GL there is a single
1428 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1429 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351430 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1431 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021432 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151433 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1434 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021435 GLenum offscreen_target_color_format_;
1436 GLenum offscreen_target_depth_format_;
1437 GLenum offscreen_target_stencil_format_;
1438 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351439
[email protected]a3a93e7b2010-08-28 00:48:561440 GLuint copy_texture_to_parent_texture_fb_;
1441
[email protected]34ff8b0c2010-10-01 20:06:021442 // The copy that is saved when SwapBuffers is called. It is also
1443 // used as the destination for multi-sample resolves.
1444 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351445 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]97872062010-11-03 19:07:051446 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351447
[email protected]7ff86b92010-11-25 17:50:001448 scoped_ptr<Callback1<gfx::Size>::Type> resize_callback_;
[email protected]43f28f832010-02-03 02:28:481449 scoped_ptr<Callback0::Type> swap_buffers_callback_;
1450
[email protected]32fe9aa2011-01-21 23:47:131451 // The format of the back buffer_
1452 GLenum back_buffer_color_format_;
1453
[email protected]8eee29c2010-04-29 03:38:291454 // The last error message set.
1455 std::string last_error_;
1456
[email protected]a3a93e7b2010-08-28 00:48:561457 // The current decoder error.
1458 error::Error current_decoder_error_;
1459
[email protected]b1d2dcb2010-05-17 19:24:181460 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451461 scoped_ptr<ShaderTranslator> vertex_translator_;
1462 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181463
[email protected]c410da802011-03-14 19:17:411464 DisallowedExtensions disallowed_extensions_;
1465
[email protected]915a59a12010-09-30 21:29:111466 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051467 const Validators* validators_;
[email protected]915a59a12010-09-30 21:29:111468 FeatureInfo* feature_info_;
[email protected]9438b012010-06-15 22:55:051469
[email protected]96449d2c2009-11-25 00:01:321470 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1471};
1472
[email protected]6217d392010-03-25 22:08:351473ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1474 : decoder_(decoder) {
1475 decoder_->CopyRealGLErrorsToWrapper();
1476}
1477
1478ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1479 decoder_->ClearRealGLErrors();
1480}
1481
1482ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1483 GLuint id)
1484 : decoder_(decoder) {
1485 ScopedGLErrorSuppressor suppressor(decoder_);
1486
1487 // TODO(apatrick): Check if there are any other states that need to be reset
1488 // before binding a new texture.
1489 glActiveTexture(GL_TEXTURE0);
1490 glBindTexture(GL_TEXTURE_2D, id);
1491}
1492
1493ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1494 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301495 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351496}
1497
1498ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1499 GLuint id)
1500 : decoder_(decoder) {
1501 ScopedGLErrorSuppressor suppressor(decoder_);
1502 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1503}
1504
1505ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1506 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301507 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351508}
1509
1510ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1511 GLuint id)
1512 : decoder_(decoder) {
1513 ScopedGLErrorSuppressor suppressor(decoder_);
1514 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1515}
1516
1517ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1518 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301519 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351520}
1521
[email protected]34ff8b0c2010-10-01 20:06:021522ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1523 GLES2DecoderImpl* decoder) : decoder_(decoder) {
1524 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1525 decoder_->IsOffscreenBufferMultisampled() &&
1526 !decoder_->bound_read_framebuffer_.get());
1527 if (!resolve_and_bind_)
1528 return;
1529
1530 ScopedGLErrorSuppressor suppressor(decoder_);
1531 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1532 decoder_->offscreen_target_frame_buffer_->id());
1533 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT,
1534 decoder_->offscreen_saved_frame_buffer_->id());
1535 const int width = decoder_->offscreen_size_.width();
1536 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181537 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021538 if (IsAngle()) {
1539 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1540 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1541 } else {
1542 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1543 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1544 }
1545 glBindFramebufferEXT(GL_FRAMEBUFFER,
1546 decoder_->offscreen_saved_frame_buffer_->id());
1547}
1548
1549ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1550 if (!resolve_and_bind_)
1551 return;
1552
1553 ScopedGLErrorSuppressor suppressor(decoder_);
1554 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181555 if (decoder_->enable_scissor_test_) {
1556 glEnable(GL_SCISSOR_TEST);
1557 }
[email protected]34ff8b0c2010-10-01 20:06:021558}
1559
[email protected]6217d392010-03-25 22:08:351560Texture::Texture(GLES2DecoderImpl* decoder)
1561 : decoder_(decoder),
1562 id_(0) {
1563}
1564
1565Texture::~Texture() {
1566 // This does not destroy the render texture because that would require that
1567 // the associated GL context was current. Just check that it was explicitly
1568 // destroyed.
1569 DCHECK_EQ(id_, 0u);
1570}
1571
1572void Texture::Create() {
1573 ScopedGLErrorSuppressor suppressor(decoder_);
1574 Destroy();
1575 glGenTextures(1, &id_);
1576}
1577
[email protected]34ff8b0c2010-10-01 20:06:021578bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351579 DCHECK_NE(id_, 0u);
1580 ScopedGLErrorSuppressor suppressor(decoder_);
1581 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]8c515f82010-11-09 03:40:041582 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1583 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1584 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1585 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351586
1587 glTexImage2D(GL_TEXTURE_2D,
1588 0, // mip level
[email protected]34ff8b0c2010-10-01 20:06:021589 format,
[email protected]6217d392010-03-25 22:08:351590 size.width(),
1591 size.height(),
1592 0, // border
[email protected]34ff8b0c2010-10-01 20:06:021593 format,
[email protected]6217d392010-03-25 22:08:351594 GL_UNSIGNED_BYTE,
1595 NULL);
1596
[email protected]d37231fa2010-04-09 21:16:021597 size_ = size;
1598
[email protected]6217d392010-03-25 22:08:351599 return glGetError() == GL_NO_ERROR;
1600}
1601
1602void Texture::Copy(const gfx::Size& size) {
1603 DCHECK_NE(id_, 0u);
1604 ScopedGLErrorSuppressor suppressor(decoder_);
1605 ScopedTexture2DBinder binder(decoder_, id_);
1606 glCopyTexImage2D(GL_TEXTURE_2D,
1607 0, // level
1608 GL_RGBA,
1609 0, 0,
1610 size.width(),
1611 size.height(),
1612 0); // border
1613}
1614
1615void Texture::Destroy() {
1616 if (id_ != 0) {
1617 ScopedGLErrorSuppressor suppressor(decoder_);
1618 glDeleteTextures(1, &id_);
1619 id_ = 0;
1620 }
1621}
1622
[email protected]97872062010-11-03 19:07:051623void Texture::Invalidate() {
1624 id_ = 0;
1625}
1626
[email protected]6217d392010-03-25 22:08:351627RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1628 : decoder_(decoder),
1629 id_(0) {
1630}
1631
1632RenderBuffer::~RenderBuffer() {
1633 // This does not destroy the render buffer because that would require that
1634 // the associated GL context was current. Just check that it was explicitly
1635 // destroyed.
1636 DCHECK_EQ(id_, 0u);
1637}
1638
1639void RenderBuffer::Create() {
1640 ScopedGLErrorSuppressor suppressor(decoder_);
1641 Destroy();
1642 glGenRenderbuffersEXT(1, &id_);
1643}
1644
[email protected]34ff8b0c2010-10-01 20:06:021645bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1646 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351647 ScopedGLErrorSuppressor suppressor(decoder_);
1648 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021649 if (samples <= 1) {
1650 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1651 format,
1652 size.width(),
1653 size.height());
1654 } else {
1655 if (IsAngle()) {
1656 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1657 samples,
1658 format,
1659 size.width(),
1660 size.height());
1661 } else {
1662 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1663 samples,
1664 format,
1665 size.width(),
1666 size.height());
1667 }
1668 }
[email protected]6217d392010-03-25 22:08:351669 return glGetError() == GL_NO_ERROR;
1670}
1671
1672void RenderBuffer::Destroy() {
1673 if (id_ != 0) {
1674 ScopedGLErrorSuppressor suppressor(decoder_);
1675 glDeleteRenderbuffersEXT(1, &id_);
1676 id_ = 0;
1677 }
1678}
1679
[email protected]97872062010-11-03 19:07:051680void RenderBuffer::Invalidate() {
1681 id_ = 0;
1682}
1683
[email protected]6217d392010-03-25 22:08:351684FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1685 : decoder_(decoder),
1686 id_(0) {
1687}
1688
1689FrameBuffer::~FrameBuffer() {
1690 // This does not destroy the frame buffer because that would require that
1691 // the associated GL context was current. Just check that it was explicitly
1692 // destroyed.
1693 DCHECK_EQ(id_, 0u);
1694}
1695
1696void FrameBuffer::Create() {
1697 ScopedGLErrorSuppressor suppressor(decoder_);
1698 Destroy();
1699 glGenFramebuffersEXT(1, &id_);
1700}
1701
1702void FrameBuffer::AttachRenderTexture(Texture* texture) {
1703 DCHECK_NE(id_, 0u);
1704 ScopedGLErrorSuppressor suppressor(decoder_);
1705 ScopedFrameBufferBinder binder(decoder_, id_);
1706 GLuint attach_id = texture ? texture->id() : 0;
1707 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1708 GL_COLOR_ATTACHMENT0,
1709 GL_TEXTURE_2D,
1710 attach_id,
1711 0);
1712}
1713
[email protected]b9363b22010-06-09 22:06:151714void FrameBuffer::AttachRenderBuffer(GLenum target,
1715 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351716 DCHECK_NE(id_, 0u);
1717 ScopedGLErrorSuppressor suppressor(decoder_);
1718 ScopedFrameBufferBinder binder(decoder_, id_);
1719 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1720 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151721 target,
[email protected]6217d392010-03-25 22:08:351722 GL_RENDERBUFFER,
1723 attach_id);
1724}
1725
1726void FrameBuffer::Clear(GLbitfield buffers) {
1727 ScopedGLErrorSuppressor suppressor(decoder_);
1728 ScopedFrameBufferBinder binder(decoder_, id_);
1729 glClear(buffers);
1730}
1731
1732void FrameBuffer::Destroy() {
1733 if (id_ != 0) {
1734 ScopedGLErrorSuppressor suppressor(decoder_);
1735 glDeleteFramebuffersEXT(1, &id_);
1736 id_ = 0;
1737 }
1738}
1739
[email protected]97872062010-11-03 19:07:051740void FrameBuffer::Invalidate() {
1741 id_ = 0;
1742}
1743
[email protected]6217d392010-03-25 22:08:351744GLenum FrameBuffer::CheckStatus() {
1745 DCHECK_NE(id_, 0u);
1746 ScopedGLErrorSuppressor suppressor(decoder_);
1747 ScopedFrameBufferBinder binder(decoder_, id_);
1748 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1749}
1750
[email protected]3916c97e2010-02-25 03:20:501751GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1752 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321753}
1754
[email protected]3916c97e2010-02-25 03:20:501755GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391756 : GLES2Decoder(),
1757 group_(ContextGroup::Ref(group ? group : new ContextGroup())),
[email protected]96449d2c2009-11-25 00:01:321758 error_bits_(0),
1759 util_(0), // TODO(gman): Set to actual num compress texture formats.
1760 pack_alignment_(4),
1761 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241762 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491763 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241764 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401765 fixed_attrib_buffer_id_(0),
1766 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501767 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281768 clear_red_(0),
1769 clear_green_(0),
1770 clear_blue_(0),
1771 clear_alpha_(0),
1772 mask_red_(true),
1773 mask_green_(true),
1774 mask_blue_(true),
1775 mask_alpha_(true),
1776 clear_stencil_(0),
1777 mask_stencil_front_(-1),
1778 mask_stencil_back_(-1),
1779 clear_depth_(1.0f),
1780 mask_depth_(true),
1781 enable_scissor_test_(false),
[email protected]34ff8b0c2010-10-01 20:06:021782 offscreen_target_color_format_(0),
1783 offscreen_target_depth_format_(0),
1784 offscreen_target_stencil_format_(0),
1785 offscreen_target_samples_(0),
[email protected]5ea88812011-03-28 10:45:391786 copy_texture_to_parent_texture_fb_(0),
[email protected]97872062010-11-03 19:07:051787 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:131788 back_buffer_color_format_(0),
[email protected]a3a93e7b2010-08-28 00:48:561789 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051790 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111791 validators_(group_->feature_info()->validators()),
[email protected]34ff8b0c2010-10-01 20:06:021792 feature_info_(group_->feature_info()) {
[email protected]b1122982010-05-17 23:04:241793 attrib_0_value_.v[0] = 0.0f;
1794 attrib_0_value_.v[1] = 0.0f;
1795 attrib_0_value_.v[2] = 0.0f;
1796 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151797
[email protected]c2f8c8402010-12-06 18:07:241798 // The shader translator is used for WebGL even when running on EGL
1799 // because additional restrictions are needed (like only enabling
1800 // GL_OES_standard_derivatives on demand). It is used for the unit
1801 // tests because
1802 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1803 // empty string to CompileShader and this is not a valid shader.
1804 // TODO(apatrick): fix this test.
1805 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1806 !feature_info_->feature_flags().chromium_webglsl) ||
[email protected]b9363b22010-06-09 22:06:151807 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1808 use_shader_translator_ = false;
1809 }
[email protected]96449d2c2009-11-25 00:01:321810}
1811
[email protected]c410da802011-03-14 19:17:411812bool GLES2DecoderImpl::Initialize(
1813 gfx::GLContext* context,
1814 const gfx::Size& size,
1815 const DisallowedExtensions& disallowed_extensions,
1816 const char* allowed_extensions,
1817 const std::vector<int32>& attribs,
1818 GLES2Decoder* parent,
1819 uint32 parent_client_texture_id) {
[email protected]4bedba72010-04-20 22:08:541820 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301821 DCHECK(!context_.get());
1822
1823 // Take ownership of the GLContext.
1824 context_.reset(context);
[email protected]d37231fa2010-04-09 21:16:021825
[email protected]6217d392010-03-25 22:08:351826 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021827 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351828 if (parent)
1829 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1830
[email protected]246a70452010-03-05 21:53:501831 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011832 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1833 << "MakeCurrent failed.";
[email protected]246a70452010-03-05 21:53:501834 Destroy();
1835 return false;
[email protected]eb54a562010-01-20 21:55:181836 }
1837
[email protected]c410da802011-03-14 19:17:411838 if (!group_->Initialize(disallowed_extensions, allowed_extensions)) {
[email protected]a3ded6d2010-10-19 06:44:391839 LOG(ERROR) << "GPUProcessor::InitializeCommon failed because group "
1840 << "failed to initialize.";
1841 Destroy();
[email protected]ae1741092010-11-17 19:16:031842 return false;
[email protected]a3ded6d2010-10-19 06:44:391843 }
1844
[email protected]246a70452010-03-05 21:53:501845 CHECK_GL_ERROR();
[email protected]c410da802011-03-14 19:17:411846 disallowed_extensions_ = disallowed_extensions;
[email protected]246a70452010-03-05 21:53:501847
[email protected]f39f4b3f2010-05-12 17:04:081848 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321849
[email protected]32fe9aa2011-01-21 23:47:131850 GLint v = 0;
1851 glGetIntegerv(GL_ALPHA_BITS, &v);
1852 back_buffer_color_format_ = v ? GL_RGBA : GL_RGB;
1853
[email protected]1071e572011-02-09 20:00:121854 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1855 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1856 // OpenGL ES 2.0 does not have this issue.
1857 glEnableVertexAttribArray(0);
1858 }
[email protected]b1122982010-05-17 23:04:241859 glGenBuffersARB(1, &attrib_0_buffer_id_);
1860 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1861 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1862 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401863 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081864
[email protected]246a70452010-03-05 21:53:501865 texture_units_.reset(
1866 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151867 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491868 glActiveTexture(GL_TEXTURE0 + tt);
1869 // Do cube map first because we want the last bind to be 2D.
1870 TextureManager::TextureInfo* info =
[email protected]1958e0e2010-04-22 05:17:151871 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491872 texture_units_[tt].bound_texture_cube_map = info;
1873 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1874 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1875 texture_units_[tt].bound_texture_2d = info;
1876 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151877 }
[email protected]00f893d2010-08-24 18:55:491878 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501879 CHECK_GL_ERROR();
1880
[email protected]d37231fa2010-04-09 21:16:021881 if (context_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:021882 ContextCreationAttribParser attrib_parser;
1883 if (!attrib_parser.Parse(attribs))
1884 return false;
1885
1886 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:541887 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:021888 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
1889 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:431890 // max_sample_count must be initialized to a sane value. If
1891 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
1892 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:021893 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
1894 offscreen_target_samples_ = std::min(attrib_parser.samples_,
1895 max_sample_count);
1896 } else {
1897 offscreen_target_samples_ = 1;
1898 }
1899
1900 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1901 const bool rgb8_supported =
1902 context_->HasExtension("GL_OES_rgb8_rgba8");
1903 // The only available default render buffer formats in GLES2 have very
1904 // little precision. Don't enable multisampling unless 8-bit render
1905 // buffer formats are available--instead fall back to 8-bit textures.
1906 if (rgb8_supported && offscreen_target_samples_ > 1) {
1907 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1908 GL_RGBA8 : GL_RGB8;
1909 } else {
1910 offscreen_target_samples_ = 1;
1911 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1912 GL_RGBA : GL_RGB;
1913 }
1914
1915 // ANGLE only supports packed depth/stencil formats, so use it if it is
1916 // available.
1917 const bool depth24_stencil8_supported =
1918 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271919 VLOG(1) << "GL_OES_packed_depth_stencil "
1920 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:001921 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1922 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021923 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1924 offscreen_target_stencil_format_ = 0;
1925 } else {
1926 // It may be the case that this depth/stencil combination is not
1927 // supported, but this will be checked later by CheckFramebufferStatus.
1928 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1929 GL_DEPTH_COMPONENT16 : 0;
1930 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1931 GL_STENCIL_INDEX8 : 0;
1932 }
1933 } else {
1934 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1935 GL_RGBA : GL_RGB;
1936
1937 // If depth is requested at all, use the packed depth stencil format if
1938 // it's available, as some desktop GL drivers don't support any non-packed
1939 // formats for depth attachments.
1940 const bool depth24_stencil8_supported =
1941 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271942 VLOG(1) << "GL_EXT_packed_depth_stencil "
1943 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:021944
[email protected]71ee3642010-10-14 18:08:001945 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1946 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021947 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1948 offscreen_target_stencil_format_ = 0;
1949 } else {
1950 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1951 GL_DEPTH_COMPONENT : 0;
1952 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1953 GL_STENCIL_INDEX : 0;
1954 }
1955 }
1956
[email protected]97872062010-11-03 19:07:051957 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
1958 GL_RGBA : GL_RGB;
1959
[email protected]6217d392010-03-25 22:08:351960 // Create the target frame buffer. This is the one that the client renders
1961 // directly to.
1962 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1963 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021964 // Due to GLES2 format limitations, either the color texture (for
1965 // non-multisampling) or the color render buffer (for multisampling) will be
1966 // attached to the offscreen frame buffer. The render buffer has more
1967 // limited formats available to it, but the texture can't do multisampling.
1968 if (IsOffscreenBufferMultisampled()) {
1969 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
1970 offscreen_target_color_render_buffer_->Create();
1971 } else {
1972 offscreen_target_color_texture_.reset(new Texture(this));
1973 offscreen_target_color_texture_->Create();
1974 }
1975 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151976 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021977 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151978 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:351979
1980 // Create the saved offscreen texture. The target frame buffer is copied
1981 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021982 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
1983 offscreen_saved_frame_buffer_->Create();
1984 //
[email protected]6217d392010-03-25 22:08:351985 offscreen_saved_color_texture_.reset(new Texture(this));
1986 offscreen_saved_color_texture_->Create();
1987
[email protected]6217d392010-03-25 22:08:351988 // Map the ID of the saved offscreen texture into the parent so that
1989 // it can reference it.
1990 if (parent_) {
1991 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]6217d392010-03-25 22:08:351992 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:031993 parent_->CreateTextureInfo(parent_client_texture_id, service_id);
[email protected]4874aae2011-03-18 01:19:561994 info->SetNotOwned();
[email protected]6217d392010-03-25 22:08:351995 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
1996 }
1997
1998 // Allocate the render buffers at their initial size and check the status
1999 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:022000 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352001 if (!UpdateOffscreenFrameBufferSize()) {
[email protected]d0498742010-09-20 20:27:012002 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352003 Destroy();
2004 return false;
2005 }
2006
2007 // Bind to the new default frame buffer (the offscreen target frame buffer).
2008 // This should now be associated with ID zero.
2009 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]a3a93e7b2010-08-28 00:48:562010
2011 glGenFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:352012 }
2013
[email protected]76a0ee102010-04-07 21:03:042014 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2015 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2016 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372017 // mailing list archives. It also implicitly enables the desktop GL
2018 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2019 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152020 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2021 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372022 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152023 }
[email protected]de17df392010-04-23 21:09:412024
[email protected]c2f8c8402010-12-06 18:07:242025 if (!InitializeShaderTranslator()) {
2026 return false;
[email protected]de17df392010-04-23 21:09:412027 }
[email protected]76a0ee102010-04-07 21:03:042028
[email protected]246a70452010-03-05 21:53:502029 return true;
[email protected]96449d2c2009-11-25 00:01:322030}
2031
[email protected]c2f8c8402010-12-06 18:07:242032bool GLES2DecoderImpl::InitializeShaderTranslator() {
2033 // Re-check the state of use_shader_translator_ each time this is called.
2034 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
2035 feature_info_->feature_flags().chromium_webglsl &&
2036 !use_shader_translator_) {
2037 use_shader_translator_ = true;
2038 }
2039 if (!use_shader_translator_) {
2040 return true;
2041 }
2042 ShBuiltInResources resources;
2043 ShInitBuiltInResources(&resources);
2044 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2045 resources.MaxVertexUniformVectors =
2046 group_->max_vertex_uniform_vectors();
2047 resources.MaxVaryingVectors = group_->max_varying_vectors();
2048 resources.MaxVertexTextureImageUnits =
2049 group_->max_vertex_texture_image_units();
2050 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2051 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2052 resources.MaxFragmentUniformVectors =
2053 group_->max_fragment_uniform_vectors();
2054 resources.MaxDrawBuffers = 1;
2055 resources.OES_standard_derivatives =
2056 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
2057 vertex_translator_.reset(new ShaderTranslator);
2058 ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ?
2059 SH_WEBGL_SPEC : SH_GLES2_SPEC;
2060 bool is_glsl_es =
2061 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
2062 if (!vertex_translator_->Init(
2063 SH_VERTEX_SHADER, shader_spec, &resources, is_glsl_es)) {
2064 LOG(ERROR) << "Could not initialize vertex shader translator.";
2065 Destroy();
2066 return false;
2067 }
2068 fragment_translator_.reset(new ShaderTranslator);
2069 if (!fragment_translator_->Init(
2070 SH_FRAGMENT_SHADER, shader_spec, &resources, is_glsl_es)) {
2071 LOG(ERROR) << "Could not initialize fragment shader translator.";
2072 Destroy();
2073 return false;
2074 }
2075 return true;
2076}
2077
[email protected]ae51d192010-04-27 00:48:032078bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472079 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032080 if (GetBufferInfo(client_ids[ii])) {
2081 return false;
2082 }
2083 }
2084 scoped_array<GLuint> service_ids(new GLuint[n]);
2085 glGenBuffersARB(n, service_ids.get());
2086 for (GLsizei ii = 0; ii < n; ++ii) {
2087 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2088 }
2089 return true;
2090}
2091
2092bool GLES2DecoderImpl::GenFramebuffersHelper(
2093 GLsizei n, const GLuint* client_ids) {
2094 for (GLsizei ii = 0; ii < n; ++ii) {
2095 if (GetFramebufferInfo(client_ids[ii])) {
2096 return false;
2097 }
2098 }
2099 scoped_array<GLuint> service_ids(new GLuint[n]);
2100 glGenFramebuffersEXT(n, service_ids.get());
2101 for (GLsizei ii = 0; ii < n; ++ii) {
2102 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2103 }
2104 return true;
2105}
2106
2107bool GLES2DecoderImpl::GenRenderbuffersHelper(
2108 GLsizei n, const GLuint* client_ids) {
2109 for (GLsizei ii = 0; ii < n; ++ii) {
2110 if (GetRenderbufferInfo(client_ids[ii])) {
2111 return false;
2112 }
2113 }
2114 scoped_array<GLuint> service_ids(new GLuint[n]);
2115 glGenRenderbuffersEXT(n, service_ids.get());
2116 for (GLsizei ii = 0; ii < n; ++ii) {
2117 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2118 }
2119 return true;
2120}
2121
2122bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2123 for (GLsizei ii = 0; ii < n; ++ii) {
2124 if (GetTextureInfo(client_ids[ii])) {
2125 return false;
2126 }
2127 }
2128 scoped_array<GLuint> service_ids(new GLuint[n]);
2129 glGenTextures(n, service_ids.get());
2130 for (GLsizei ii = 0; ii < n; ++ii) {
2131 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2132 }
2133 return true;
2134}
2135
2136void GLES2DecoderImpl::DeleteBuffersHelper(
2137 GLsizei n, const GLuint* client_ids) {
2138 for (GLsizei ii = 0; ii < n; ++ii) {
2139 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
2140 if (info) {
2141 GLuint service_id = info->service_id();
2142 glDeleteBuffersARB(1, &service_id);
2143 RemoveBufferInfo(client_ids[ii]);
2144 }
[email protected]a93bb842010-02-16 23:03:472145 }
[email protected]07f54fcc2009-12-22 02:46:302146}
2147
[email protected]ae51d192010-04-27 00:48:032148void GLES2DecoderImpl::DeleteFramebuffersHelper(
2149 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582150 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032151 FramebufferManager::FramebufferInfo* info =
2152 GetFramebufferInfo(client_ids[ii]);
2153 if (info) {
2154 GLuint service_id = info->service_id();
2155 glDeleteFramebuffersEXT(1, &service_id);
2156 RemoveFramebufferInfo(client_ids[ii]);
2157 }
[email protected]a25fa872010-03-25 02:57:582158 }
[email protected]07f54fcc2009-12-22 02:46:302159}
2160
[email protected]ae51d192010-04-27 00:48:032161void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2162 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582163 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032164 RenderbufferManager::RenderbufferInfo* info =
2165 GetRenderbufferInfo(client_ids[ii]);
2166 if (info) {
2167 GLuint service_id = info->service_id();
2168 glDeleteRenderbuffersEXT(1, &service_id);
2169 RemoveRenderbufferInfo(client_ids[ii]);
2170 }
[email protected]a25fa872010-03-25 02:57:582171 }
[email protected]07f54fcc2009-12-22 02:46:302172}
2173
[email protected]ae51d192010-04-27 00:48:032174void GLES2DecoderImpl::DeleteTexturesHelper(
2175 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472176 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032177 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
2178 if (info) {
2179 GLuint service_id = info->service_id();
2180 glDeleteTextures(1, &service_id);
2181 RemoveTextureInfo(client_ids[ii]);
2182 }
[email protected]a93bb842010-02-16 23:03:472183 }
[email protected]07f54fcc2009-12-22 02:46:302184}
2185
[email protected]43f28f832010-02-03 02:28:482186// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322187
[email protected]eb54a562010-01-20 21:55:182188bool GLES2DecoderImpl::MakeCurrent() {
[email protected]66791e382010-07-14 20:48:302189 return context_.get() ? context_->MakeCurrent() : false;
[email protected]eb54a562010-01-20 21:55:182190}
2191
[email protected]8e3e0662010-08-23 18:46:302192void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2193 glBindRenderbufferEXT(
2194 GL_RENDERBUFFER,
2195 bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
2196}
2197
2198static void RebindCurrentFramebuffer(
2199 GLenum target,
2200 FramebufferManager::FramebufferInfo* info,
2201 FrameBuffer* offscreen_frame_buffer) {
2202 GLuint framebuffer_id = info ? info->service_id() : 0;
2203 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2204 framebuffer_id = offscreen_frame_buffer->id();
2205 }
2206 glBindFramebufferEXT(target, framebuffer_id);
2207}
2208
2209void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]a3ded6d2010-10-19 06:44:392210 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302211 RebindCurrentFramebuffer(
2212 GL_FRAMEBUFFER,
2213 bound_draw_framebuffer_.get(),
2214 offscreen_target_frame_buffer_.get());
2215 } else {
2216 RebindCurrentFramebuffer(
2217 GL_READ_FRAMEBUFFER_EXT,
2218 bound_read_framebuffer_.get(),
2219 offscreen_target_frame_buffer_.get());
2220 RebindCurrentFramebuffer(
2221 GL_DRAW_FRAMEBUFFER_EXT,
2222 bound_draw_framebuffer_.get(),
2223 offscreen_target_frame_buffer_.get());
2224 }
2225}
2226
2227void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2228 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2229 GLuint last_id;
2230 if (info.bound_texture_2d) {
2231 last_id = info.bound_texture_2d->service_id();
2232 } else {
2233 last_id = 0;
2234 }
2235
2236 glBindTexture(GL_TEXTURE_2D, last_id);
2237 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2238}
2239
[email protected]3a03a8f2011-03-19 00:51:272240bool GLES2DecoderImpl::CheckFramebufferComplete(const char* func_name) {
2241 if (bound_draw_framebuffer_ && bound_draw_framebuffer_->IsNotComplete()) {
2242 SetGLError(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
2243 (std::string(func_name) + " framebuffer incomplete").c_str());
2244 return false;
2245 }
2246 return true;
2247}
2248
[email protected]8e3e0662010-08-23 18:46:302249gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2250 if (bound_read_framebuffer_ != 0) {
[email protected]9edc6b22010-12-23 02:00:262251 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2252 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2253 if (attachment) {
2254 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502255 }
[email protected]9edc6b22010-12-23 02:00:262256 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022257 } else if (offscreen_target_frame_buffer_.get()) {
2258 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352259 } else {
[email protected]d37231fa2010-04-09 21:16:022260 return context_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022261 }
[email protected]246a70452010-03-05 21:53:502262}
2263
[email protected]9edc6b22010-12-23 02:00:262264GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
2265 if (bound_read_framebuffer_ != 0) {
2266 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2267 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2268 if (attachment) {
2269 return attachment->internal_format();
2270 }
2271 return 0;
2272 } else if (offscreen_target_frame_buffer_.get()) {
2273 return offscreen_target_color_format_;
2274 } else {
[email protected]32fe9aa2011-01-21 23:47:132275 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262276 }
2277}
2278
[email protected]6217d392010-03-25 22:08:352279bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]34ff8b0c2010-10-01 20:06:022280 if (offscreen_size_ == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:352281 return true;
2282
[email protected]34ff8b0c2010-10-01 20:06:022283 offscreen_size_ = pending_offscreen_size_;
[email protected]a470d612011-02-25 04:15:002284 int w = offscreen_size_.width();
2285 int h = offscreen_size_.height();
2286 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2287 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2288 << "to allocate storage due to excessive dimensions.";
2289 return false;
2290 }
[email protected]34ff8b0c2010-10-01 20:06:022291
[email protected]6217d392010-03-25 22:08:352292 // Reallocate the offscreen target buffers.
[email protected]34ff8b0c2010-10-01 20:06:022293 DCHECK(offscreen_target_color_format_);
2294 if (IsOffscreenBufferMultisampled()) {
2295 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2296 pending_offscreen_size_, offscreen_target_color_format_,
2297 offscreen_target_samples_)) {
2298 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2299 << "to allocate storage for offscreen target color buffer.";
2300 return false;
2301 }
2302 } else {
2303 if (!offscreen_target_color_texture_->AllocateStorage(
2304 pending_offscreen_size_, offscreen_target_color_format_)) {
2305 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2306 << "to allocate storage for offscreen target color texture.";
2307 return false;
2308 }
2309 }
2310 if (offscreen_target_depth_format_ &&
2311 !offscreen_target_depth_render_buffer_->AllocateStorage(
2312 pending_offscreen_size_, offscreen_target_depth_format_,
2313 offscreen_target_samples_)) {
[email protected]d0498742010-09-20 20:27:012314 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
[email protected]34ff8b0c2010-10-01 20:06:022315 << "to allocate storage for offscreen target depth buffer.";
2316 return false;
2317 }
2318 if (offscreen_target_stencil_format_ &&
2319 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2320 pending_offscreen_size_, offscreen_target_stencil_format_,
2321 offscreen_target_samples_)) {
2322 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2323 << "to allocate storage for offscreen target stencil buffer.";
[email protected]6217d392010-03-25 22:08:352324 return false;
2325 }
2326
[email protected]2f2d7042010-04-14 21:45:582327 // Attach the offscreen target buffers to the target frame buffer.
[email protected]34ff8b0c2010-10-01 20:06:022328 if (IsOffscreenBufferMultisampled()) {
[email protected]b9363b22010-06-09 22:06:152329 offscreen_target_frame_buffer_->AttachRenderBuffer(
[email protected]34ff8b0c2010-10-01 20:06:022330 GL_COLOR_ATTACHMENT0,
2331 offscreen_target_color_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152332 } else {
[email protected]34ff8b0c2010-10-01 20:06:022333 offscreen_target_frame_buffer_->AttachRenderTexture(
2334 offscreen_target_color_texture_.get());
2335 }
2336 if (offscreen_target_depth_format_) {
2337 offscreen_target_frame_buffer_->AttachRenderBuffer(
2338 GL_DEPTH_ATTACHMENT,
2339 offscreen_target_depth_render_buffer_.get());
2340 }
2341 const bool packed_depth_stencil =
2342 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2343 if (packed_depth_stencil) {
[email protected]b9363b22010-06-09 22:06:152344 offscreen_target_frame_buffer_->AttachRenderBuffer(
2345 GL_STENCIL_ATTACHMENT,
2346 offscreen_target_depth_render_buffer_.get());
[email protected]34ff8b0c2010-10-01 20:06:022347 } else if (offscreen_target_stencil_format_) {
2348 offscreen_target_frame_buffer_->AttachRenderBuffer(
2349 GL_STENCIL_ATTACHMENT,
2350 offscreen_target_stencil_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152351 }
[email protected]34ff8b0c2010-10-01 20:06:022352
[email protected]6217d392010-03-25 22:08:352353 if (offscreen_target_frame_buffer_->CheckStatus() !=
2354 GL_FRAMEBUFFER_COMPLETE) {
[email protected]d0498742010-09-20 20:27:012355 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2356 << "because offscreen FBO was incomplete.";
[email protected]6217d392010-03-25 22:08:352357 return false;
2358 }
2359
[email protected]c007aa02010-09-02 22:22:402360 // Clear the target frame buffer.
2361 {
2362 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]3f0add5e2010-09-13 20:16:282363 glClearColor(0, 0, 0, 0);
[email protected]c007aa02010-09-02 22:22:402364 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2365 glClearStencil(0);
2366 glStencilMaskSeparate(GL_FRONT, GL_TRUE);
2367 glStencilMaskSeparate(GL_BACK, GL_TRUE);
2368 glClearDepth(0);
2369 glDepthMask(GL_TRUE);
2370 glDisable(GL_SCISSOR_TEST);
[email protected]2f2d7042010-04-14 21:45:582371 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402372 RestoreClearState();
[email protected]2f2d7042010-04-14 21:45:582373 }
[email protected]2f2d7042010-04-14 21:45:582374
[email protected]34ff8b0c2010-10-01 20:06:022375 if (parent_ || IsOffscreenBufferMultisampled()) {
[email protected]97872062010-11-03 19:07:052376 DCHECK(offscreen_saved_color_format_);
2377 offscreen_saved_color_texture_->AllocateStorage(
2378 pending_offscreen_size_, offscreen_saved_color_format_);
[email protected]d37231fa2010-04-09 21:16:022379
[email protected]34ff8b0c2010-10-01 20:06:022380 offscreen_saved_frame_buffer_->AttachRenderTexture(
2381 offscreen_saved_color_texture_.get());
2382 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2383 GL_FRAMEBUFFER_COMPLETE) {
2384 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2385 << "because offscreen saved FBO was incomplete.";
2386 return false;
2387 }
2388 }
2389
2390 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582391 // Update the info about the offscreen saved color texture in the parent.
2392 // The reference to the parent is a weak pointer and will become null if the
2393 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352394 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142395 GLuint client_id;
[email protected]262d7aa2010-12-03 22:07:292396 TextureManager* parent_texture_manager = parent_->texture_manager();
2397 CHECK(parent_texture_manager->GetClientId(service_id, &client_id));
[email protected]8d25d042010-06-16 19:48:142398 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352399 DCHECK(info);
2400
[email protected]262d7aa2010-12-03 22:07:292401 parent_texture_manager->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:112402 feature_info_,
[email protected]ef526492010-06-02 23:12:252403 info,
2404 GL_TEXTURE_2D,
2405 0, // level
2406 GL_RGBA,
2407 pending_offscreen_size_.width(),
2408 pending_offscreen_size_.height(),
2409 1, // depth
2410 0, // border
2411 GL_RGBA,
2412 GL_UNSIGNED_BYTE);
[email protected]262d7aa2010-12-03 22:07:292413 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042414 feature_info_,
2415 info,
2416 GL_TEXTURE_MAG_FILTER,
2417 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292418 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042419 feature_info_,
2420 info,
2421 GL_TEXTURE_MIN_FILTER,
2422 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292423 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042424 feature_info_,
2425 info,
2426 GL_TEXTURE_WRAP_S,
2427 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292428 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042429 feature_info_,
2430 info,
2431 GL_TEXTURE_WRAP_T,
2432 GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:352433
[email protected]c007aa02010-09-02 22:22:402434 // Clear the offscreen color texture.
2435 {
[email protected]34ff8b0c2010-10-01 20:06:022436 ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:402437 glClearColor(0, 0, 0, 0);
2438 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2439 glDisable(GL_SCISSOR_TEST);
[email protected]0c8c9d22010-06-25 17:36:392440 glClear(GL_COLOR_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402441 RestoreClearState();
[email protected]0c8c9d22010-06-25 17:36:392442 }
[email protected]0c8c9d22010-06-25 17:36:392443 }
[email protected]e566b955d2010-06-22 19:26:512444
[email protected]6217d392010-03-25 22:08:352445 return true;
2446}
2447
[email protected]7ff86b92010-11-25 17:50:002448void GLES2DecoderImpl::SetResizeCallback(Callback1<gfx::Size>::Type* callback) {
2449 resize_callback_.reset(callback);
2450}
2451
[email protected]43f28f832010-02-03 02:28:482452void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
2453 swap_buffers_callback_.reset(callback);
2454}
2455
[email protected]1318e922010-09-17 22:03:162456bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2457 uint32* service_texture_id) {
2458 TextureManager::TextureInfo* texture =
2459 texture_manager()->GetTextureInfo(client_texture_id);
2460 if (texture) {
2461 *service_texture_id = texture->service_id();
2462 return true;
2463 }
2464 return false;
2465}
2466
[email protected]96449d2c2009-11-25 00:01:322467void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392468 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052469
2470 if (group_.get())
2471 group_->set_have_context(have_context);
2472
[email protected]eadc96792010-10-27 19:39:392473 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142474 if (current_program_) {
2475 program_manager()->UnuseProgram(shader_manager(), current_program_);
2476 current_program_ = NULL;
2477 }
2478
[email protected]b1122982010-05-17 23:04:242479 if (attrib_0_buffer_id_) {
2480 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2481 }
[email protected]8fbedc02010-11-18 18:43:402482 if (fixed_attrib_buffer_id_) {
2483 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2484 }
[email protected]b1122982010-05-17 23:04:242485
[email protected]4bedba72010-04-20 22:08:542486 // Remove the saved frame buffer mapping from the parent decoder. The
2487 // parent pointer is a weak pointer so it will be null if the parent has
2488 // already been destroyed.
2489 if (parent_) {
2490 // First check the texture has been mapped into the parent. This might not
2491 // be the case if initialization failed midway through.
2492 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]ae51d192010-04-27 00:48:032493 GLuint client_id = 0;
2494 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]915a59a12010-09-30 21:29:112495 parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]4bedba72010-04-20 22:08:542496 }
[email protected]a3a93e7b2010-08-28 00:48:562497
2498 glDeleteFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:352499 }
[email protected]6217d392010-03-25 22:08:352500
[email protected]97872062010-11-03 19:07:052501 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542502 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052503 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542504 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052505 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022506 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052507 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152508 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052509 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152510 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052511 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022512 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052513 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542514 offscreen_saved_color_texture_->Destroy();
[email protected]66791e382010-07-14 20:48:302515
[email protected]eadc96792010-10-27 19:39:392516 // must release the ContextGroup before destroying the context as its
2517 // destructor uses GL.
2518 group_ = NULL;
2519
[email protected]66791e382010-07-14 20:48:302520 context_->Destroy();
2521 context_.reset();
[email protected]97872062010-11-03 19:07:052522 } else {
2523 if (offscreen_target_frame_buffer_.get())
2524 offscreen_target_frame_buffer_->Invalidate();
2525 if (offscreen_target_color_texture_.get())
2526 offscreen_target_color_texture_->Invalidate();
2527 if (offscreen_target_color_render_buffer_.get())
2528 offscreen_target_color_render_buffer_->Invalidate();
2529 if (offscreen_target_depth_render_buffer_.get())
2530 offscreen_target_depth_render_buffer_->Invalidate();
2531 if (offscreen_target_stencil_render_buffer_.get())
2532 offscreen_target_stencil_render_buffer_->Invalidate();
2533 if (offscreen_saved_frame_buffer_.get())
2534 offscreen_saved_frame_buffer_->Invalidate();
2535 if (offscreen_saved_color_texture_.get())
2536 offscreen_saved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022537 }
[email protected]97872062010-11-03 19:07:052538
2539 offscreen_target_frame_buffer_.reset();
2540 offscreen_target_color_texture_.reset();
2541 offscreen_target_color_render_buffer_.reset();
2542 offscreen_target_depth_render_buffer_.reset();
2543 offscreen_target_stencil_render_buffer_.reset();
2544 offscreen_saved_frame_buffer_.reset();
2545 offscreen_saved_color_texture_.reset();
[email protected]96449d2c2009-11-25 00:01:322546}
2547
[email protected]6217d392010-03-25 22:08:352548void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2549 // We can't resize the render buffers immediately because there might be a
2550 // partial frame rendered into them and we don't want the tail end of that
2551 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:022552 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352553}
2554
[email protected]269200b12010-11-18 22:53:062555void GLES2DecoderImpl::DoCopyTextureToParentTextureCHROMIUM(
[email protected]c007aa02010-09-02 22:22:402556 GLuint client_texture_id,
2557 GLuint parent_client_texture_id) {
[email protected]a3a93e7b2010-08-28 00:48:562558 if (parent_) {
[email protected]c007aa02010-09-02 22:22:402559 TextureManager::TextureInfo* texture = texture_manager()->GetTextureInfo(
2560 client_texture_id);
2561 TextureManager::TextureInfo* parent_texture =
2562 parent_->texture_manager()->GetTextureInfo(parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:562563 if (!texture || !parent_texture) {
2564 current_decoder_error_ = error::kInvalidArguments;
2565 return;
2566 }
2567 ScopedFrameBufferBinder fb_binder(this, copy_texture_to_parent_texture_fb_);
2568 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2569 GL_COLOR_ATTACHMENT0,
2570 GL_TEXTURE_2D,
2571 texture->service_id(),
2572 0);
2573 ScopedTexture2DBinder tex_binder(this, parent_texture->service_id());
2574 GLsizei width, height;
2575 parent_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
2576 glCopyTexImage2D(GL_TEXTURE_2D,
2577 0, // level
2578 GL_RGBA,
[email protected]c007aa02010-09-02 22:22:402579 0, 0, // x, y
[email protected]a3a93e7b2010-08-28 00:48:562580 width,
2581 height,
2582 0); // border
2583 }
2584}
2585
[email protected]43ecf372010-11-16 19:19:392586void GLES2DecoderImpl::DoResizeCHROMIUM(GLuint width, GLuint height) {
[email protected]7ff86b92010-11-25 17:50:002587#if defined(OS_LINUX)
2588 // Make sure that we are done drawing to the back buffer before resizing.
2589 glFinish();
2590#endif
2591 if (resize_callback_.get()) {
2592 gfx::Size size(width, height);
2593 resize_callback_->Run(size);
2594 }
[email protected]43ecf372010-11-16 19:19:392595}
2596
[email protected]96449d2c2009-11-25 00:01:322597const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2598 if (command_id > kStartPoint && command_id < kNumCommands) {
2599 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2600 }
2601 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2602}
2603
2604// Decode command with its arguments, and call the corresponding GL function.
2605// Note: args is a pointer to the command buffer. As such, it could be changed
2606// by a (malicious) client at any time, so if validation has to happen, it
2607// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142608error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322609 unsigned int command,
2610 unsigned int arg_count,
2611 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142612 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192613 if (debug()) {
2614 // TODO(gman): Change output to something useful for NaCl.
[email protected]d366c482010-10-20 00:11:272615 DVLOG(1) << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192616 }
[email protected]96449d2c2009-11-25 00:01:322617 unsigned int command_index = command - kStartPoint - 1;
2618 if (command_index < arraysize(g_command_info)) {
2619 const CommandInfo& info = g_command_info[command_index];
2620 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2621 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2622 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192623 uint32 immediate_data_size =
2624 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322625 switch (command) {
2626 #define GLES2_CMD_OP(name) \
2627 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192628 result = Handle ## name( \
2629 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322630 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192631 break; \
[email protected]96449d2c2009-11-25 00:01:322632
2633 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322634 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382635 }
2636 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302637 GLenum error;
2638 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382639 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292640 SetGLError(error, NULL);
[email protected]d366c482010-10-20 00:11:272641 DVLOG(1) << "GL ERROR: " << error << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192642 }
[email protected]96449d2c2009-11-25 00:01:322643 }
2644 } else {
[email protected]f7a64ee2010-02-01 22:24:142645 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322646 }
[email protected]b9849abf2009-11-25 19:13:192647 } else {
2648 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322649 }
[email protected]a3a93e7b2010-08-28 00:48:562650 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
2651 result = current_decoder_error_;
2652 current_decoder_error_ = error::kNoError;
2653 }
[email protected]b9849abf2009-11-25 19:13:192654 return result;
[email protected]96449d2c2009-11-25 00:01:322655}
2656
[email protected]ae51d192010-04-27 00:48:032657void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2658 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502659}
2660
[email protected]ae51d192010-04-27 00:48:032661bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2662 if (GetProgramInfo(client_id)) {
2663 return false;
2664 }
[email protected]96449d2c2009-11-25 00:01:322665 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032666 if (service_id != 0) {
2667 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322668 }
[email protected]ae51d192010-04-27 00:48:032669 return true;
[email protected]96449d2c2009-11-25 00:01:322670}
2671
[email protected]ae51d192010-04-27 00:48:032672bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2673 if (GetShaderInfo(client_id)) {
2674 return false;
[email protected]96449d2c2009-11-25 00:01:322675 }
[email protected]ae51d192010-04-27 00:48:032676 GLuint service_id = glCreateShader(type);
2677 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382678 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032679 }
2680 return true;
[email protected]96449d2c2009-11-25 00:01:322681}
2682
[email protected]3916c97e2010-02-25 03:20:502683void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452684 GLuint texture_index = texture_unit - GL_TEXTURE0;
2685 if (texture_index > group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292686 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502687 return;
2688 }
[email protected]36cef8ce2010-03-16 07:34:452689 active_texture_unit_ = texture_index;
2690 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502691}
2692
[email protected]051b1372010-04-12 02:42:082693void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502694 BufferManager::BufferInfo* 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 = GetBufferInfo(client_id);
2698 if (!info) {
2699 // It's a new id so make a buffer info for it.
2700 glGenBuffersARB(1, &service_id);
2701 CreateBufferInfo(client_id, service_id);
2702 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102703 IdAllocator* id_allocator =
2704 group_->GetIdAllocator(id_namespaces::kBuffers);
2705 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032706 }
[email protected]051b1372010-04-12 02:42:082707 }
[email protected]ae51d192010-04-27 00:48:032708 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102709 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292710 SetGLError(GL_INVALID_OPERATION,
2711 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472712 return;
2713 }
[email protected]ae51d192010-04-27 00:48:032714 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472715 }
[email protected]96449d2c2009-11-25 00:01:322716 switch (target) {
2717 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502718 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322719 break;
2720 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502721 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322722 break;
2723 default:
[email protected]a93bb842010-02-16 23:03:472724 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322725 break;
2726 }
[email protected]051b1372010-04-12 02:42:082727 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322728}
2729
[email protected]051b1372010-04-12 02:42:082730void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2731 FramebufferManager::FramebufferInfo* info = NULL;
2732 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032733 if (client_id != 0) {
2734 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082735 if (!info) {
[email protected]ae51d192010-04-27 00:48:032736 // It's a new id so make a framebuffer info for it.
2737 glGenFramebuffersEXT(1, &service_id);
2738 CreateFramebufferInfo(client_id, service_id);
2739 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102740 IdAllocator* id_allocator =
2741 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2742 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032743 } else {
2744 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082745 }
[email protected]06c8b082011-01-05 18:00:362746 info->MarkAsValid();
[email protected]eff9a222010-12-21 21:48:562747 } else {
2748 service_id = context_->GetBackingFrameBufferObject();
[email protected]051b1372010-04-12 02:42:082749 }
[email protected]8e3e0662010-08-23 18:46:302750
2751 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
2752 bound_draw_framebuffer_ = info;
2753 }
2754 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
2755 bound_read_framebuffer_ = info;
2756 }
[email protected]6217d392010-03-25 22:08:352757
2758 // When rendering to an offscreen frame buffer, instead of unbinding from
2759 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:082760 if (info == NULL && offscreen_target_frame_buffer_.get())
2761 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:352762
[email protected]051b1372010-04-12 02:42:082763 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562764}
2765
[email protected]051b1372010-04-12 02:42:082766void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2767 RenderbufferManager::RenderbufferInfo* info = NULL;
2768 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032769 if (client_id != 0) {
2770 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082771 if (!info) {
[email protected]ae51d192010-04-27 00:48:032772 // It's a new id so make a renderbuffer info for it.
2773 glGenRenderbuffersEXT(1, &service_id);
2774 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102775 info = GetRenderbufferInfo(client_id);
2776 IdAllocator* id_allocator =
2777 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2778 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032779 } else {
2780 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082781 }
[email protected]06c8b082011-01-05 18:00:362782 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:082783 }
2784 bound_renderbuffer_ = info;
2785 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562786}
2787
[email protected]051b1372010-04-12 02:42:082788void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032789 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082790 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032791 if (client_id != 0) {
2792 info = GetTextureInfo(client_id);
2793 if (!info) {
2794 // It's a new id so make a texture info for it.
2795 glGenTextures(1, &service_id);
2796 CreateTextureInfo(client_id, service_id);
2797 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:102798 IdAllocator* id_allocator =
2799 group_->GetIdAllocator(id_namespaces::kTextures);
2800 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032801 }
2802 } else {
2803 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082804 }
[email protected]ae51d192010-04-27 00:48:032805
[email protected]1958e0e2010-04-22 05:17:152806 // Check the texture exists
2807 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032808 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292809 SetGLError(GL_INVALID_OPERATION,
2810 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152811 return;
2812 }
2813 if (info->target() == 0) {
2814 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472815 }
[email protected]ae51d192010-04-27 00:48:032816 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502817 TextureUnit& unit = texture_units_[active_texture_unit_];
2818 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472819 switch (target) {
2820 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502821 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472822 break;
2823 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502824 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472825 break;
2826 default:
2827 NOTREACHED(); // Validation should prevent us getting here.
2828 break;
2829 }
2830}
2831
[email protected]07f54fcc2009-12-22 02:46:302832void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082833 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:122834 if (index != 0 ||
2835 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:242836 glDisableVertexAttribArray(index);
2837 }
[email protected]07f54fcc2009-12-22 02:46:302838 } else {
[email protected]8eee29c2010-04-29 03:38:292839 SetGLError(GL_INVALID_VALUE,
2840 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302841 }
2842}
2843
2844void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082845 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302846 glEnableVertexAttribArray(index);
2847 } else {
[email protected]8eee29c2010-04-29 03:38:292848 SetGLError(GL_INVALID_VALUE,
2849 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302850 }
2851}
2852
[email protected]a93bb842010-02-16 23:03:472853void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502854 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]915a59a12010-09-30 21:29:112855 if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) {
[email protected]8eee29c2010-04-29 03:38:292856 SetGLError(GL_INVALID_OPERATION,
2857 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472858 return;
2859 }
[email protected]59f3ca02011-03-26 22:24:192860 // Workaround for Mac driver bug. In the large scheme of things setting
2861 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
2862 // hit so there's probably no need to make this conditional.
2863 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
[email protected]a93bb842010-02-16 23:03:472864 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:192865 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:472866}
2867
[email protected]b273e432010-04-12 17:23:582868bool GLES2DecoderImpl::GetHelper(
2869 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582870 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152871 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2872 switch (pname) {
[email protected]b273e432010-04-12 17:23:582873 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2874 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102875 if (params) {
[email protected]5094b0f2010-11-09 19:45:242876 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:102877 }
[email protected]b273e432010-04-12 17:23:582878 return true;
2879 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2880 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102881 if (params) {
[email protected]5094b0f2010-11-09 19:45:242882 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:102883 }
[email protected]b273e432010-04-12 17:23:582884 return true;
2885 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2886 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102887 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482888 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102889 }
[email protected]b273e432010-04-12 17:23:582890 return true;
2891 case GL_MAX_VARYING_VECTORS:
2892 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102893 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482894 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102895 }
[email protected]b273e432010-04-12 17:23:582896 return true;
2897 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2898 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102899 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482900 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102901 }
[email protected]b273e432010-04-12 17:23:582902 return true;
[email protected]5094b0f2010-11-09 19:45:242903 case GL_MAX_VIEWPORT_DIMS:
2904 if (offscreen_target_frame_buffer_.get()) {
2905 *num_written = 2;
2906 if (params) {
2907 params[0] = renderbuffer_manager()->max_renderbuffer_size();
2908 params[1] = renderbuffer_manager()->max_renderbuffer_size();
2909 }
2910 return true;
2911 }
[email protected]b9363b22010-06-09 22:06:152912 }
2913 }
2914 switch (pname) {
[email protected]656dcaad2010-05-07 17:18:372915 case GL_COMPRESSED_TEXTURE_FORMATS:
2916 *num_written = 0;
2917 // We don't support compressed textures.
2918 return true;
[email protected]b273e432010-04-12 17:23:582919 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
2920 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102921 if (params) {
2922 *params = 0; // We don't support compressed textures.
2923 }
[email protected]b273e432010-04-12 17:23:582924 return true;
2925 case GL_NUM_SHADER_BINARY_FORMATS:
2926 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102927 if (params) {
2928 *params = 0; // We don't support binary shader formats.
2929 }
[email protected]b273e432010-04-12 17:23:582930 return true;
2931 case GL_SHADER_BINARY_FORMATS:
2932 *num_written = 0;
2933 return true; // We don't support binary shader format.s
2934 case GL_SHADER_COMPILER:
2935 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102936 if (params) {
2937 *params = GL_TRUE;
2938 }
[email protected]b273e432010-04-12 17:23:582939 return true;
[email protected]6b8cf1a2010-05-06 16:13:582940 case GL_ARRAY_BUFFER_BINDING:
2941 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102942 if (params) {
2943 if (bound_array_buffer_) {
2944 GLuint client_id = 0;
2945 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
2946 &client_id);
2947 *params = client_id;
2948 } else {
2949 *params = 0;
2950 }
[email protected]6b8cf1a2010-05-06 16:13:582951 }
2952 return true;
2953 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
2954 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102955 if (params) {
2956 if (bound_element_array_buffer_) {
2957 GLuint client_id = 0;
2958 buffer_manager()->GetClientId(
2959 bound_element_array_buffer_->service_id(),
2960 &client_id);
2961 *params = client_id;
2962 } else {
2963 *params = 0;
2964 }
[email protected]6b8cf1a2010-05-06 16:13:582965 }
2966 return true;
2967 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:302968 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:582969 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102970 if (params) {
[email protected]8e3e0662010-08-23 18:46:302971 if (bound_draw_framebuffer_) {
[email protected]4e8a5b122010-05-08 22:00:102972 GLuint client_id = 0;
2973 framebuffer_manager()->GetClientId(
[email protected]8e3e0662010-08-23 18:46:302974 bound_draw_framebuffer_->service_id(), &client_id);
2975 *params = client_id;
2976 } else {
2977 *params = 0;
2978 }
2979 }
2980 return true;
2981 case GL_READ_FRAMEBUFFER_BINDING:
2982 *num_written = 1;
2983 if (params) {
2984 if (bound_read_framebuffer_) {
2985 GLuint client_id = 0;
2986 framebuffer_manager()->GetClientId(
2987 bound_read_framebuffer_->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:102988 *params = client_id;
2989 } else {
2990 *params = 0;
2991 }
[email protected]6b8cf1a2010-05-06 16:13:582992 }
2993 return true;
2994 case GL_RENDERBUFFER_BINDING:
2995 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102996 if (params) {
2997 if (bound_renderbuffer_) {
2998 GLuint client_id = 0;
2999 renderbuffer_manager()->GetClientId(
3000 bound_renderbuffer_->service_id(), &client_id);
3001 *params = client_id;
3002 } else {
3003 *params = 0;
3004 }
[email protected]6b8cf1a2010-05-06 16:13:583005 }
3006 return true;
3007 case GL_CURRENT_PROGRAM:
3008 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103009 if (params) {
3010 if (current_program_) {
3011 GLuint client_id = 0;
3012 program_manager()->GetClientId(
3013 current_program_->service_id(), &client_id);
3014 *params = client_id;
3015 } else {
3016 *params = 0;
3017 }
[email protected]6b8cf1a2010-05-06 16:13:583018 }
3019 return true;
[email protected]4e8a5b122010-05-08 22:00:103020 case GL_TEXTURE_BINDING_2D:
3021 *num_written = 1;
3022 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583023 TextureUnit& unit = texture_units_[active_texture_unit_];
3024 if (unit.bound_texture_2d) {
3025 GLuint client_id = 0;
3026 texture_manager()->GetClientId(
3027 unit.bound_texture_2d->service_id(), &client_id);
3028 *params = client_id;
3029 } else {
3030 *params = 0;
3031 }
[email protected]6b8cf1a2010-05-06 16:13:583032 }
[email protected]4e8a5b122010-05-08 22:00:103033 return true;
3034 case GL_TEXTURE_BINDING_CUBE_MAP:
3035 *num_written = 1;
3036 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583037 TextureUnit& unit = texture_units_[active_texture_unit_];
3038 if (unit.bound_texture_cube_map) {
3039 GLuint client_id = 0;
3040 texture_manager()->GetClientId(
3041 unit.bound_texture_cube_map->service_id(), &client_id);
3042 *params = client_id;
3043 } else {
3044 *params = 0;
3045 }
[email protected]6b8cf1a2010-05-06 16:13:583046 }
[email protected]4e8a5b122010-05-08 22:00:103047 return true;
[email protected]b273e432010-04-12 17:23:583048 default:
[email protected]4e8a5b122010-05-08 22:00:103049 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533050 return false;
[email protected]b273e432010-04-12 17:23:583051 }
3052}
3053
[email protected]4e8a5b122010-05-08 22:00:103054bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3055 GLenum pname, GLsizei* num_values) {
3056 return GetHelper(pname, NULL, num_values);
3057}
3058
[email protected]b273e432010-04-12 17:23:583059void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3060 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103061 GLsizei num_written = 0;
3062 if (GetHelper(pname, NULL, &num_written)) {
3063 scoped_array<GLint> values(new GLint[num_written]);
3064 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583065 for (GLsizei ii = 0; ii < num_written; ++ii) {
3066 params[ii] = static_cast<GLboolean>(values[ii]);
3067 }
3068 } else {
3069 glGetBooleanv(pname, params);
3070 }
3071}
3072
3073void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3074 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103075 GLsizei num_written = 0;
3076 if (GetHelper(pname, NULL, &num_written)) {
3077 scoped_array<GLint> values(new GLint[num_written]);
3078 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583079 for (GLsizei ii = 0; ii < num_written; ++ii) {
3080 params[ii] = static_cast<GLfloat>(values[ii]);
3081 }
3082 } else {
3083 glGetFloatv(pname, params);
3084 }
3085}
3086
3087void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3088 DCHECK(params);
3089 GLsizei num_written;
3090 if (!GetHelper(pname, params, &num_written)) {
3091 glGetIntegerv(pname, params);
3092 }
3093}
3094
[email protected]a0c3e972010-04-21 00:49:133095void GLES2DecoderImpl::DoGetProgramiv(
3096 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583097 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3098 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133099 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133100 return;
3101 }
3102 info->GetProgramiv(pname, params);
3103}
3104
[email protected]558847a2010-03-24 07:02:543105error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3106 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:583107 GLuint program = static_cast<GLuint>(c.program);
3108 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3109 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033110 if (!info) {
[email protected]558847a2010-03-24 07:02:543111 return error::kNoError;
3112 }
3113 GLuint index = static_cast<GLuint>(c.index);
3114 uint32 name_size = c.data_size;
3115 const char* name = GetSharedMemoryAs<const char*>(
3116 c.name_shm_id, c.name_shm_offset, name_size);
3117 if (name == NULL) {
3118 return error::kOutOfBounds;
3119 }
3120 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033121 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543122 return error::kNoError;
3123}
3124
3125error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3126 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583127 GLuint program = static_cast<GLuint>(c.program);
3128 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3129 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033130 if (!info) {
[email protected]558847a2010-03-24 07:02:543131 return error::kNoError;
3132 }
3133 GLuint index = static_cast<GLuint>(c.index);
3134 uint32 name_size = c.data_size;
3135 const char* name = GetImmediateDataAs<const char*>(
3136 c, name_size, immediate_data_size);
3137 if (name == NULL) {
3138 return error::kOutOfBounds;
3139 }
3140 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033141 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543142 return error::kNoError;
3143}
3144
3145error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3146 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583147 GLuint program = static_cast<GLuint>(c.program);
3148 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3149 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033150 if (!info) {
[email protected]558847a2010-03-24 07:02:543151 return error::kNoError;
3152 }
3153 GLuint index = static_cast<GLuint>(c.index);
3154 Bucket* bucket = GetBucket(c.name_bucket_id);
3155 if (!bucket || bucket->size() == 0) {
3156 return error::kInvalidArguments;
3157 }
3158 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183159 if (!bucket->GetAsString(&name_str)) {
3160 return error::kInvalidArguments;
3161 }
[email protected]ae51d192010-04-27 00:48:033162 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543163 return error::kNoError;
3164}
3165
[email protected]f7a64ee2010-02-01 22:24:143166error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463167 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033168 GLuint client_id = c.shader;
3169 if (client_id) {
3170 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3171 if (info) {
[email protected]ca488e12010-12-13 20:06:143172 if (!info->IsDeleted()) {
3173 glDeleteShader(info->service_id());
3174 shader_manager()->MarkAsDeleted(info);
3175 }
[email protected]ae51d192010-04-27 00:48:033176 } else {
[email protected]8eee29c2010-04-29 03:38:293177 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033178 }
[email protected]96449d2c2009-11-25 00:01:323179 }
[email protected]f7a64ee2010-02-01 22:24:143180 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323181}
3182
[email protected]f7a64ee2010-02-01 22:24:143183error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463184 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033185 GLuint client_id = c.program;
3186 if (client_id) {
3187 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3188 if (info) {
[email protected]ca488e12010-12-13 20:06:143189 if (!info->IsDeleted()) {
3190 glDeleteProgram(info->service_id());
3191 program_manager()->MarkAsDeleted(shader_manager(), info);
3192 }
[email protected]ae51d192010-04-27 00:48:033193 } else {
[email protected]8eee29c2010-04-29 03:38:293194 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033195 }
[email protected]96449d2c2009-11-25 00:01:323196 }
[email protected]f7a64ee2010-02-01 22:24:143197 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323198}
3199
[email protected]269200b12010-11-18 22:53:063200void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103201 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3202 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3203 for (GLsizei ii = 0; ii < n; ++ii) {
3204 id_allocator->FreeID(ids[ii]);
3205 }
3206}
3207
[email protected]269200b12010-11-18 22:53:063208error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3209 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103210 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3211 GLsizei n = static_cast<GLsizei>(c.n);
3212 uint32 data_size;
3213 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3214 return error::kOutOfBounds;
3215 }
3216 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3217 c.ids_shm_id, c.ids_shm_offset, data_size);
3218 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063219 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103220 return error::kNoError;
3221 }
3222 if (ids == NULL) {
3223 return error::kOutOfBounds;
3224 }
[email protected]269200b12010-11-18 22:53:063225 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103226 return error::kNoError;
3227}
3228
[email protected]269200b12010-11-18 22:53:063229void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103230 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
3231 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3232 if (id_offset == 0) {
3233 for (GLsizei ii = 0; ii < n; ++ii) {
3234 ids[ii] = id_allocator->AllocateID();
3235 }
3236 } else {
3237 for (GLsizei ii = 0; ii < n; ++ii) {
3238 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3239 id_offset = ids[ii] + 1;
3240 }
3241 }
3242}
3243
[email protected]269200b12010-11-18 22:53:063244error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3245 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103246 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3247 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3248 GLsizei n = static_cast<GLsizei>(c.n);
3249 uint32 data_size;
3250 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3251 return error::kOutOfBounds;
3252 }
3253 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3254 c.ids_shm_id, c.ids_shm_offset, data_size);
3255 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063256 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103257 return error::kNoError;
3258 }
3259 if (ids == NULL) {
3260 return error::kOutOfBounds;
3261 }
[email protected]269200b12010-11-18 22:53:063262 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103263 return error::kNoError;
3264}
3265
[email protected]269200b12010-11-18 22:53:063266void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103267 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3268 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3269 for (GLsizei ii = 0; ii < n; ++ii) {
3270 if (!id_allocator->MarkAsUsed(ids[ii])) {
3271 for (GLsizei jj = 0; jj < ii; ++jj) {
3272 id_allocator->FreeID(ids[jj]);
3273 }
3274 SetGLError(
3275 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063276 "RegisterSharedIdsCHROMIUM: attempt to register "
3277 "id that already exists");
[email protected]066849e32010-05-03 19:14:103278 return;
3279 }
3280 }
3281}
3282
[email protected]269200b12010-11-18 22:53:063283error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3284 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103285 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3286 GLsizei n = static_cast<GLsizei>(c.n);
3287 uint32 data_size;
3288 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3289 return error::kOutOfBounds;
3290 }
3291 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3292 c.ids_shm_id, c.ids_shm_offset, data_size);
3293 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063294 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103295 return error::kNoError;
3296 }
3297 if (ids == NULL) {
3298 return error::kOutOfBounds;
3299 }
[email protected]269200b12010-11-18 22:53:063300 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103301 return error::kNoError;
3302}
3303
[email protected]3a03a8f2011-03-19 00:51:273304void GLES2DecoderImpl::DoClear(GLbitfield mask) {
3305 if (CheckFramebufferComplete("glClear")) {
3306 glClear(mask);
3307 }
3308}
3309
[email protected]07f54fcc2009-12-22 02:46:303310void GLES2DecoderImpl::DoDrawArrays(
3311 GLenum mode, GLint first, GLsizei count) {
[email protected]3a03a8f2011-03-19 00:51:273312 if (!CheckFramebufferComplete("glDrawArrays")) {
3313 return;
3314 }
[email protected]d81e8c52010-06-07 17:58:323315 // We have to check this here because the prototype for glDrawArrays
3316 // is GLint not GLsizei.
3317 if (first < 0) {
[email protected]7601c3f2010-12-22 00:41:203318 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
[email protected]d81e8c52010-06-07 17:58:323319 return;
3320 }
[email protected]6c788fb72010-08-26 02:16:313321
3322 if (count == 0) {
3323 return;
3324 }
3325
[email protected]8fbedc02010-11-18 18:43:403326 GLuint max_vertex_accessed = first + count - 1;
3327 if (IsDrawValid(max_vertex_accessed)) {
3328 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
3329 bool simulated_fixed_attribs = false;
3330 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
3331 bool textures_set = SetBlackTextureForNonRenderableTextures();
3332 glDrawArrays(mode, first, count);
3333 if (textures_set) {
3334 RestoreStateForNonRenderableTextures();
3335 }
3336 if (simulated_fixed_attribs) {
3337 RestoreStateForSimulatedFixedAttribs();
3338 }
[email protected]3916c97e2010-02-25 03:20:503339 }
[email protected]b1122982010-05-17 23:04:243340 if (simulated_attrib_0) {
3341 RestoreStateForSimulatedAttrib0();
3342 }
[email protected]07f54fcc2009-12-22 02:46:303343 }
3344}
3345
[email protected]36cef8ce2010-03-16 07:34:453346void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3347 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033348 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303349 FramebufferManager::FramebufferInfo* framebuffer_info =
3350 GetFramebufferInfoForTarget(target);
3351 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293352 SetGLError(GL_INVALID_OPERATION,
3353 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453354 return;
3355 }
[email protected]ae51d192010-04-27 00:48:033356 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283357 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033358 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283359 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033360 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293361 SetGLError(GL_INVALID_OPERATION,
3362 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033363 return;
3364 }
3365 service_id = info->service_id();
3366 }
[email protected]9edc6b22010-12-23 02:00:263367 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033368 glFramebufferRenderbufferEXT(
3369 target, attachment, renderbuffertarget, service_id);
[email protected]9edc6b22010-12-23 02:00:263370 GLenum error = glGetError();
3371 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303372 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]9edc6b22010-12-23 02:00:263373 if (service_id == 0 ||
3374 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3375 if (info) {
3376 ClearUnclearedRenderbuffers(target, framebuffer_info);
3377 }
[email protected]3a2e7c7b2010-08-06 01:12:283378 }
3379 }
3380}
3381
3382void GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
3383 switch (cap) {
3384 case GL_SCISSOR_TEST:
3385 enable_scissor_test_ = enabled;
3386 break;
3387 default:
3388 break;
3389 }
3390}
3391
3392void GLES2DecoderImpl::DoDisable(GLenum cap) {
3393 SetCapabilityState(cap, false);
3394 glDisable(cap);
3395}
3396
3397void GLES2DecoderImpl::DoEnable(GLenum cap) {
3398 SetCapabilityState(cap, true);
3399 glEnable(cap);
3400}
3401
3402void GLES2DecoderImpl::DoClearColor(
3403 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
3404 clear_red_ = red;
3405 clear_green_ = green;
3406 clear_blue_ = blue;
3407 clear_alpha_ = alpha;
3408 glClearColor(red, green, blue, alpha);
3409}
3410
3411void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
3412 clear_depth_ = depth;
3413 glClearDepth(depth);
3414}
3415
3416void GLES2DecoderImpl::DoClearStencil(GLint s) {
3417 clear_stencil_ = s;
3418 glClearStencil(s);
3419}
3420
3421void GLES2DecoderImpl::DoColorMask(
3422 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
3423 mask_red_ = red;
3424 mask_green_ = green;
3425 mask_blue_ = blue;
3426 mask_alpha_ = alpha;
3427 glColorMask(red, green, blue, alpha);
3428}
3429
3430void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
3431 mask_depth_ = depth;
3432 glDepthMask(depth);
3433}
3434
3435void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
3436 mask_stencil_front_ = mask;
3437 mask_stencil_back_ = mask;
3438 glStencilMask(mask);
3439}
3440
3441void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
3442 if (face == GL_FRONT) {
3443 mask_stencil_front_ = mask;
3444 } else {
3445 mask_stencil_back_ = mask;
3446 }
3447 glStencilMaskSeparate(face, mask);
3448}
3449
3450// NOTE: There's an assumption here that Texture attachments
3451// are cleared because they are textures so we only need to clear
3452// the renderbuffers.
3453void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
[email protected]8e3e0662010-08-23 18:46:303454 GLenum target, FramebufferManager::FramebufferInfo* info) {
3455 if (target == GL_READ_FRAMEBUFFER_EXT) {
3456 // TODO(gman): bind this to the DRAW point, clear then bind back to READ
3457 }
[email protected]3a2e7c7b2010-08-06 01:12:283458 GLbitfield clear_bits = 0;
3459 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
3460 glClearColor(0, 0, 0, 0);
3461 glColorMask(true, true, true, true);
3462 clear_bits |= GL_COLOR_BUFFER_BIT;
3463 }
3464
3465 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
3466 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3467 glClearStencil(0);
3468 glStencilMask(-1);
3469 clear_bits |= GL_STENCIL_BUFFER_BIT;
3470 }
3471
3472 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
3473 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3474 glClearDepth(1.0f);
3475 glDepthMask(true);
3476 clear_bits |= GL_DEPTH_BUFFER_BIT;
3477 }
3478
3479 glDisable(GL_SCISSOR_TEST);
3480 glClear(clear_bits);
3481
3482 info->MarkAttachedRenderbuffersAsCleared();
3483
[email protected]c007aa02010-09-02 22:22:403484 RestoreClearState();
3485
3486 if (target == GL_READ_FRAMEBUFFER_EXT) {
3487 // TODO(gman): rebind draw.
3488 }
3489}
3490
3491void GLES2DecoderImpl::RestoreClearState() {
[email protected]3a2e7c7b2010-08-06 01:12:283492 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
3493 glColorMask(mask_red_, mask_green_, mask_blue_, mask_alpha_);
3494 glClearStencil(clear_stencil_);
3495 glStencilMaskSeparate(GL_FRONT, mask_stencil_front_);
3496 glStencilMaskSeparate(GL_BACK, mask_stencil_back_);
3497 glClearDepth(clear_depth_);
3498 glDepthMask(mask_depth_);
3499 if (enable_scissor_test_) {
3500 glEnable(GL_SCISSOR_TEST);
3501 }
[email protected]36cef8ce2010-03-16 07:34:453502}
3503
3504GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]8e3e0662010-08-23 18:46:303505 FramebufferManager::FramebufferInfo* info =
3506 GetFramebufferInfoForTarget(target);
3507 if (!info) {
[email protected]36cef8ce2010-03-16 07:34:453508 return GL_FRAMEBUFFER_COMPLETE;
3509 }
3510 return glCheckFramebufferStatusEXT(target);
3511}
3512
3513void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033514 GLenum target, GLenum attachment, GLenum textarget,
3515 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303516 FramebufferManager::FramebufferInfo* framebuffer_info =
3517 GetFramebufferInfoForTarget(target);
3518 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293519 SetGLError(GL_INVALID_OPERATION,
3520 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453521 return;
3522 }
[email protected]ae51d192010-04-27 00:48:033523 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283524 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033525 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283526 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033527 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293528 SetGLError(GL_INVALID_OPERATION,
3529 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033530 return;
3531 }
3532 service_id = info->service_id();
3533 }
[email protected]9edc6b22010-12-23 02:00:263534 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033535 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]9edc6b22010-12-23 02:00:263536 GLenum error = glGetError();
3537 if (error == GL_NO_ERROR) {
3538 framebuffer_info->AttachTexture(attachment, info, textarget, level);
3539 if (service_id != 0 &&
3540 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3541 ClearUnclearedRenderbuffers(target, framebuffer_info);
3542 }
[email protected]3a2e7c7b2010-08-06 01:12:283543 }
[email protected]36cef8ce2010-03-16 07:34:453544}
3545
3546void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3547 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303548 FramebufferManager::FramebufferInfo* framebuffer_info =
3549 GetFramebufferInfoForTarget(target);
3550 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293551 SetGLError(GL_INVALID_OPERATION,
3552 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453553 return;
3554 }
3555 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573556 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3557 GLint type = 0;
3558 GLuint client_id = 0;
3559 glGetFramebufferAttachmentParameterivEXT(
3560 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3561 switch (type) {
3562 case GL_RENDERBUFFER: {
3563 renderbuffer_manager()->GetClientId(*params, &client_id);
3564 break;
3565 }
3566 case GL_TEXTURE: {
3567 texture_manager()->GetClientId(*params, &client_id);
3568 break;
3569 }
3570 default:
3571 break;
3572 }
3573 *params = client_id;
3574 }
[email protected]36cef8ce2010-03-16 07:34:453575}
3576
3577void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
3578 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:083579 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293580 SetGLError(GL_INVALID_OPERATION,
3581 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453582 return;
3583 }
[email protected]3a03a8f2011-03-19 00:51:273584 switch (pname) {
3585 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]b71f52c2010-06-18 22:20:203586 *params = bound_renderbuffer_->internal_format();
[email protected]3a03a8f2011-03-19 00:51:273587 break;
3588 case GL_RENDERBUFFER_WIDTH:
3589 *params = bound_renderbuffer_->width();
3590 break;
3591 case GL_RENDERBUFFER_HEIGHT:
3592 *params = bound_renderbuffer_->height();
3593 break;
3594 default:
3595 glGetRenderbufferParameterivEXT(target, pname, params);
3596 break;
[email protected]b71f52c2010-06-18 22:20:203597 }
[email protected]36cef8ce2010-03-16 07:34:453598}
3599
[email protected]8e3e0662010-08-23 18:46:303600void GLES2DecoderImpl::DoBlitFramebufferEXT(
3601 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3602 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3603 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:393604 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303605 SetGLError(GL_INVALID_OPERATION,
3606 "glBlitFramebufferEXT: function not available");
3607 }
[email protected]5094b0f2010-11-09 19:45:243608 if (IsAngle()) {
3609 glBlitFramebufferANGLE(
3610 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3611 } else {
3612 glBlitFramebufferEXT(
3613 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3614 }
[email protected]8e3e0662010-08-23 18:46:303615}
3616
3617void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
3618 GLenum target, GLsizei samples, GLenum internalformat,
3619 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:393620 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303621 SetGLError(GL_INVALID_OPERATION,
3622 "glRenderbufferStorageMultisampleEXT: function not available");
3623 return;
3624 }
[email protected]8e3e0662010-08-23 18:46:303625
[email protected]9edc6b22010-12-23 02:00:263626 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:303627 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263628 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:303629 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263630 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:303631 break;
3632 case GL_RGBA4:
3633 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263634 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:303635 break;
3636 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263637 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:303638 break;
3639 }
3640 }
3641
[email protected]9edc6b22010-12-23 02:00:263642 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:083643 if (IsAngle()) {
3644 glRenderbufferStorageMultisampleANGLE(
3645 target, samples, impl_format, width, height);
3646 } else {
3647 glRenderbufferStorageMultisampleEXT(
3648 target, samples, impl_format, width, height);
3649 }
[email protected]9edc6b22010-12-23 02:00:263650 GLenum error = glGetError();
3651 if (error == GL_NO_ERROR) {
3652 bound_renderbuffer_->SetInfo(samples, internalformat, width, height);
3653 }
[email protected]8e3e0662010-08-23 18:46:303654}
3655
[email protected]36cef8ce2010-03-16 07:34:453656void GLES2DecoderImpl::DoRenderbufferStorage(
3657 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:083658 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293659 SetGLError(GL_INVALID_OPERATION,
3660 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453661 return;
3662 }
[email protected]876f6fee2010-08-02 23:10:323663
[email protected]9edc6b22010-12-23 02:00:263664 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:323665 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263666 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:323667 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263668 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:323669 break;
3670 case GL_RGBA4:
3671 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263672 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:323673 break;
3674 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263675 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:323676 break;
3677 }
[email protected]b71f52c2010-06-18 22:20:203678 }
[email protected]876f6fee2010-08-02 23:10:323679
[email protected]9edc6b22010-12-23 02:00:263680 CopyRealGLErrorsToWrapper();
3681 glRenderbufferStorageEXT(target, impl_format, width, height);
3682 GLenum error = glGetError();
3683 if (error == GL_NO_ERROR) {
3684 bound_renderbuffer_->SetInfo(0, internalformat, width, height);
3685 }
[email protected]36cef8ce2010-03-16 07:34:453686}
3687
[email protected]07f54fcc2009-12-22 02:46:303688void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]6b8cf1a2010-05-06 16:13:583689 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3690 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:473691 if (!info) {
[email protected]a93bb842010-02-16 23:03:473692 return;
3693 }
[email protected]05afda12011-01-20 00:17:343694
3695 info->ClearLinkStatus();
[email protected]d81e8c52010-06-07 17:58:323696 if (!info->CanLink()) {
[email protected]d81e8c52010-06-07 17:58:323697 return;
3698 }
[email protected]05afda12011-01-20 00:17:343699
[email protected]ae51d192010-04-27 00:48:033700 glLinkProgram(info->service_id());
[email protected]6b8cf1a2010-05-06 16:13:583701 GLint success = 0;
3702 glGetProgramiv(info->service_id(), GL_LINK_STATUS, &success);
3703 if (success) {
[email protected]a93bb842010-02-16 23:03:473704 info->Update();
[email protected]07f54fcc2009-12-22 02:46:303705 }
3706};
3707
[email protected]3916c97e2010-02-25 03:20:503708void GLES2DecoderImpl::DoTexParameterf(
3709 GLenum target, GLenum pname, GLfloat param) {
3710 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:303711 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293712 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]07f54fcc2009-12-22 02:46:303713 } else {
[email protected]915a59a12010-09-30 21:29:113714 texture_manager()->SetParameter(
3715 feature_info_, info, pname, static_cast<GLint>(param));
[email protected]3916c97e2010-02-25 03:20:503716 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:303717 }
3718}
3719
[email protected]3916c97e2010-02-25 03:20:503720void GLES2DecoderImpl::DoTexParameteri(
3721 GLenum target, GLenum pname, GLint param) {
3722 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3723 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293724 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503725 } else {
[email protected]915a59a12010-09-30 21:29:113726 texture_manager()->SetParameter(feature_info_, info, pname, param);
[email protected]3916c97e2010-02-25 03:20:503727 glTexParameteri(target, pname, param);
3728 }
3729}
3730
3731void GLES2DecoderImpl::DoTexParameterfv(
3732 GLenum target, GLenum pname, const GLfloat* params) {
3733 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3734 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293735 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503736 } else {
[email protected]ef526492010-06-02 23:12:253737 texture_manager()->SetParameter(
[email protected]915a59a12010-09-30 21:29:113738 feature_info_, info, pname, *reinterpret_cast<const GLint*>(params));
[email protected]3916c97e2010-02-25 03:20:503739 glTexParameterfv(target, pname, params);
3740 }
3741}
3742
3743void GLES2DecoderImpl::DoTexParameteriv(
3744 GLenum target, GLenum pname, const GLint* params) {
3745 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3746 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293747 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503748 } else {
[email protected]915a59a12010-09-30 21:29:113749 texture_manager()->SetParameter(feature_info_, info, pname, *params);
[email protected]3916c97e2010-02-25 03:20:503750 glTexParameteriv(target, pname, params);
3751 }
3752}
3753
[email protected]939e7362010-05-13 20:49:103754bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:143755 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:103756 // The program does not exist.
3757 SetGLError(GL_INVALID_OPERATION,
3758 (std::string(function_name) + ": no program in use").c_str());
3759 return false;
3760 }
[email protected]ca488e12010-12-13 20:06:143761 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:103762 SetGLError(GL_INVALID_OPERATION,
3763 (std::string(function_name) + ": program not linked").c_str());
3764 return false;
3765 }
3766 return true;
3767}
3768
3769bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
3770 GLint location, const char* function_name) {
3771 if (!CheckCurrentProgram(function_name)) {
3772 return false;
3773 }
3774 return location != -1;
3775}
3776
[email protected]43c2f1f2011-03-25 18:35:363777bool GLES2DecoderImpl::PrepForSetUniformByLocation(
3778 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
3779 DCHECK(type);
3780 DCHECK(count);
[email protected]939e7362010-05-13 20:49:103781 if (!CheckCurrentProgramForUniform(location, function_name)) {
3782 return false;
3783 }
[email protected]43c2f1f2011-03-25 18:35:363784 GLint array_index = -1;
3785 const ProgramManager::ProgramInfo::UniformInfo* info =
3786 current_program_->GetUniformInfoByLocation(location, &array_index);
3787 if (!info) {
[email protected]939e7362010-05-13 20:49:103788 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:363789 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:103790 return false;
3791 }
[email protected]43c2f1f2011-03-25 18:35:363792 if (*count > 1 && !info->is_array) {
3793 SetGLError(
3794 GL_INVALID_OPERATION,
3795 (std::string(function_name) + ": count > 1 for non-array").c_str());
3796 return false;
3797 }
3798 *count = std::min(info->size - array_index, *count);
3799 if (*count <= 0) {
3800 return false;
3801 }
3802 *type = info->type;
[email protected]939e7362010-05-13 20:49:103803 return true;
3804}
3805
[email protected]939e7362010-05-13 20:49:103806void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
3807 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:503808 return;
3809 }
3810 current_program_->SetSamplers(location, 1, &v0);
3811 glUniform1i(location, v0);
3812}
3813
3814void GLES2DecoderImpl::DoUniform1iv(
3815 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:103816 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:503817 return;
3818 }
[email protected]43c2f1f2011-03-25 18:35:363819 GLenum type = 0;
3820 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
3821 return;
3822 }
3823 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE) {
3824 current_program_->SetSamplers(location, count, value);
3825 }
[email protected]3916c97e2010-02-25 03:20:503826 glUniform1iv(location, count, value);
3827}
3828
[email protected]939e7362010-05-13 20:49:103829void GLES2DecoderImpl::DoUniform1fv(
3830 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363831 GLenum type = 0;
3832 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103833 return;
3834 }
3835 if (type == GL_BOOL) {
3836 scoped_array<GLint> temp(new GLint[count]);
3837 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:533838 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103839 }
3840 DoUniform1iv(location, count, temp.get());
3841 } else {
3842 glUniform1fv(location, count, value);
3843 }
3844}
3845
3846void GLES2DecoderImpl::DoUniform2fv(
3847 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363848 GLenum type = 0;
3849 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103850 return;
3851 }
3852 if (type == GL_BOOL_VEC2) {
3853 GLsizei num_values = count * 2;
3854 scoped_array<GLint> temp(new GLint[num_values]);
3855 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533856 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103857 }
3858 glUniform2iv(location, count, temp.get());
3859 } else {
3860 glUniform2fv(location, count, value);
3861 }
3862}
3863
3864void GLES2DecoderImpl::DoUniform3fv(
3865 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363866 GLenum type = 0;
3867 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103868 return;
3869 }
3870 if (type == GL_BOOL_VEC3) {
3871 GLsizei num_values = count * 3;
3872 scoped_array<GLint> temp(new GLint[num_values]);
3873 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533874 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103875 }
3876 glUniform3iv(location, count, temp.get());
3877 } else {
3878 glUniform3fv(location, count, value);
3879 }
3880}
3881
3882void GLES2DecoderImpl::DoUniform4fv(
3883 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363884 GLenum type = 0;
3885 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103886 return;
3887 }
3888 if (type == GL_BOOL_VEC4) {
3889 GLsizei num_values = count * 4;
3890 scoped_array<GLint> temp(new GLint[num_values]);
3891 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533892 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103893 }
3894 glUniform4iv(location, count, temp.get());
3895 } else {
3896 glUniform4fv(location, count, value);
3897 }
3898}
3899
[email protected]43c2f1f2011-03-25 18:35:363900void GLES2DecoderImpl::DoUniform2iv(
3901 GLint location, GLsizei count, const GLint* value) {
3902 GLenum type = 0;
3903 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
3904 return;
3905 }
3906 glUniform2iv(location, count, value);
3907}
3908
3909void GLES2DecoderImpl::DoUniform3iv(
3910 GLint location, GLsizei count, const GLint* value) {
3911 GLenum type = 0;
3912 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
3913 return;
3914 }
3915 glUniform3iv(location, count, value);
3916}
3917
3918void GLES2DecoderImpl::DoUniform4iv(
3919 GLint location, GLsizei count, const GLint* value) {
3920 GLenum type = 0;
3921 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
3922 return;
3923 }
3924 glUniform4iv(location, count, value);
3925}
3926
3927void GLES2DecoderImpl::DoUniformMatrix2fv(
3928 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
3929 GLenum type = 0;
3930 if (!PrepForSetUniformByLocation(
3931 location, "glUniformMatrix2fv", &type, &count)) {
3932 return;
3933 }
3934 glUniformMatrix2fv (location, count, transpose, value);
3935}
3936
3937void GLES2DecoderImpl::DoUniformMatrix3fv(
3938 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
3939 GLenum type = 0;
3940 if (!PrepForSetUniformByLocation(
3941 location, "glUniformMatrix3fv", &type, &count)) {
3942 return;
3943 }
3944 glUniformMatrix3fv (location, count, transpose, value);
3945}
3946
3947void GLES2DecoderImpl::DoUniformMatrix4fv(
3948 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
3949 GLenum type = 0;
3950 if (!PrepForSetUniformByLocation(
3951 location, "glUniformMatrix4fv", &type, &count)) {
3952 return;
3953 }
3954 glUniformMatrix4fv (location, count, transpose, value);
3955}
3956
[email protected]3916c97e2010-02-25 03:20:503957void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:033958 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:503959 ProgramManager::ProgramInfo* info = NULL;
3960 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:583961 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:503962 if (!info) {
[email protected]ae51d192010-04-27 00:48:033963 return;
3964 }
3965 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:503966 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:293967 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:503968 return;
3969 }
[email protected]ae51d192010-04-27 00:48:033970 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:503971 }
[email protected]ca488e12010-12-13 20:06:143972 if (current_program_) {
3973 program_manager()->UnuseProgram(shader_manager(), current_program_);
3974 }
[email protected]3916c97e2010-02-25 03:20:503975 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:143976 if (current_program_) {
3977 program_manager()->UseProgram(current_program_);
3978 }
[email protected]ae51d192010-04-27 00:48:033979 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:503980}
3981
[email protected]96449d2c2009-11-25 00:01:323982GLenum GLES2DecoderImpl::GetGLError() {
3983 // Check the GL error first, then our wrapped error.
3984 GLenum error = glGetError();
3985 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:373986 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:323987 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:293988 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:323989 break;
3990 }
3991 }
3992 }
3993
3994 if (error != GL_NO_ERROR) {
3995 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:293996 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:323997 }
3998 return error;
3999}
4000
[email protected]8eee29c2010-04-29 03:38:294001void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4002 if (msg) {
4003 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:014004 LOG(ERROR) << last_error_;
[email protected]8eee29c2010-04-29 03:38:294005 }
[email protected]ddd968b82010-03-02 00:44:294006 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324007}
4008
[email protected]07f54fcc2009-12-22 02:46:304009void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4010 GLenum error;
4011 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294012 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304013 }
4014}
4015
[email protected]6217d392010-03-25 22:08:354016void GLES2DecoderImpl::ClearRealGLErrors() {
4017 GLenum error;
4018 while ((error = glGetError()) != GL_NO_ERROR) {
4019 NOTREACHED() << "GL error " << error << " was unhandled.";
4020 }
4021}
4022
[email protected]ef526492010-06-02 23:12:254023bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504024 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254025 // Only check if there are some unrenderable textures.
4026 if (!texture_manager()->HaveUnrenderableTextures()) {
4027 return false;
4028 }
4029 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504030 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4031 current_program_->sampler_indices();
4032 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4033 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4034 current_program_->GetUniformInfo(sampler_indices[ii]);
4035 DCHECK(uniform_info);
4036 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4037 GLuint texture_unit_index = uniform_info->texture_units[jj];
4038 if (texture_unit_index < group_->max_texture_units()) {
4039 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4040 TextureManager::TextureInfo* texture_info =
4041 uniform_info->type == GL_SAMPLER_2D ?
4042 texture_unit.bound_texture_2d :
4043 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114044 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]ef526492010-06-02 23:12:254045 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504046 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4047 glBindTexture(
4048 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
4049 GL_TEXTURE_CUBE_MAP,
[email protected]00f893d2010-08-24 18:55:494050 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504051 }
4052 }
4053 // else: should this be an error?
4054 }
4055 }
[email protected]ef526492010-06-02 23:12:254056 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504057}
4058
4059void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4060 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504061 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4062 current_program_->sampler_indices();
4063 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4064 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4065 current_program_->GetUniformInfo(sampler_indices[ii]);
4066 DCHECK(uniform_info);
4067 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4068 GLuint texture_unit_index = uniform_info->texture_units[jj];
4069 if (texture_unit_index < group_->max_texture_units()) {
4070 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4071 TextureManager::TextureInfo* texture_info =
4072 uniform_info->type == GL_SAMPLER_2D ?
4073 texture_unit.bound_texture_2d :
4074 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114075 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]3916c97e2010-02-25 03:20:504076 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4077 // Get the texture info that was previously bound here.
4078 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4079 texture_unit.bound_texture_2d :
4080 texture_unit.bound_texture_cube_map;
4081 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034082 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504083 }
4084 }
4085 }
4086 }
4087 // Set the active texture back to whatever the user had it as.
4088 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304089}
4090
4091bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034092 // NOTE: We specifically do not check current_program->IsValid() because
4093 // it could never be invalid since glUseProgram would have failed. While
4094 // glLinkProgram could later mark the program as invalid the previous
4095 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144096 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504097 // The program does not exist.
4098 // But GL says no ERROR.
4099 return false;
4100 }
[email protected]f39f4b3f2010-05-12 17:04:084101 // Validate all attribs currently enabled. If they are used by the current
4102 // program then check that they have enough elements to handle the draw call.
4103 // If they are not used by the current program check that they have a buffer
4104 // assigned.
4105 const VertexAttribManager::VertexAttribInfoList& infos =
4106 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4107 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404108 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084109 const VertexAttribManager::VertexAttribInfo* info = *it;
4110 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4111 current_program_->GetAttribInfoByLocation(info->index());
4112 if (attrib_info) {
4113 // This attrib is used in the current program.
4114 if (!info->CanAccess(max_vertex_accessed)) {
4115 SetGLError(GL_INVALID_OPERATION,
4116 "glDrawXXX: attempt to access out of range vertices");
4117 return false;
4118 }
4119 } else {
4120 // This attrib is not used in the current program.
4121 if (!info->buffer() || info->buffer()->IsDeleted()) {
4122 SetGLError(
4123 GL_INVALID_OPERATION,
4124 "glDrawXXX: attempt to render with no buffer attached to enabled "
4125 "attrib");
4126 return false;
4127 }
[email protected]1d32bc82010-01-13 22:06:464128 }
[email protected]07f54fcc2009-12-22 02:46:304129 }
[email protected]3916c97e2010-02-25 03:20:504130 return true;
[email protected]b1122982010-05-17 23:04:244131}
4132
4133bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
[email protected]876f6fee2010-08-02 23:10:324134 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4135 return false;
4136
[email protected]b1122982010-05-17 23:04:244137 const VertexAttribManager::VertexAttribInfo* info =
4138 vertex_attrib_manager_.GetVertexAttribInfo(0);
4139 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494140 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4141 if (info->enabled() && attrib_0_used) {
[email protected]b1122982010-05-17 23:04:244142 return false;
4143 }
4144
4145 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4146
4147 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4148
4149 // Make a buffer with a single repeated vec4 value enough to
4150 // simulate the constant value that is supposed to be here.
4151 // This is required to emulate GLES2 on GL.
4152 GLsizei num_vertices = max_vertex_accessed + 1;
4153 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
[email protected]fc753442011-02-04 19:49:494154 if (size_needed > attrib_0_size_) {
4155 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4156 // TODO(gman): check for error here?
4157 attrib_0_buffer_matches_value_ = false;
4158 }
4159 if (attrib_0_used &&
4160 (!attrib_0_buffer_matches_value_ ||
4161 (info->value().v[0] != attrib_0_value_.v[0] ||
4162 info->value().v[1] != attrib_0_value_.v[1] ||
4163 info->value().v[2] != attrib_0_value_.v[2] ||
4164 info->value().v[3] != attrib_0_value_.v[3]))) {
4165 std::vector<Vec4> temp(num_vertices, info->value());
4166 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4167 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244168 attrib_0_value_ = info->value();
4169 attrib_0_size_ = size_needed;
4170 }
4171
4172 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4173
4174 return true;
[email protected]b1122982010-05-17 23:04:244175}
4176
4177void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4178 const VertexAttribManager::VertexAttribInfo* info =
4179 vertex_attrib_manager_.GetVertexAttribInfo(0);
4180 const void* ptr = reinterpret_cast<const void*>(info->offset());
4181 BufferManager::BufferInfo* buffer_info = info->buffer();
4182 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4183 glVertexAttribPointer(
4184 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4185 ptr);
4186 glBindBuffer(GL_ARRAY_BUFFER,
4187 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4188}
[email protected]07f54fcc2009-12-22 02:46:304189
[email protected]8fbedc02010-11-18 18:43:404190bool GLES2DecoderImpl::SimulateFixedAttribs(
4191 GLuint max_vertex_accessed, bool* simulated) {
4192 DCHECK(simulated);
4193 *simulated = false;
4194 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4195 return true;
4196
4197 if (!vertex_attrib_manager_.HaveFixedAttribs()) {
4198 return true;
4199 }
4200
4201 // NOTE: we could be smart and try to check if a buffer is used
4202 // twice in 2 different attribs, find the overlapping parts and therefore
4203 // duplicate the minimum amount of data but this whole code path is not meant
4204 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4205 // tests so we just add to the buffer attrib used.
4206
4207 // Compute the number of elements needed.
4208 int num_vertices = max_vertex_accessed + 1;
4209 int elements_needed = 0;
4210 const VertexAttribManager::VertexAttribInfoList& infos =
4211 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4212 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4213 infos.begin(); it != infos.end(); ++it) {
4214 const VertexAttribManager::VertexAttribInfo* info = *it;
4215 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4216 current_program_->GetAttribInfoByLocation(info->index());
4217 if (attrib_info &&
4218 info->CanAccess(max_vertex_accessed) &&
4219 info->type() == GL_FIXED) {
4220 int elements_used = 0;
4221 if (!SafeMultiply(
4222 static_cast<int>(num_vertices),
4223 info->size(), &elements_used) ||
4224 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4225 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4226 return false;
4227 }
4228 }
4229 }
4230
4231 const int kSizeOfFloat = sizeof(float); // NOLINT
4232 int size_needed = 0;
4233 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed)) {
4234 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4235 return false;
4236 }
4237
4238
4239 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
4240 if (size_needed > fixed_attrib_buffer_size_) {
4241 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4242 }
4243
4244 // Copy the elements and convert to float
4245 GLintptr offset = 0;
4246 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4247 infos.begin(); it != infos.end(); ++it) {
4248 const VertexAttribManager::VertexAttribInfo* info = *it;
4249 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4250 current_program_->GetAttribInfoByLocation(info->index());
4251 if (attrib_info &&
4252 info->CanAccess(max_vertex_accessed) &&
4253 info->type() == GL_FIXED) {
4254 int num_elements = info->size() * kSizeOfFloat;
4255 int size = num_elements * num_vertices;
4256 scoped_array<float> data(new float[size]);
4257 const int32* src = reinterpret_cast<const int32 *>(
4258 info->buffer()->GetRange(info->offset(), size));
4259 const int32* end = src + num_elements;
4260 float* dst = data.get();
4261 while (src != end) {
4262 *dst++ = static_cast<float>(*src++) / 65536.0f;
4263 }
4264 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
4265 glVertexAttribPointer(
4266 info->index(), info->size(), GL_FLOAT, false, 0,
4267 reinterpret_cast<GLvoid*>(offset));
4268 offset += size;
4269 }
4270 }
4271 *simulated = true;
4272 return true;
4273}
4274
4275void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
4276 // There's no need to call glVertexAttribPointer because we shadow all the
4277 // settings and passing GL_FIXED to it will not work.
4278 glBindBuffer(GL_ARRAY_BUFFER,
4279 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4280}
4281
[email protected]f7a64ee2010-02-01 22:24:144282error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:194283 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:504284 if (!bound_element_array_buffer_ ||
4285 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:294286 SetGLError(GL_INVALID_OPERATION,
4287 "glDrawElements: No element array buffer bound");
4288 return error::kNoError;
4289 }
4290
4291 GLenum mode = c.mode;
4292 GLsizei count = c.count;
4293 GLenum type = c.type;
4294 int32 offset = c.index_offset;
4295 if (count < 0) {
4296 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
4297 return error::kNoError;
4298 }
4299 if (offset < 0) {
4300 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
4301 return error::kNoError;
4302 }
[email protected]9438b012010-06-15 22:55:054303 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:294304 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
4305 return error::kNoError;
4306 }
[email protected]9438b012010-06-15 22:55:054307 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294308 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
4309 return error::kNoError;
4310 }
4311
[email protected]3a03a8f2011-03-19 00:51:274312 if (!CheckFramebufferComplete("glDrawElements")) {
4313 return error::kNoError;
4314 }
4315
[email protected]6c788fb72010-08-26 02:16:314316 if (count == 0) {
4317 return error::kNoError;
4318 }
4319
[email protected]8eee29c2010-04-29 03:38:294320 GLuint max_vertex_accessed;
4321 if (!bound_element_array_buffer_->GetMaxValueForRange(
4322 offset, count, type, &max_vertex_accessed)) {
4323 SetGLError(GL_INVALID_OPERATION,
4324 "glDrawElements: range out of bounds for buffer");
4325 return error::kNoError;
4326 }
4327
4328 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:244329 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]8fbedc02010-11-18 18:43:404330 bool simulated_fixed_attribs = false;
4331 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4332 bool textures_set = SetBlackTextureForNonRenderableTextures();
4333 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
4334 glDrawElements(mode, count, type, indices);
4335 if (textures_set) {
4336 RestoreStateForNonRenderableTextures();
4337 }
4338 if (simulated_fixed_attribs) {
4339 RestoreStateForSimulatedFixedAttribs();
4340 }
[email protected]ba3176a2009-12-16 18:19:464341 }
[email protected]b1122982010-05-17 23:04:244342 if (simulated_attrib_0) {
4343 RestoreStateForSimulatedAttrib0();
4344 }
[email protected]96449d2c2009-11-25 00:01:324345 }
[email protected]f7a64ee2010-02-01 22:24:144346 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324347}
4348
[email protected]269200b12010-11-18 22:53:064349GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:234350 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
4351 GLuint max_vertex_accessed = 0;
4352 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:294353 if (!info) {
[email protected]ae51d192010-04-27 00:48:034354 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294355 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064356 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:234357 } else {
4358 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:034359 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:064360 SetGLError(
4361 GL_INVALID_OPERATION,
4362 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:234363 }
4364 }
4365 return max_vertex_accessed;
4366}
4367
[email protected]96449d2c2009-11-25 00:01:324368// Calls glShaderSource for the various versions of the ShaderSource command.
4369// Assumes that data / data_size points to a piece of memory that is in range
4370// of whatever context it came from (shared memory, immediate memory, bucket
4371// memory.)
[email protected]45bf5152010-02-12 00:11:314372error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034373 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:584374 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4375 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:314376 if (!info) {
[email protected]45bf5152010-02-12 00:11:314377 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324378 }
[email protected]45bf5152010-02-12 00:11:314379 // Note: We don't actually call glShaderSource here. We wait until
4380 // the call to glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524381 info->Update(std::string(data, data + data_size).c_str());
[email protected]f7a64ee2010-02-01 22:24:144382 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324383}
4384
[email protected]f7a64ee2010-02-01 22:24:144385error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:194386 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:324387 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314388 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:324389 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:464390 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144391 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324392 }
[email protected]ae51d192010-04-27 00:48:034393 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:324394}
4395
[email protected]f7a64ee2010-02-01 22:24:144396error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:194397 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:324398 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314399 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:304400 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464401 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144402 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324403 }
[email protected]ae51d192010-04-27 00:48:034404 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:314405}
4406
[email protected]558847a2010-03-24 07:02:544407error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
4408 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:544409 Bucket* bucket = GetBucket(c.data_bucket_id);
4410 if (!bucket || bucket->size() == 0) {
4411 return error::kInvalidArguments;
4412 }
4413 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034414 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:544415 bucket->size() - 1);
4416}
4417
[email protected]ae51d192010-04-27 00:48:034418void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584419 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4420 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:314421 if (!info) {
[email protected]45bf5152010-02-12 00:11:314422 return;
4423 }
[email protected]de17df392010-04-23 21:09:414424 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
4425 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524426 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:344427 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:184428 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:344429 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:454430 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:234431
[email protected]a550584e2010-09-17 18:01:454432 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:344433 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:184434 return;
4435 }
[email protected]a550584e2010-09-17 18:01:454436 shader_src = translator->translated_shader();
[email protected]de17df392010-04-23 21:09:414437 }
[email protected]de17df392010-04-23 21:09:414438
[email protected]ae51d192010-04-27 00:48:034439 glShaderSource(info->service_id(), 1, &shader_src, NULL);
4440 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:414441 GLint status = GL_FALSE;
4442 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
4443 if (status) {
[email protected]f57bb282010-11-12 00:51:344444 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:414445 } else {
[email protected]d9977d42010-09-01 20:27:024446 // We cannot reach here if we are using the shader translator.
4447 // All invalid shaders must be rejected by the translator.
4448 // All translated shaders must compile.
4449 LOG_IF(ERROR, use_shader_translator_)
4450 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:334451 GLint max_len = 0;
4452 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
4453 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:414454 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:334455 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
4456 DCHECK(max_len == 0 || len < max_len);
4457 DCHECK(len ==0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:524458 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:414459 }
[email protected]45bf5152010-02-12 00:11:314460};
4461
[email protected]ddd968b82010-03-02 00:44:294462void GLES2DecoderImpl::DoGetShaderiv(
4463 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:584464 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4465 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:294466 if (!info) {
[email protected]ddd968b82010-03-02 00:44:294467 return;
4468 }
[email protected]8f1ccdac2010-05-19 21:01:484469 switch (pname) {
4470 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524471 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:484472 return;
4473 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:414474 *params = info->IsValid();
4475 return;
[email protected]8f1ccdac2010-05-19 21:01:484476 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524477 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:414478 return;
[email protected]8f1ccdac2010-05-19 21:01:484479 default:
4480 break;
[email protected]ddd968b82010-03-02 00:44:294481 }
[email protected]8f1ccdac2010-05-19 21:01:484482 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:294483}
4484
[email protected]ae51d192010-04-27 00:48:034485error::Error GLES2DecoderImpl::HandleGetShaderSource(
4486 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
4487 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:034488 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4489 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:584490 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4491 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:524492 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:294493 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:294494 return error::kNoError;
4495 }
[email protected]df6cf1ad2011-01-29 01:20:524496 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:034497 return error::kNoError;
4498}
4499
4500error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
4501 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
4502 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:584503 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4504 Bucket* bucket = CreateBucket(bucket_id);
4505 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4506 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524507 if (!info || !info->log_info()) {
4508 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034509 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:314510 }
[email protected]df6cf1ad2011-01-29 01:20:524511 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034512 return error::kNoError;
4513}
4514
4515error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
4516 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
4517 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:584518 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4519 Bucket* bucket = CreateBucket(bucket_id);
4520 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4521 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524522 if (!info || !info->log_info()) {
[email protected]6b8cf1a2010-05-06 16:13:584523 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034524 return error::kNoError;
4525 }
[email protected]df6cf1ad2011-01-29 01:20:524526 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034527 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324528}
4529
[email protected]1958e0e2010-04-22 05:17:154530bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364531 const BufferManager::BufferInfo* info = GetBufferInfo(client_id);
4532 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154533}
4534
4535bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364536 const FramebufferManager::FramebufferInfo* info =
4537 GetFramebufferInfo(client_id);
4538 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154539}
4540
4541bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364542 // IsProgram is true for programs as soon as they are created, until they are
4543 // deleted and no longer in use.
[email protected]ae51d192010-04-27 00:48:034544 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154545}
4546
4547bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364548 const RenderbufferManager::RenderbufferInfo* info =
4549 GetRenderbufferInfo(client_id);
4550 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154551}
4552
4553bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364554 // IsShader is true for shaders as soon as they are created, until they
4555 // are deleted and not attached to any programs.
[email protected]ae51d192010-04-27 00:48:034556 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154557}
4558
4559bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364560 const TextureManager::TextureInfo* info = GetTextureInfo(client_id);
4561 return info && info->IsValid();
[email protected]ae51d192010-04-27 00:48:034562}
4563
4564void GLES2DecoderImpl::DoAttachShader(
4565 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584566 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4567 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034568 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034569 return;
[email protected]1958e0e2010-04-22 05:17:154570 }
[email protected]6b8cf1a2010-05-06 16:13:584571 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4572 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034573 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034574 return;
4575 }
[email protected]ca488e12010-12-13 20:06:144576 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:314577 SetGLError(GL_INVALID_OPERATION,
4578 "glAttachShader: can not attach more than"
4579 " one shader of the same type.");
4580 return;
4581 }
[email protected]ae51d192010-04-27 00:48:034582 glAttachShader(program_info->service_id(), shader_info->service_id());
4583}
4584
4585void GLES2DecoderImpl::DoDetachShader(
4586 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584587 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4588 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034589 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034590 return;
4591 }
[email protected]6b8cf1a2010-05-06 16:13:584592 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4593 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034594 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034595 return;
4596 }
[email protected]9a0ccd42011-03-16 23:58:224597 if (!program_info->DetachShader(shader_manager(), shader_info)) {
4598 SetGLError(GL_INVALID_OPERATION,
4599 "glDetachShader: shader not attached to program");
4600 return;
4601 }
[email protected]ae51d192010-04-27 00:48:034602 glDetachShader(program_info->service_id(), shader_info->service_id());
4603}
4604
4605void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584606 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4607 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:034608 if (!info) {
[email protected]ae51d192010-04-27 00:48:034609 return;
4610 }
[email protected]e5186162010-06-14 18:54:414611 if (!info->CanLink()) {
4612 info->set_log_info("Missing Shader");
4613 return;
4614 }
[email protected]ae51d192010-04-27 00:48:034615 glValidateProgram(info->service_id());
[email protected]e5186162010-06-14 18:54:414616 info->UpdateLogInfo();
[email protected]1958e0e2010-04-22 05:17:154617}
4618
[email protected]b1122982010-05-17 23:04:244619void GLES2DecoderImpl::DoGetVertexAttribfv(
4620 GLuint index, GLenum pname, GLfloat* params) {
4621 VertexAttribManager::VertexAttribInfo* info =
4622 vertex_attrib_manager_.GetVertexAttribInfo(index);
4623 if (!info) {
4624 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
4625 return;
4626 }
4627 switch (pname) {
4628 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4629 BufferManager::BufferInfo* buffer = info->buffer();
4630 if (buffer && !buffer->IsDeleted()) {
4631 GLuint client_id;
4632 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4633 *params = static_cast<GLfloat>(client_id);
4634 }
4635 break;
4636 }
4637 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4638 *params = static_cast<GLfloat>(info->enabled());
4639 break;
4640 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4641 *params = static_cast<GLfloat>(info->size());
4642 break;
4643 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4644 *params = static_cast<GLfloat>(info->gl_stride());
4645 break;
4646 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4647 *params = static_cast<GLfloat>(info->type());
4648 break;
4649 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4650 *params = static_cast<GLfloat>(info->normalized());
4651 break;
4652 case GL_CURRENT_VERTEX_ATTRIB:
4653 params[0] = info->value().v[0];
4654 params[1] = info->value().v[1];
4655 params[2] = info->value().v[2];
4656 params[3] = info->value().v[3];
4657 break;
4658 default:
4659 NOTREACHED();
4660 break;
4661 }
4662}
4663
4664void GLES2DecoderImpl::DoGetVertexAttribiv(
4665 GLuint index, GLenum pname, GLint* params) {
4666 VertexAttribManager::VertexAttribInfo* info =
4667 vertex_attrib_manager_.GetVertexAttribInfo(index);
4668 if (!info) {
4669 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
4670 return;
4671 }
4672 switch (pname) {
4673 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4674 BufferManager::BufferInfo* buffer = info->buffer();
4675 if (buffer && !buffer->IsDeleted()) {
4676 GLuint client_id;
4677 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4678 *params = client_id;
4679 }
4680 break;
4681 }
4682 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4683 *params = info->enabled();
4684 break;
4685 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4686 *params = info->size();
4687 break;
4688 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4689 *params = info->gl_stride();
4690 break;
4691 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4692 *params = info->type();
4693 break;
4694 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4695 *params = static_cast<GLint>(info->normalized());
4696 break;
4697 case GL_CURRENT_VERTEX_ATTRIB:
4698 params[0] = static_cast<GLint>(info->value().v[0]);
4699 params[1] = static_cast<GLint>(info->value().v[1]);
4700 params[2] = static_cast<GLint>(info->value().v[2]);
4701 params[3] = static_cast<GLint>(info->value().v[3]);
4702 break;
4703 default:
4704 NOTREACHED();
4705 break;
4706 }
4707}
4708
4709void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
4710 VertexAttribManager::VertexAttribInfo* info =
4711 vertex_attrib_manager_.GetVertexAttribInfo(index);
4712 if (!info) {
4713 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
4714 return;
4715 }
4716 VertexAttribManager::VertexAttribInfo::Vec4 value;
4717 value.v[0] = v0;
4718 value.v[1] = 0.0f;
4719 value.v[2] = 0.0f;
4720 value.v[3] = 1.0f;
4721 info->set_value(value);
4722 glVertexAttrib1f(index, v0);
4723}
4724
4725void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
4726 VertexAttribManager::VertexAttribInfo* info =
4727 vertex_attrib_manager_.GetVertexAttribInfo(index);
4728 if (!info) {
4729 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
4730 return;
4731 }
4732 VertexAttribManager::VertexAttribInfo::Vec4 value;
4733 value.v[0] = v0;
4734 value.v[1] = v1;
4735 value.v[2] = 0.0f;
4736 value.v[3] = 1.0f;
4737 info->set_value(value);
4738 glVertexAttrib2f(index, v0, v1);
4739}
4740
4741void GLES2DecoderImpl::DoVertexAttrib3f(
4742 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
4743 VertexAttribManager::VertexAttribInfo* info =
4744 vertex_attrib_manager_.GetVertexAttribInfo(index);
4745 if (!info) {
4746 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
4747 return;
4748 }
4749 VertexAttribManager::VertexAttribInfo::Vec4 value;
4750 value.v[0] = v0;
4751 value.v[1] = v1;
4752 value.v[2] = v2;
4753 value.v[3] = 1.0f;
4754 info->set_value(value);
4755 glVertexAttrib3f(index, v0, v1, v2);
4756}
4757
4758void GLES2DecoderImpl::DoVertexAttrib4f(
4759 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
4760 VertexAttribManager::VertexAttribInfo* info =
4761 vertex_attrib_manager_.GetVertexAttribInfo(index);
4762 if (!info) {
4763 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
4764 return;
4765 }
4766 VertexAttribManager::VertexAttribInfo::Vec4 value;
4767 value.v[0] = v0;
4768 value.v[1] = v1;
4769 value.v[2] = v2;
4770 value.v[3] = v3;
4771 info->set_value(value);
4772 glVertexAttrib4f(index, v0, v1, v2, v3);
4773}
4774
4775void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
4776 VertexAttribManager::VertexAttribInfo* info =
4777 vertex_attrib_manager_.GetVertexAttribInfo(index);
4778 if (!info) {
4779 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
4780 return;
4781 }
4782 VertexAttribManager::VertexAttribInfo::Vec4 value;
4783 value.v[0] = v[0];
4784 value.v[1] = 0.0f;
4785 value.v[2] = 0.0f;
4786 value.v[3] = 1.0f;
4787 info->set_value(value);
4788 glVertexAttrib1fv(index, v);
4789}
4790
4791void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
4792 VertexAttribManager::VertexAttribInfo* info =
4793 vertex_attrib_manager_.GetVertexAttribInfo(index);
4794 if (!info) {
4795 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
4796 return;
4797 }
4798 VertexAttribManager::VertexAttribInfo::Vec4 value;
4799 value.v[0] = v[0];
4800 value.v[1] = v[1];
4801 value.v[2] = 0.0f;
4802 value.v[3] = 1.0f;
4803 info->set_value(value);
4804 glVertexAttrib2fv(index, v);
4805}
4806
4807void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
4808 VertexAttribManager::VertexAttribInfo* info =
4809 vertex_attrib_manager_.GetVertexAttribInfo(index);
4810 if (!info) {
4811 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
4812 return;
4813 }
4814 VertexAttribManager::VertexAttribInfo::Vec4 value;
4815 value.v[0] = v[0];
4816 value.v[1] = v[1];
4817 value.v[2] = v[2];
4818 value.v[3] = 1.0f;
4819 info->set_value(value);
4820 glVertexAttrib3fv(index, v);
4821}
4822
4823void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
4824 VertexAttribManager::VertexAttribInfo* info =
4825 vertex_attrib_manager_.GetVertexAttribInfo(index);
4826 if (!info) {
4827 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
4828 return;
4829 }
4830 VertexAttribManager::VertexAttribInfo::Vec4 value;
4831 value.v[0] = v[0];
4832 value.v[1] = v[1];
4833 value.v[2] = v[2];
4834 value.v[3] = v[3];
4835 info->set_value(value);
4836 glVertexAttrib4fv(index, v);
4837}
4838
[email protected]f7a64ee2010-02-01 22:24:144839error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:194840 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:294841 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
4842 SetGLError(GL_INVALID_VALUE,
4843 "glVertexAttribPointer: no array buffer bound");
4844 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324845 }
[email protected]8eee29c2010-04-29 03:38:294846
4847 GLuint indx = c.indx;
4848 GLint size = c.size;
4849 GLenum type = c.type;
4850 GLboolean normalized = c.normalized;
4851 GLsizei stride = c.stride;
4852 GLsizei offset = c.offset;
4853 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:054854 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294855 SetGLError(GL_INVALID_ENUM,
4856 "glVertexAttribPointer: type GL_INVALID_ENUM");
4857 return error::kNoError;
4858 }
[email protected]9438b012010-06-15 22:55:054859 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:314860 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:294861 "glVertexAttribPointer: size GL_INVALID_VALUE");
4862 return error::kNoError;
4863 }
4864 if (indx >= group_->max_vertex_attribs()) {
4865 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
4866 return error::kNoError;
4867 }
4868 if (stride < 0) {
4869 SetGLError(GL_INVALID_VALUE,
4870 "glVertexAttribPointer: stride < 0");
4871 return error::kNoError;
4872 }
4873 if (stride > 255) {
4874 SetGLError(GL_INVALID_VALUE,
4875 "glVertexAttribPointer: stride > 255");
4876 return error::kNoError;
4877 }
4878 if (offset < 0) {
4879 SetGLError(GL_INVALID_VALUE,
4880 "glVertexAttribPointer: offset < 0");
4881 return error::kNoError;
4882 }
4883 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:314884 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:294885 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:314886 SetGLError(GL_INVALID_OPERATION,
4887 "glVertexAttribPointer: offset not valid for type");
4888 return error::kNoError;
4889 }
4890 if (stride % component_size > 0) {
4891 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:294892 "glVertexAttribPointer: stride not valid for type");
4893 return error::kNoError;
4894 }
[email protected]8fbedc02010-11-18 18:43:404895 vertex_attrib_manager_.SetAttribInfo(
4896 indx,
[email protected]8eee29c2010-04-29 03:38:294897 bound_array_buffer_,
4898 size,
4899 type,
[email protected]b1122982010-05-17 23:04:244900 normalized,
4901 stride,
4902 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:294903 offset);
[email protected]8fbedc02010-11-18 18:43:404904 if (type != GL_FIXED) {
4905 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
4906 }
[email protected]f7a64ee2010-02-01 22:24:144907 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324908}
4909
[email protected]f7a64ee2010-02-01 22:24:144910error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:194911 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:314912 GLint x = c.x;
4913 GLint y = c.y;
4914 GLsizei width = c.width;
4915 GLsizei height = c.height;
4916 GLenum format = c.format;
4917 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:564918 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:294919 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:564920 return error::kNoError;
4921 }
[email protected]a51788e2010-02-24 21:54:254922 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:184923 uint32 pixels_size;
4924 if (!GLES2Util::ComputeImageDataSize(
4925 width, height, format, type, pack_alignment_, &pixels_size)) {
4926 return error::kOutOfBounds;
4927 }
[email protected]612d2f82009-12-08 20:49:314928 void* pixels = GetSharedMemoryAs<void*>(
4929 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:254930 Result* result = GetSharedMemoryAs<Result*>(
4931 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4932 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:144933 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464934 }
[email protected]a51788e2010-02-24 21:54:254935
[email protected]9438b012010-06-15 22:55:054936 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:294937 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
4938 return error::kNoError;
4939 }
[email protected]9438b012010-06-15 22:55:054940 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294941 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:124942 return error::kNoError;
4943 }
[email protected]57f223832010-03-19 01:57:564944 if (width == 0 || height == 0) {
4945 return error::kNoError;
4946 }
4947
4948 CopyRealGLErrorsToWrapper();
4949
[email protected]34ff8b0c2010-10-01 20:06:024950 ScopedResolvedFrameBufferBinder binder(this);
4951
[email protected]57f223832010-03-19 01:57:564952 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:304953 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:564954
4955 GLint max_x;
4956 GLint max_y;
4957 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:294958 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:144959 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:314960 }
[email protected]57f223832010-03-19 01:57:564961
[email protected]d37231fa2010-04-09 21:16:024962 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:564963 // The user requested an out of range area. Get the results 1 line
4964 // at a time.
4965 uint32 temp_size;
4966 if (!GLES2Util::ComputeImageDataSize(
4967 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:294968 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564969 return error::kNoError;
4970 }
4971 GLsizei unpadded_row_size = temp_size;
4972 if (!GLES2Util::ComputeImageDataSize(
4973 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:294974 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564975 return error::kNoError;
4976 }
4977 GLsizei padded_row_size = temp_size - unpadded_row_size;
4978 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:294979 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564980 return error::kNoError;
4981 }
4982
4983 GLint dest_x_offset = std::max(-x, 0);
4984 uint32 dest_row_offset;
4985 if (!GLES2Util::ComputeImageDataSize(
4986 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:294987 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564988 return error::kNoError;
4989 }
4990
4991 // Copy each row into the larger dest rect.
4992 int8* dst = static_cast<int8*>(pixels);
4993 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:024994 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:564995 GLint read_width = read_end_x - read_x;
4996 for (GLint yy = 0; yy < height; ++yy) {
4997 GLint ry = y + yy;
4998
4999 // Clear the row.
5000 memset(dst, 0, unpadded_row_size);
5001
5002 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025003 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565004 glReadPixels(
5005 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5006 }
5007 dst += padded_row_size;
5008 }
5009 } else {
5010 glReadPixels(x, y, width, height, format, type, pixels);
5011 }
[email protected]a51788e2010-02-24 21:54:255012 GLenum error = glGetError();
5013 if (error == GL_NO_ERROR) {
5014 *result = true;
[email protected]4848b9f82011-03-10 18:37:565015
5016 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5017 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5018 if ((channels_exist & 0x0008) == 0) {
5019 // Set the alpha to 255 because some drivers are buggy in this regard.
5020 uint32 temp_size;
5021 if (!GLES2Util::ComputeImageDataSize(
5022 width, 1, format, type, pack_alignment_, &temp_size)) {
5023 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5024 return error::kNoError;
5025 }
5026 GLsizei unpadded_row_size = temp_size;
5027 if (!GLES2Util::ComputeImageDataSize(
5028 width, 2, format, type, pack_alignment_, &temp_size)) {
5029 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5030 return error::kNoError;
5031 }
5032 GLsizei padded_row_size = temp_size - unpadded_row_size;
5033 if (padded_row_size < 0 || unpadded_row_size < 0) {
5034 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5035 return error::kNoError;
5036 }
5037 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5038 // of this implementation.
5039 if (type != GL_UNSIGNED_BYTE) {
5040 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5041 return error::kNoError;
5042 }
5043 switch (format) {
5044 case GL_RGBA:
5045 case GL_ALPHA: {
5046 int offset = (format == GL_ALPHA) ? 0 : 3;
5047 int step = (format == GL_ALPHA) ? 1 : 4;
5048 uint8* dst = static_cast<uint8*>(pixels) + offset;
5049 for (GLint yy = 0; yy < height; ++yy) {
5050 uint8* end = dst + unpadded_row_size;
5051 for (uint8* d = dst; d < end; d += step) {
5052 *d = 255;
5053 }
5054 dst += padded_row_size;
5055 }
5056 break;
5057 }
5058 default:
5059 break;
5060 }
5061 }
[email protected]a51788e2010-02-24 21:54:255062 } else {
[email protected]8eee29c2010-04-29 03:38:295063 SetGLError(error, NULL);
[email protected]a51788e2010-02-24 21:54:255064 }
[email protected]4848b9f82011-03-10 18:37:565065
[email protected]f7a64ee2010-02-01 22:24:145066 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325067}
5068
[email protected]f7a64ee2010-02-01 22:24:145069error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195070 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5071 GLenum pname = c.pname;
5072 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055073 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295074 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125075 return error::kNoError;
5076 }
[email protected]9438b012010-06-15 22:55:055077 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:295078 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:145079 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195080 }
5081 glPixelStorei(pname, param);
5082 switch (pname) {
5083 case GL_PACK_ALIGNMENT:
5084 pack_alignment_ = param;
5085 break;
5086 case GL_UNPACK_ALIGNMENT:
5087 unpack_alignment_ = param;
5088 break;
5089 default:
5090 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:375091 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:195092 break;
5093 }
[email protected]f7a64ee2010-02-01 22:24:145094 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195095}
5096
[email protected]558847a2010-03-24 07:02:545097error::Error GLES2DecoderImpl::GetAttribLocationHelper(
5098 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5099 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585100 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5101 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:035102 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145103 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195104 }
[email protected]ae51d192010-04-27 00:48:035105 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295106 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255107 return error::kNoError;
5108 }
[email protected]b9849abf2009-11-25 19:13:195109 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545110 location_shm_id, location_shm_offset, sizeof(GLint));
5111 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145112 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195113 }
[email protected]558847a2010-03-24 07:02:545114 // Require the client to init this incase the context is lost and we are no
5115 // longer executing commands.
5116 if (*location != -1) {
5117 return error::kGenericError;
5118 }
[email protected]0bfd9882010-02-05 23:02:255119 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145120 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195121}
5122
[email protected]558847a2010-03-24 07:02:545123error::Error GLES2DecoderImpl::HandleGetAttribLocation(
5124 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
5125 uint32 name_size = c.data_size;
5126 const char* name = GetSharedMemoryAs<const char*>(
5127 c.name_shm_id, c.name_shm_offset, name_size);
5128 if (!name) {
5129 return error::kOutOfBounds;
5130 }
5131 String name_str(name, name_size);
5132 return GetAttribLocationHelper(
5133 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5134}
5135
[email protected]f7a64ee2010-02-01 22:24:145136error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195137 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:545138 uint32 name_size = c.data_size;
5139 const char* name = GetImmediateDataAs<const char*>(
5140 c, name_size, immediate_data_size);
5141 if (!name) {
5142 return error::kOutOfBounds;
5143 }
5144 String name_str(name, name_size);
5145 return GetAttribLocationHelper(
5146 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5147}
5148
5149error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
5150 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
5151 Bucket* bucket = GetBucket(c.name_bucket_id);
5152 if (!bucket) {
5153 return error::kInvalidArguments;
5154 }
5155 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185156 if (!bucket->GetAsString(&name_str)) {
5157 return error::kInvalidArguments;
5158 }
[email protected]558847a2010-03-24 07:02:545159 return GetAttribLocationHelper(
5160 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5161}
5162
5163error::Error GLES2DecoderImpl::GetUniformLocationHelper(
5164 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5165 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585166 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5167 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:035168 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145169 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195170 }
[email protected]ae51d192010-04-27 00:48:035171 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295172 SetGLError(GL_INVALID_OPERATION,
5173 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255174 return error::kNoError;
5175 }
[email protected]b9849abf2009-11-25 19:13:195176 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545177 location_shm_id, location_shm_offset, sizeof(GLint));
5178 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145179 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195180 }
[email protected]558847a2010-03-24 07:02:545181 // Require the client to init this incase the context is lost an we are no
5182 // longer executing commands.
5183 if (*location != -1) {
5184 return error::kGenericError;
5185 }
5186 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145187 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195188}
5189
[email protected]f7a64ee2010-02-01 22:24:145190error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:195191 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:195192 uint32 name_size = c.data_size;
5193 const char* name = GetSharedMemoryAs<const char*>(
5194 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:545195 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145196 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195197 }
5198 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545199 return GetUniformLocationHelper(
5200 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195201}
5202
[email protected]f7a64ee2010-02-01 22:24:145203error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195204 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:195205 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:305206 const char* name = GetImmediateDataAs<const char*>(
5207 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:545208 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145209 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195210 }
5211 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545212 return GetUniformLocationHelper(
5213 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5214}
5215
5216error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
5217 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
5218 Bucket* bucket = GetBucket(c.name_bucket_id);
5219 if (!bucket) {
5220 return error::kInvalidArguments;
5221 }
5222 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185223 if (!bucket->GetAsString(&name_str)) {
5224 return error::kInvalidArguments;
5225 }
[email protected]558847a2010-03-24 07:02:545226 return GetUniformLocationHelper(
5227 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195228}
5229
[email protected]ddd968b82010-03-02 00:44:295230error::Error GLES2DecoderImpl::HandleGetString(
5231 uint32 immediate_data_size, const gles2::GetString& c) {
5232 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:055233 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:295234 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:295235 return error::kNoError;
5236 }
[email protected]1958e0e2010-04-22 05:17:155237 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
5238 const char* str = NULL;
5239 switch (name) {
5240 case GL_VERSION:
5241 str = "OpenGL ES 2.0 Chromium";
5242 break;
5243 case GL_SHADING_LANGUAGE_VERSION:
5244 str = "OpenGL ES GLSL ES 1.0 Chromium";
5245 break;
5246 case GL_EXTENSIONS:
[email protected]915a59a12010-09-30 21:29:115247 str = feature_info_->extensions().c_str();
[email protected]1958e0e2010-04-22 05:17:155248 break;
5249 default:
5250 str = gl_str;
5251 break;
5252 }
[email protected]ddd968b82010-03-02 00:44:295253 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:155254 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:295255 return error::kNoError;
5256}
5257
[email protected]0c86dbf2010-03-05 08:14:115258void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:155259 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:055260 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295261 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
5262 return;
5263 }
[email protected]9438b012010-06-15 22:55:055264 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:295265 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:115266 return;
[email protected]3b6ec202010-03-05 05:16:235267 }
5268 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:295269 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:285270 return;
[email protected]3b6ec202010-03-05 05:16:235271 }
5272 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
5273 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295274 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285275 return;
[email protected]3b6ec202010-03-05 05:16:235276 }
5277 // Clear the buffer to 0 if no initial data was passed in.
5278 scoped_array<int8> zero;
5279 if (!data) {
5280 zero.reset(new int8[size]);
5281 memset(zero.get(), 0, size);
5282 data = zero.get();
5283 }
5284 CopyRealGLErrorsToWrapper();
5285 glBufferData(target, size, data, usage);
5286 GLenum error = glGetError();
5287 if (error != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:295288 SetGLError(error, NULL);
[email protected]3b6ec202010-03-05 05:16:235289 } else {
[email protected]4e8a5b122010-05-08 22:00:105290 buffer_manager()->SetSize(info, size);
[email protected]0c86dbf2010-03-05 08:14:115291 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:235292 }
[email protected]0c86dbf2010-03-05 08:14:115293}
5294
5295error::Error GLES2DecoderImpl::HandleBufferData(
5296 uint32 immediate_data_size, const gles2::BufferData& c) {
5297 GLenum target = static_cast<GLenum>(c.target);
5298 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
5299 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5300 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5301 GLenum usage = static_cast<GLenum>(c.usage);
5302 const void* data = NULL;
5303 if (data_shm_id != 0 || data_shm_offset != 0) {
5304 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
5305 if (!data) {
5306 return error::kOutOfBounds;
5307 }
5308 }
5309 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:145310 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195311}
5312
[email protected]f7a64ee2010-02-01 22:24:145313error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:195314 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
5315 GLenum target = static_cast<GLenum>(c.target);
5316 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:305317 const void* data = GetImmediateDataAs<const void*>(
5318 c, size, immediate_data_size);
5319 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145320 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:305321 }
[email protected]b9849abf2009-11-25 19:13:195322 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:115323 DoBufferData(target, size, data, usage);
5324 return error::kNoError;
5325}
5326
5327void GLES2DecoderImpl::DoBufferSubData(
5328 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:505329 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475330 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295331 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285332 return;
[email protected]a93bb842010-02-16 23:03:475333 }
[email protected]0c86dbf2010-03-05 08:14:115334 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:295335 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]07f54fcc2009-12-22 02:46:305336 } else {
[email protected]0c86dbf2010-03-05 08:14:115337 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:305338 }
[email protected]b9849abf2009-11-25 19:13:195339}
5340
[email protected]a93bb842010-02-16 23:03:475341error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
5342 GLenum target,
5343 GLint level,
5344 GLenum internal_format,
5345 GLsizei width,
5346 GLsizei height,
5347 GLint border,
5348 GLsizei image_size,
5349 const void* data) {
[email protected]a93bb842010-02-16 23:03:475350 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:055351 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295352 SetGLError(GL_INVALID_ENUM,
5353 "glCompressedTexImage2D: target GL_INVALID_ENUM");
5354 return error::kNoError;
5355 }
[email protected]9438b012010-06-15 22:55:055356 if (!validators_->compressed_texture_format.IsValid(
5357 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295358 SetGLError(GL_INVALID_ENUM,
5359 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:475360 return error::kNoError;
5361 }
[email protected]915a59a12010-09-30 21:29:115362 if (!texture_manager()->ValidForTarget(
5363 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475364 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295365 SetGLError(GL_INVALID_VALUE,
5366 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475367 return error::kNoError;
5368 }
[email protected]3916c97e2010-02-25 03:20:505369 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475370 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295371 SetGLError(GL_INVALID_VALUE,
5372 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:475373 return error::kNoError;
5374 }
5375 scoped_array<int8> zero;
5376 if (!data) {
5377 zero.reset(new int8[image_size]);
5378 memset(zero.get(), 0, image_size);
5379 data = zero.get();
5380 }
[email protected]cadde4a2010-07-31 17:10:435381 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475382 glCompressedTexImage2D(
5383 target, level, internal_format, width, height, border, image_size, data);
[email protected]cadde4a2010-07-31 17:10:435384 GLenum error = glGetError();
5385 if (error == GL_NO_ERROR) {
5386 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115387 feature_info_,
[email protected]cadde4a2010-07-31 17:10:435388 info, target, level, internal_format, width, height, 1, border, 0, 0);
5389 }
[email protected]a93bb842010-02-16 23:03:475390 return error::kNoError;
5391}
5392
[email protected]f7a64ee2010-02-01 22:24:145393error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195394 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
5395 GLenum target = static_cast<GLenum>(c.target);
5396 GLint level = static_cast<GLint>(c.level);
5397 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5398 GLsizei width = static_cast<GLsizei>(c.width);
5399 GLsizei height = static_cast<GLsizei>(c.height);
5400 GLint border = static_cast<GLint>(c.border);
5401 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
5402 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5403 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5404 const void* data = NULL;
5405 if (data_shm_id != 0 || data_shm_offset != 0) {
5406 data = GetSharedMemoryAs<const void*>(
5407 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:465408 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145409 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195410 }
5411 }
[email protected]a93bb842010-02-16 23:03:475412 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195413 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:195414}
5415
[email protected]f7a64ee2010-02-01 22:24:145416error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195417 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
5418 GLenum target = static_cast<GLenum>(c.target);
5419 GLint level = static_cast<GLint>(c.level);
5420 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5421 GLsizei width = static_cast<GLsizei>(c.width);
5422 GLsizei height = static_cast<GLsizei>(c.height);
5423 GLint border = static_cast<GLint>(c.border);
5424 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:305425 const void* data = GetImmediateDataAs<const void*>(
5426 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465427 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145428 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465429 }
[email protected]a93bb842010-02-16 23:03:475430 return DoCompressedTexImage2D(
5431 target, level, internal_format, width, height, border, image_size, data);
5432}
5433
[email protected]b6140d02010-05-17 14:47:165434error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
5435 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
5436 GLenum target = static_cast<GLenum>(c.target);
5437 GLint level = static_cast<GLint>(c.level);
5438 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5439 GLsizei width = static_cast<GLsizei>(c.width);
5440 GLsizei height = static_cast<GLsizei>(c.height);
5441 GLint border = static_cast<GLint>(c.border);
5442 Bucket* bucket = GetBucket(c.bucket_id);
5443 return DoCompressedTexImage2D(
5444 target, level, internal_format, width, height, border,
5445 bucket->size(), bucket->GetData(0, bucket->size()));
5446}
5447
5448error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
5449 uint32 immediate_data_size,
5450 const gles2::CompressedTexSubImage2DBucket& c) {
5451 GLenum target = static_cast<GLenum>(c.target);
5452 GLint level = static_cast<GLint>(c.level);
5453 GLint xoffset = static_cast<GLint>(c.xoffset);
5454 GLint yoffset = static_cast<GLint>(c.yoffset);
5455 GLsizei width = static_cast<GLsizei>(c.width);
5456 GLsizei height = static_cast<GLsizei>(c.height);
5457 GLenum format = static_cast<GLenum>(c.format);
5458 Bucket* bucket = GetBucket(c.bucket_id);
5459 uint32 data_size = bucket->size();
5460 GLsizei imageSize = data_size;
5461 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:055462 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:165463 SetGLError(
5464 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
5465 return error::kNoError;
5466 }
[email protected]9438b012010-06-15 22:55:055467 if (!validators_->compressed_texture_format.IsValid(format)) {
5468 SetGLError(GL_INVALID_ENUM,
5469 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
5470 return error::kNoError;
5471 }
[email protected]b6140d02010-05-17 14:47:165472 if (width < 0) {
5473 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
5474 return error::kNoError;
5475 }
5476 if (height < 0) {
5477 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
5478 return error::kNoError;
5479 }
5480 if (imageSize < 0) {
5481 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
5482 return error::kNoError;
5483 }
[email protected]cadde4a2010-07-31 17:10:435484 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:165485 target, level, xoffset, yoffset, width, height, format, imageSize, data);
5486 return error::kNoError;
5487}
5488
[email protected]a93bb842010-02-16 23:03:475489error::Error GLES2DecoderImpl::DoTexImage2D(
5490 GLenum target,
5491 GLint level,
5492 GLenum internal_format,
5493 GLsizei width,
5494 GLsizei height,
5495 GLint border,
5496 GLenum format,
5497 GLenum type,
5498 const void* pixels,
5499 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:055500 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295501 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
5502 return error::kNoError;
5503 }
[email protected]9438b012010-06-15 22:55:055504 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295505 SetGLError(GL_INVALID_ENUM,
5506 "glTexImage2D: internal_format GL_INVALID_ENUM");
5507 return error::kNoError;
5508 }
[email protected]9438b012010-06-15 22:55:055509 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295510 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
5511 return error::kNoError;
5512 }
[email protected]9438b012010-06-15 22:55:055513 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295514 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145515 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195516 }
[email protected]7b92c412010-07-20 17:48:255517 if (format != internal_format) {
5518 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
5519 return error::kNoError;
5520 }
[email protected]915a59a12010-09-30 21:29:115521 if (!texture_manager()->ValidForTarget(
5522 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475523 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295524 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475525 return error::kNoError;
5526 }
[email protected]3916c97e2010-02-25 03:20:505527 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475528 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295529 SetGLError(GL_INVALID_OPERATION,
5530 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:475531 return error::kNoError;
5532 }
5533 scoped_array<int8> zero;
5534 if (!pixels) {
5535 zero.reset(new int8[pixels_size]);
5536 memset(zero.get(), 0, pixels_size);
5537 pixels = zero.get();
5538 }
[email protected]876f6fee2010-08-02 23:10:325539
[email protected]f5719fb2010-08-04 18:27:185540 GLenum gl_internal_format = internal_format;
[email protected]876f6fee2010-08-02 23:10:325541 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
5542 if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
[email protected]f5719fb2010-08-04 18:27:185543 gl_internal_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:325544 } else if (type == GL_FLOAT) {
5545 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:185546 gl_internal_format = GL_RGBA32F_ARB;
[email protected]876f6fee2010-08-02 23:10:325547 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:185548 gl_internal_format = GL_RGB32F_ARB;
[email protected]876f6fee2010-08-02 23:10:325549 }
5550 } else if (type == GL_HALF_FLOAT_OES) {
5551 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:185552 gl_internal_format = GL_RGBA16F_ARB;
[email protected]876f6fee2010-08-02 23:10:325553 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:185554 gl_internal_format = GL_RGB16F_ARB;
[email protected]876f6fee2010-08-02 23:10:325555 }
[email protected]7b92c412010-07-20 17:48:255556 }
[email protected]7488d962010-07-16 02:41:585557 }
[email protected]876f6fee2010-08-02 23:10:325558
[email protected]cadde4a2010-07-31 17:10:435559 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475560 glTexImage2D(
[email protected]f5719fb2010-08-04 18:27:185561 target, level, gl_internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475562 pixels);
[email protected]cadde4a2010-07-31 17:10:435563 GLenum error = glGetError();
5564 if (error == GL_NO_ERROR) {
[email protected]915a59a12010-09-30 21:29:115565 texture_manager()->SetLevelInfo(feature_info_, info,
[email protected]cadde4a2010-07-31 17:10:435566 target, level, internal_format, width, height, 1, border, format, type);
5567 }
[email protected]f7a64ee2010-02-01 22:24:145568 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195569}
5570
[email protected]f7a64ee2010-02-01 22:24:145571error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195572 uint32 immediate_data_size, const gles2::TexImage2D& c) {
5573 GLenum target = static_cast<GLenum>(c.target);
5574 GLint level = static_cast<GLint>(c.level);
5575 GLint internal_format = static_cast<GLint>(c.internalformat);
5576 GLsizei width = static_cast<GLsizei>(c.width);
5577 GLsizei height = static_cast<GLsizei>(c.height);
5578 GLint border = static_cast<GLint>(c.border);
5579 GLenum format = static_cast<GLenum>(c.format);
5580 GLenum type = static_cast<GLenum>(c.type);
5581 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
5582 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:185583 uint32 pixels_size;
5584 if (!GLES2Util::ComputeImageDataSize(
5585 width, height, format, type, unpack_alignment_, &pixels_size)) {
5586 return error::kOutOfBounds;
5587 }
[email protected]b9849abf2009-11-25 19:13:195588 const void* pixels = NULL;
5589 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
5590 pixels = GetSharedMemoryAs<const void*>(
5591 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:465592 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145593 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195594 }
5595 }
[email protected]a93bb842010-02-16 23:03:475596 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195597 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475598 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:195599}
5600
[email protected]f7a64ee2010-02-01 22:24:145601error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195602 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
5603 GLenum target = static_cast<GLenum>(c.target);
5604 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:465605 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:195606 GLsizei width = static_cast<GLsizei>(c.width);
5607 GLsizei height = static_cast<GLsizei>(c.height);
5608 GLint border = static_cast<GLint>(c.border);
5609 GLenum format = static_cast<GLenum>(c.format);
5610 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:185611 uint32 size;
5612 if (!GLES2Util::ComputeImageDataSize(
5613 width, height, format, type, unpack_alignment_, &size)) {
5614 return error::kOutOfBounds;
5615 }
[email protected]07f54fcc2009-12-22 02:46:305616 const void* pixels = GetImmediateDataAs<const void*>(
5617 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465618 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145619 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465620 }
[email protected]a93bb842010-02-16 23:03:475621 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:465622 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475623 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:145624 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325625}
5626
[email protected]cadde4a2010-07-31 17:10:435627void GLES2DecoderImpl::DoCompressedTexSubImage2D(
5628 GLenum target,
5629 GLint level,
5630 GLint xoffset,
5631 GLint yoffset,
5632 GLsizei width,
5633 GLsizei height,
5634 GLenum format,
5635 GLsizei image_size,
5636 const void * data) {
5637 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5638 if (!info) {
5639 SetGLError(GL_INVALID_OPERATION,
5640 "glCompressedTexSubImage2D: unknown texture for target");
5641 return;
5642 }
5643 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:525644 GLenum internal_format = 0;
5645 if (!info->GetLevelType(target, level, &type, &internal_format)) {
5646 SetGLError(
5647 GL_INVALID_OPERATION,
5648 "glCompressdTexSubImage2D: level does not exist.");
5649 return;
5650 }
5651 if (internal_format != format) {
5652 SetGLError(
5653 GL_INVALID_OPERATION,
5654 "glCompressdTexSubImage2D: format does not match internal format.");
5655 return;
5656 }
5657 if (!info->ValidForTexture(
5658 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:435659 SetGLError(GL_INVALID_VALUE,
5660 "glCompressdTexSubImage2D: bad dimensions.");
5661 return;
5662 }
5663 glCompressedTexSubImage2D(
5664 target, level, xoffset, yoffset, width, height, format, image_size, data);
5665}
5666
[email protected]6e288612010-12-21 20:45:035667static void Clip(
5668 GLint start, GLint range, GLint sourceRange,
5669 GLint* out_start, GLint* out_range) {
5670 DCHECK(out_start);
5671 DCHECK(out_range);
5672 if (start < 0) {
5673 range += start;
5674 start = 0;
5675 }
5676 GLint end = start + range;
5677 if (end > sourceRange) {
5678 range -= end - sourceRange;
5679 }
5680 *out_start = start;
5681 *out_range = range;
5682}
5683
5684
[email protected]cadde4a2010-07-31 17:10:435685void GLES2DecoderImpl::DoCopyTexImage2D(
5686 GLenum target,
5687 GLint level,
5688 GLenum internal_format,
5689 GLint x,
5690 GLint y,
5691 GLsizei width,
5692 GLsizei height,
5693 GLint border) {
5694 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5695 if (!info) {
5696 SetGLError(GL_INVALID_OPERATION,
5697 "glCopyTexImage2D: unknown texture for target");
5698 return;
5699 }
[email protected]915a59a12010-09-30 21:29:115700 if (!texture_manager()->ValidForTarget(
5701 feature_info_, target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:185702 border != 0) {
5703 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
5704 return;
5705 }
5706
[email protected]9edc6b22010-12-23 02:00:265707 // Check we have compatible formats.
5708 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5709 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5710 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
5711
5712 if ((channels_needed & channels_exist) != channels_needed) {
5713 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
5714 return;
5715 }
5716
[email protected]cadde4a2010-07-31 17:10:435717 CopyRealGLErrorsToWrapper();
[email protected]34ff8b0c2010-10-01 20:06:025718 ScopedResolvedFrameBufferBinder binder(this);
[email protected]6e288612010-12-21 20:45:035719 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:265720
5721 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:035722 GLint copyX = 0;
5723 GLint copyY = 0;
5724 GLint copyWidth = 0;
5725 GLint copyHeight = 0;
5726 Clip(x, width, size.width(), &copyX, &copyWidth);
5727 Clip(y, height, size.height(), &copyY, &copyHeight);
5728
5729 if (copyX != x ||
5730 copyY != y ||
5731 copyWidth != width ||
5732 copyHeight != height) {
5733 // some part was clipped so clear the texture.
5734 uint32 pixels_size = 0;
5735 if (!GLES2Util::ComputeImageDataSize(
5736 width, height, internal_format, GL_UNSIGNED_BYTE,
5737 unpack_alignment_, &pixels_size)) {
5738 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions too large");
5739 return;
5740 }
5741 scoped_array<char> zero(new char[pixels_size]);
5742 memset(zero.get(), 0, pixels_size);
5743 glTexImage2D(target, level, internal_format, width, height, 0,
5744 internal_format, GL_UNSIGNED_BYTE, zero.get());
5745 if (copyHeight > 0 && copyWidth > 0) {
5746 GLint dx = copyX - x;
5747 GLint dy = copyY - y;
5748 GLint destX = dx;
5749 GLint destY = dy;
5750 glCopyTexSubImage2D(target, level,
5751 destX, destY, copyX, copyY,
5752 copyWidth, copyHeight);
5753 }
5754 } else {
5755 glCopyTexImage2D(target, level, internal_format,
5756 copyX, copyY, copyWidth, copyHeight, border);
5757 }
[email protected]cadde4a2010-07-31 17:10:435758 GLenum error = glGetError();
5759 if (error == GL_NO_ERROR) {
5760 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115761 feature_info_, info, target, level, internal_format, width, height, 1,
5762 border, internal_format, GL_UNSIGNED_BYTE);
[email protected]cadde4a2010-07-31 17:10:435763 }
5764}
5765
5766void GLES2DecoderImpl::DoCopyTexSubImage2D(
5767 GLenum target,
5768 GLint level,
5769 GLint xoffset,
5770 GLint yoffset,
5771 GLint x,
5772 GLint y,
5773 GLsizei width,
5774 GLsizei height) {
5775 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5776 if (!info) {
5777 SetGLError(GL_INVALID_OPERATION,
5778 "glCopyTexSubImage2D: unknown texture for target");
5779 return;
5780 }
5781 GLenum type = 0;
5782 GLenum format = 0;
5783 if (!info->GetLevelType(target, level, &type, &format) ||
5784 !info->ValidForTexture(
5785 target, level, xoffset, yoffset, width, height, format, type)) {
5786 SetGLError(GL_INVALID_VALUE,
5787 "glCopyTexSubImage2D: bad dimensions.");
5788 return;
5789 }
[email protected]9edc6b22010-12-23 02:00:265790
5791 // Check we have compatible formats.
5792 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5793 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5794 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
5795
5796 if ((channels_needed & channels_exist) != channels_needed) {
5797 SetGLError(
5798 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
5799 return;
5800 }
5801
[email protected]34ff8b0c2010-10-01 20:06:025802 ScopedResolvedFrameBufferBinder binder(this);
[email protected]6e288612010-12-21 20:45:035803 gfx::Size size = GetBoundReadFrameBufferSize();
5804 GLint copyX = 0;
5805 GLint copyY = 0;
5806 GLint copyWidth = 0;
5807 GLint copyHeight = 0;
5808 Clip(x, width, size.width(), &copyX, &copyWidth);
5809 Clip(y, height, size.height(), &copyY, &copyHeight);
5810 if (copyX != x ||
5811 copyY != y ||
5812 copyWidth != width ||
5813 copyHeight != height) {
5814 // some part was clipped so clear the texture.
5815 uint32 pixels_size = 0;
5816 if (!GLES2Util::ComputeImageDataSize(
5817 width, height, format, type, unpack_alignment_, &pixels_size)) {
5818 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
5819 return;
5820 }
5821 scoped_array<char> zero(new char[pixels_size]);
5822 memset(zero.get(), 0, pixels_size);
5823 glTexSubImage2D(
5824 target, level, xoffset, yoffset, width, height,
5825 format, type, zero.get());
5826 }
5827 if (copyHeight > 0 && copyWidth > 0) {
5828 GLint dx = copyX - x;
5829 GLint dy = copyY - y;
5830 GLint destX = xoffset + dx;
5831 GLint destY = yoffset + dy;
5832 glCopyTexSubImage2D(target, level,
5833 destX, destY, copyX, copyY,
5834 copyWidth, copyHeight);
5835 }
[email protected]cadde4a2010-07-31 17:10:435836}
5837
5838void GLES2DecoderImpl::DoTexSubImage2D(
5839 GLenum target,
5840 GLint level,
5841 GLint xoffset,
5842 GLint yoffset,
5843 GLsizei width,
5844 GLsizei height,
5845 GLenum format,
5846 GLenum type,
5847 const void * data) {
5848 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5849 if (!info) {
5850 SetGLError(GL_INVALID_OPERATION,
5851 "glTexSubImage2D: unknown texture for target");
5852 return;
5853 }
[email protected]df6cf1ad2011-01-29 01:20:525854 GLenum current_type = 0;
5855 GLenum internal_format = 0;
5856 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
5857 SetGLError(
5858 GL_INVALID_OPERATION,
5859 "glTexSubImage2D: level does not exist.");
5860 return;
5861 }
5862 if (format != internal_format) {
5863 SetGLError(GL_INVALID_OPERATION,
5864 "glTexSubImage2D: format does not match internal format.");
5865 return;
5866 }
5867 if (type != current_type) {
5868 SetGLError(GL_INVALID_OPERATION,
5869 "glTexSubImage2D: type does not match type of texture.");
5870 return;
5871 }
5872
[email protected]cadde4a2010-07-31 17:10:435873 if (!info->ValidForTexture(
5874 target, level, xoffset, yoffset, width, height, format, type)) {
5875 SetGLError(GL_INVALID_VALUE,
5876 "glTexSubImage2D: bad dimensions.");
5877 return;
5878 }
5879 glTexSubImage2D(
5880 target, level, xoffset, yoffset, width, height, format, type, data);
5881}
5882
[email protected]f7a64ee2010-02-01 22:24:145883error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:195884 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:365885 GLuint index = static_cast<GLuint>(c.index);
5886 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:255887 typedef gles2::GetVertexAttribPointerv::Result Result;
5888 Result* result = GetSharedMemoryAs<Result*>(
5889 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:365890 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:145891 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:365892 }
[email protected]07d0cc82010-02-17 04:51:405893 // Check that the client initialized the result.
5894 if (result->size != 0) {
5895 return error::kInvalidArguments;
5896 }
[email protected]9438b012010-06-15 22:55:055897 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295898 SetGLError(GL_INVALID_ENUM,
5899 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145900 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:365901 }
[email protected]3916c97e2010-02-25 03:20:505902 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:295903 SetGLError(GL_INVALID_VALUE,
5904 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:145905 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:365906 }
[email protected]0bfd9882010-02-05 23:02:255907 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:085908 *result->GetData() =
5909 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:145910 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325911}
5912
[email protected]f7b85372010-02-03 01:11:375913bool GLES2DecoderImpl::GetUniformSetup(
5914 GLuint program, GLint location,
5915 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:105916 error::Error* error, GLuint* service_id, void** result_pointer,
5917 GLenum* result_type) {
5918 DCHECK(error);
5919 DCHECK(service_id);
5920 DCHECK(result_pointer);
5921 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:375922 *error = error::kNoError;
5923 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:255924 SizedResult<GLint>* result;
5925 result = GetSharedMemoryAs<SizedResult<GLint>*>(
5926 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
5927 if (!result) {
[email protected]f7b85372010-02-03 01:11:375928 *error = error::kOutOfBounds;
5929 return false;
5930 }
[email protected]0bfd9882010-02-05 23:02:255931 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:375932 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:255933 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:585934 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5935 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:375936 if (!info) {
[email protected]ae51d192010-04-27 00:48:035937 return false;
5938 }
5939 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:375940 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:295941 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:375942 return false;
5943 }
[email protected]ae51d192010-04-27 00:48:035944 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:365945 GLint array_index = -1;
5946 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
5947 info->GetUniformInfoByLocation(location, &array_index);
5948 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:375949 // No such location.
[email protected]8eee29c2010-04-29 03:38:295950 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:375951 return false;
5952 }
[email protected]43c2f1f2011-03-25 18:35:365953 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:505954 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:375955 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:295956 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:375957 return false;
5958 }
[email protected]0bfd9882010-02-05 23:02:255959 result = GetSharedMemoryAs<SizedResult<GLint>*>(
5960 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
5961 if (!result) {
[email protected]f7b85372010-02-03 01:11:375962 *error = error::kOutOfBounds;
5963 return false;
5964 }
[email protected]0bfd9882010-02-05 23:02:255965 result->size = size;
[email protected]939e7362010-05-13 20:49:105966 *result_type = type;
[email protected]f7b85372010-02-03 01:11:375967 return true;
5968}
5969
[email protected]f7a64ee2010-02-01 22:24:145970error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:195971 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:375972 GLuint program = c.program;
5973 GLint location = c.location;
5974 GLuint service_id;
[email protected]939e7362010-05-13 20:49:105975 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:375976 Error error;
[email protected]0bfd9882010-02-05 23:02:255977 void* result;
[email protected]f7b85372010-02-03 01:11:375978 if (GetUniformSetup(
5979 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:105980 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:255981 glGetUniformiv(
5982 service_id, location,
5983 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:375984 }
5985 return error;
[email protected]96449d2c2009-11-25 00:01:325986}
5987
[email protected]f7a64ee2010-02-01 22:24:145988error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:195989 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:375990 GLuint program = c.program;
5991 GLint location = c.location;
5992 GLuint service_id;
5993 Error error;
[email protected]0bfd9882010-02-05 23:02:255994 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:105995 Result* result;
5996 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:375997 if (GetUniformSetup(
5998 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:105999 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
6000 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
6001 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
6002 GLsizei num_values = result->GetNumResults();
6003 scoped_array<GLint> temp(new GLint[num_values]);
6004 glGetUniformiv(service_id, location, temp.get());
6005 GLfloat* dst = result->GetData();
6006 for (GLsizei ii = 0; ii < num_values; ++ii) {
6007 dst[ii] = (temp[ii] != 0);
6008 }
6009 } else {
6010 glGetUniformfv(service_id, location, result->GetData());
6011 }
[email protected]f7b85372010-02-03 01:11:376012 }
6013 return error;
[email protected]96449d2c2009-11-25 00:01:326014}
6015
[email protected]f7a64ee2010-02-01 22:24:146016error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:196017 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:256018 GLenum shader_type = static_cast<GLenum>(c.shadertype);
6019 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
6020 typedef gles2::GetShaderPrecisionFormat::Result Result;
6021 Result* result = GetSharedMemoryAs<Result*>(
6022 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6023 if (!result) {
6024 return error::kOutOfBounds;
6025 }
[email protected]07d0cc82010-02-17 04:51:406026 // Check that the client initialized the result.
6027 if (result->success != 0) {
6028 return error::kInvalidArguments;
6029 }
[email protected]9438b012010-06-15 22:55:056030 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:296031 SetGLError(GL_INVALID_ENUM,
6032 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
6033 return error::kNoError;
6034 }
[email protected]9438b012010-06-15 22:55:056035 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:296036 SetGLError(GL_INVALID_ENUM,
6037 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
6038 return error::kNoError;
6039 }
6040
6041 result->success = 1; // true
6042 switch (precision_type) {
6043 case GL_LOW_INT:
6044 case GL_MEDIUM_INT:
6045 case GL_HIGH_INT:
6046 result->min_range = -31;
6047 result->max_range = 31;
6048 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:106049 break;
[email protected]8eee29c2010-04-29 03:38:296050 case GL_LOW_FLOAT:
6051 case GL_MEDIUM_FLOAT:
6052 case GL_HIGH_FLOAT:
6053 result->min_range = -62;
6054 result->max_range = 62;
6055 result->precision = -16;
6056 break;
6057 default:
6058 NOTREACHED();
6059 break;
[email protected]0bfd9882010-02-05 23:02:256060 }
[email protected]f7a64ee2010-02-01 22:24:146061 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326062}
6063
[email protected]f7a64ee2010-02-01 22:24:146064error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:196065 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:256066 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:586067 GLuint program = static_cast<GLuint>(c.program);
6068 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6069 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:036070 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256071 return error::kNoError;
6072 }
6073 typedef gles2::GetAttachedShaders::Result Result;
6074 uint32 max_count = Result::ComputeMaxResults(result_size);
6075 Result* result = GetSharedMemoryAs<Result*>(
6076 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
6077 if (!result) {
6078 return error::kOutOfBounds;
6079 }
[email protected]07d0cc82010-02-17 04:51:406080 // Check that the client initialized the result.
6081 if (result->size != 0) {
6082 return error::kInvalidArguments;
6083 }
[email protected]0bfd9882010-02-05 23:02:256084 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:036085 glGetAttachedShaders(
6086 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:256087 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:036088 if (!shader_manager()->GetClientId(result->GetData()[ii],
6089 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:256090 NOTREACHED();
6091 return error::kGenericError;
6092 }
6093 }
6094 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:146095 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326096}
6097
[email protected]f7a64ee2010-02-01 22:24:146098error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:196099 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:256100 GLuint program = c.program;
6101 GLuint index = c.index;
6102 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256103 typedef gles2::GetActiveUniform::Result Result;
6104 Result* result = GetSharedMemoryAs<Result*>(
6105 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6106 if (!result) {
6107 return error::kOutOfBounds;
6108 }
[email protected]07d0cc82010-02-17 04:51:406109 // Check that the client initialized the result.
6110 if (result->success != 0) {
6111 return error::kInvalidArguments;
6112 }
[email protected]6b8cf1a2010-05-06 16:13:586113 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6114 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:036115 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256116 return error::kNoError;
6117 }
6118 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6119 info->GetUniformInfo(index);
6120 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:296121 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:256122 return error::kNoError;
6123 }
6124 result->success = 1; // true.
6125 result->size = uniform_info->size;
6126 result->type = uniform_info->type;
6127 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296128 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146129 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326130}
6131
[email protected]f7a64ee2010-02-01 22:24:146132error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:196133 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:256134 GLuint program = c.program;
6135 GLuint index = c.index;
6136 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256137 typedef gles2::GetActiveAttrib::Result Result;
6138 Result* result = GetSharedMemoryAs<Result*>(
6139 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6140 if (!result) {
6141 return error::kOutOfBounds;
6142 }
[email protected]07d0cc82010-02-17 04:51:406143 // Check that the client initialized the result.
6144 if (result->success != 0) {
6145 return error::kInvalidArguments;
6146 }
[email protected]6b8cf1a2010-05-06 16:13:586147 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6148 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:036149 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256150 return error::kNoError;
6151 }
6152 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
6153 info->GetAttribInfo(index);
6154 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:296155 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:256156 return error::kNoError;
6157 }
6158 result->success = 1; // true.
6159 result->size = attrib_info->size;
6160 result->type = attrib_info->type;
6161 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296162 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146163 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326164}
6165
[email protected]b273e432010-04-12 17:23:586166error::Error GLES2DecoderImpl::HandleShaderBinary(
6167 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
6168#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:296169 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:586170 return error::kNoError;
6171#else
6172 GLsizei n = static_cast<GLsizei>(c.n);
6173 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:296174 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:586175 return error::kNoError;
6176 }
6177 GLsizei length = static_cast<GLsizei>(c.length);
6178 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:296179 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:586180 return error::kNoError;
6181 }
6182 uint32 data_size;
6183 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
6184 return error::kOutOfBounds;
6185 }
6186 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
6187 c.shaders_shm_id, c.shaders_shm_offset, data_size);
6188 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
6189 const void* binary = GetSharedMemoryAs<const void*>(
6190 c.binary_shm_id, c.binary_shm_offset, length);
6191 if (shaders == NULL || binary == NULL) {
6192 return error::kOutOfBounds;
6193 }
6194 scoped_array<GLuint> service_ids(new GLuint[n]);
6195 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:036196 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
6197 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296198 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:586199 return error::kNoError;
6200 }
[email protected]ae51d192010-04-27 00:48:036201 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:586202 }
6203 // TODO(gman): call glShaderBinary
6204 return error::kNoError;
6205#endif
6206}
6207
[email protected]6217d392010-03-25 22:08:356208error::Error GLES2DecoderImpl::HandleSwapBuffers(
6209 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]6217d392010-03-25 22:08:356210 // If offscreen then don't actually SwapBuffers to the display. Just copy
6211 // the rendered frame to another frame buffer.
6212 if (offscreen_target_frame_buffer_.get()) {
6213 ScopedGLErrorSuppressor suppressor(this);
6214
6215 // First check to see if a deferred offscreen render buffer resize is
6216 // pending.
[email protected]d0498742010-09-20 20:27:016217 if (!UpdateOffscreenFrameBufferSize()) {
6218 LOG(ERROR) << "Context lost because reallocation of offscreen FBO "
6219 << "failed.";
[email protected]6217d392010-03-25 22:08:356220 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016221 }
[email protected]6217d392010-03-25 22:08:356222
[email protected]34ff8b0c2010-10-01 20:06:026223 if (IsOffscreenBufferMultisampled()) {
6224 // For multisampled buffers, bind the resolved frame buffer so that
6225 // callbacks can call ReadPixels or CopyTexImage2D.
6226 ScopedResolvedFrameBufferBinder binder(this);
6227 if (swap_buffers_callback_.get()) {
6228 swap_buffers_callback_->Run();
6229 }
[email protected]5d005422011-02-08 01:03:176230 return error::kThrottle;
[email protected]b86b14982010-10-11 18:45:486231 } else {
[email protected]0c8c9d22010-06-25 17:36:396232 ScopedFrameBufferBinder binder(this,
6233 offscreen_target_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:406234
[email protected]b86b14982010-10-11 18:45:486235 if (parent_) {
6236 // Copy the target frame buffer to the saved offscreen texture.
6237 offscreen_saved_color_texture_->Copy(
6238 offscreen_saved_color_texture_->size());
6239
[email protected]a3ded6d2010-10-19 06:44:396240 // Ensure the side effects of the copy are visible to the parent
6241 // context. There is no need to do this for ANGLE because it uses a
6242 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:486243 if (!IsAngle())
6244 glFlush();
6245 }
6246
6247 // Run the callback with |binder| in scope, so that the callback can call
6248 // ReadPixels or CopyTexImage2D.
6249 if (swap_buffers_callback_.get()) {
6250 swap_buffers_callback_->Run();
6251 }
[email protected]5d005422011-02-08 01:03:176252 return error::kThrottle;
[email protected]0c8c9d22010-06-25 17:36:396253 }
[email protected]6217d392010-03-25 22:08:356254 } else {
[email protected]d0498742010-09-20 20:27:016255 if (!context_->SwapBuffers()) {
6256 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:026257 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016258 }
[email protected]6217d392010-03-25 22:08:356259 }
6260
6261 if (swap_buffers_callback_.get()) {
6262 swap_buffers_callback_->Run();
6263 }
6264
[email protected]5d005422011-02-08 01:03:176265 // Do not throttle SwapBuffers by returning kThrottle. The intent of
6266 // throttling the offscreen command buffers to a fixed number of frames
6267 // ahead is to prevent them from rendering faster than they can be
6268 // presented, not to limit the rate at which we present.
6269 //
6270 // This does not hold for ANGLE, possibly because all the GL contexts in a
6271 // share group are actually one D3D device. Found by trial and error.
6272 return IsAngle() ? error::kThrottle : error::kNoError;
[email protected]6217d392010-03-25 22:08:356273}
6274
[email protected]1e6f58d2011-03-24 00:00:406275error::Error GLES2DecoderImpl::HandleSetLatchCHROMIUM(
6276 uint32 immediate_data_size, const gles2::SetLatchCHROMIUM& c) {
[email protected]ce9eea602011-04-12 20:09:576277 // Ensure the side effects of previous commands are visible to other contexts.
6278 // There is no need to do this for ANGLE because it uses a
6279 // single D3D device for all contexts.
6280 if (!IsAngle())
6281 glFlush();
6282
6283 int32 shm_id = gpu::kLatchSharedMemoryId;
[email protected]1e6f58d2011-03-24 00:00:406284 uint32 latch_id = c.latch_id;
6285 uint32 shm_offset = 0;
6286 base::subtle::Atomic32* latch;
6287 if (!SafeMultiplyUint32(latch_id, sizeof(*latch), &shm_offset)) {
6288 return error::kOutOfBounds;
6289 }
6290 latch = GetSharedMemoryAs<base::subtle::Atomic32*>(
6291 shm_id, shm_offset, sizeof(*latch));
6292 if (!latch) {
6293 return error::kOutOfBounds;
6294 }
6295 *latch = 1;
6296 return error::kNoError;
6297}
6298
6299error::Error GLES2DecoderImpl::HandleWaitLatchCHROMIUM(
6300 uint32 immediate_data_size, const gles2::WaitLatchCHROMIUM& c) {
[email protected]ce9eea602011-04-12 20:09:576301 int32 shm_id = gpu::kLatchSharedMemoryId;
[email protected]1e6f58d2011-03-24 00:00:406302 uint32 latch_id = c.latch_id;
6303 uint32 shm_offset = 0;
6304 base::subtle::Atomic32* latch;
6305 if (!SafeMultiplyUint32(latch_id, sizeof(*latch), &shm_offset)) {
6306 return error::kOutOfBounds;
6307 }
6308 latch = GetSharedMemoryAs<base::subtle::Atomic32*>(
6309 shm_id, shm_offset, sizeof(*latch));
6310 if (!latch) {
6311 return error::kOutOfBounds;
6312 }
6313
6314 base::subtle::Atomic32 old =
6315 base::subtle::NoBarrier_CompareAndSwap(latch, 1, 0);
6316 return (old == 0) ? error::kWaiting : error::kNoError;
6317}
6318
[email protected]269200b12010-11-18 22:53:066319error::Error GLES2DecoderImpl::HandleCommandBufferEnableCHROMIUM(
6320 uint32 immediate_data_size, const gles2::CommandBufferEnableCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:186321 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]269200b12010-11-18 22:53:066322 typedef gles2::CommandBufferEnableCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:186323 Result* result = GetSharedMemoryAs<Result*>(
6324 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6325 if (!result) {
6326 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:106327 }
[email protected]b1d2dcb2010-05-17 19:24:186328 // Check that the client initialized the result.
6329 if (*result != 0) {
6330 return error::kInvalidArguments;
6331 }
6332 std::string feature_str;
6333 if (!bucket->GetAsString(&feature_str)) {
6334 return error::kInvalidArguments;
6335 }
6336
6337 // TODO(gman): make this some kind of table to function pointer thingy.
6338 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
6339 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]8fbedc02010-11-18 18:43:406340 } else if (feature_str.compare(PEPPER3D_SUPPORT_FIXED_ATTRIBS) == 0) {
6341 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
6342 // TODO(gman): decide how to remove the need for this const_cast.
6343 // I could make validators_ non const but that seems bad as this is the only
6344 // place it is needed. I could make some special friend class of validators
6345 // just to allow this to set them. That seems silly. I could refactor this
6346 // code to use the extension mechanism or the initialization attributes to
6347 // turn this feature on. Given that the only real point of this is to make
6348 // the conformance tests pass and given that there is lots of real work that
6349 // needs to be done it seems like refactoring for one to one of those
6350 // methods is a very low priority.
6351 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]b1d2dcb2010-05-17 19:24:186352 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
6353 use_shader_translator_ = false;
6354 } else {
6355 return error::kNoError;
6356 }
6357
6358 *result = 1; // true.
6359 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:106360}
6361
[email protected]c2f8c8402010-12-06 18:07:246362error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
6363 uint32 immediate_data_size,
6364 const gles2::GetRequestableExtensionsCHROMIUM& c) {
6365 Bucket* bucket = CreateBucket(c.bucket_id);
6366 scoped_ptr<FeatureInfo> info(new FeatureInfo());
[email protected]c410da802011-03-14 19:17:416367 info->Initialize(disallowed_extensions_, NULL);
[email protected]c2f8c8402010-12-06 18:07:246368 bucket->SetFromString(info->extensions().c_str());
6369 return error::kNoError;
6370}
6371
6372error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
6373 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
6374 Bucket* bucket = GetBucket(c.bucket_id);
6375 std::string feature_str;
6376 if (!bucket->GetAsString(&feature_str)) {
6377 return error::kInvalidArguments;
6378 }
6379
6380 bool std_derivatives_enabled =
6381 feature_info_->feature_flags().oes_standard_derivatives;
6382 bool webglsl_enabled =
6383 feature_info_->feature_flags().chromium_webglsl;
6384
6385 feature_info_->AddFeatures(feature_str.c_str());
6386
6387 // If we just enabled a feature which affects the shader translator,
6388 // we may need to re-initialize it.
6389 if (std_derivatives_enabled !=
6390 feature_info_->feature_flags().oes_standard_derivatives ||
6391 webglsl_enabled !=
6392 feature_info_->feature_flags().chromium_webglsl) {
6393 InitializeShaderTranslator();
6394 }
6395
6396 return error::kNoError;
6397}
6398
[email protected]96449d2c2009-11-25 00:01:326399// Include the auto-generated part of this file. We split this because it means
6400// we can easily edit the non-auto generated parts right here in this file
6401// instead of having to edit some template or the code generator.
6402#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
6403
6404} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:256405} // namespace gpu