blob: 4537212a3c2965e1f7a5668fee1045e59dd79f17 [file] [log] [blame]
[email protected]d366c482010-10-20 00:11:271// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]96449d2c2009-11-25 00:01:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]8a837bb2010-01-05 00:21:245#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
[email protected]74470702010-01-06 18:51:166
7#include <stdio.h>
8
[email protected]1aef98132010-02-23 18:00:079#include <algorithm>
[email protected]f39f4b3f2010-05-12 17:04:0810#include <list>
[email protected]96449d2c2009-11-25 00:01:3211#include <map>
[email protected]f39f4b3f2010-05-12 17:04:0812#include <string>
13#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0614
15#include "app/gfx/gl/gl_context.h"
[email protected]b9363b22010-06-09 22:06:1516#include "app/gfx/gl/gl_implementation.h"
[email protected]00eb49a2010-08-12 20:46:5717#include "base/at_exit.h"
[email protected]2041cf342010-02-19 03:15:5918#include "base/callback.h"
[email protected]96449d2c2009-11-25 00:01:3219#include "base/scoped_ptr.h"
[email protected]6217d392010-03-25 22:08:3520#include "base/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0221#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3222#define GLES2_GPU_SERVICE 1
23#include "gpu/command_buffer/common/gles2_cmd_format.h"
24#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1025#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5026#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3227#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5028#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1129#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5830#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3231#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4632#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4733#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5834#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4735#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4536#include "gpu/command_buffer/service/shader_translator.h"
[email protected]a93bb842010-02-16 23:03:4737#include "gpu/command_buffer/service/texture_manager.h"
[email protected]4e8a5b122010-05-08 22:00:1038#include "gpu/GLES2/gles2_command_buffer.h"
[email protected]de17df392010-04-23 21:09:4139
[email protected]6217d392010-03-25 22:08:3540#if !defined(GL_DEPTH24_STENCIL8)
41#define GL_DEPTH24_STENCIL8 0x88F0
42#endif
43
[email protected]a7a27ace2009-12-12 00:11:2544namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3245namespace gles2 {
46
[email protected]6217d392010-03-25 22:08:3547class GLES2DecoderImpl;
48
[email protected]07f54fcc2009-12-22 02:46:3049// Check that certain assumptions the code makes are true. There are places in
50// the code where shared memory is passed direclty to GL. Example, glUniformiv,
51// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
52// a few others) are 32bits. If they are not 32bits the code will have to change
53// to call those GL functions with service side memory and then copy the results
54// to shared memory, converting the sizes.
55COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
56 GLint_not_same_size_as_uint32);
57COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
58 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3759COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
60 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3061
[email protected]43f28f832010-02-03 02:28:4862// TODO(kbr): the use of this anonymous namespace core dumps the
63// linker on Mac OS X 10.6 when the symbol ordering file is used
64// namespace {
[email protected]96449d2c2009-11-25 00:01:3265
66// Returns the address of the first byte after a struct.
67template <typename T>
68const void* AddressAfterStruct(const T& pod) {
69 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
70}
71
[email protected]07f54fcc2009-12-22 02:46:3072// Returns the address of the frst byte after the struct or NULL if size >
73// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3274template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3075RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
76 uint32 size,
77 uint32 immediate_data_size) {
78 return (size <= immediate_data_size) ?
79 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
80 NULL;
[email protected]96449d2c2009-11-25 00:01:3281}
82
[email protected]07f54fcc2009-12-22 02:46:3083// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1884bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3285 GLuint count,
86 size_t size,
[email protected]a76b0052010-03-05 00:33:1887 unsigned int elements_per_unit,
88 uint32* dst) {
89 uint32 value;
90 if (!SafeMultiplyUint32(count, size, &value)) {
91 return false;
92 }
93 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
94 return false;
95 }
96 *dst = value;
97 return true;
[email protected]96449d2c2009-11-25 00:01:3298}
99
100// A struct to hold info about each command.
101struct CommandInfo {
102 int arg_flags; // How to handle the arguments for this command
103 int arg_count; // How many arguments are expected for this command.
104};
105
106// A table of CommandInfo for all the commands.
107const CommandInfo g_command_info[] = {
108 #define GLES2_CMD_OP(name) { \
109 name::kArgFlags, \
110 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
111
112 GLES2_COMMAND_LIST(GLES2_CMD_OP)
113
114 #undef GLES2_CMD_OP
115};
116
[email protected]34ff8b0c2010-10-01 20:06:02117static bool IsAngle() {
118#if defined(OS_WIN)
119 return gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
120#else
121 return false;
122#endif
123}
124
[email protected]6217d392010-03-25 22:08:35125// This class prevents any GL errors that occur when it is in scope from
126// being reported to the client.
127class ScopedGLErrorSuppressor {
128 public:
129 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
130 ~ScopedGLErrorSuppressor();
131 private:
132 GLES2DecoderImpl* decoder_;
133 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
134};
135
136// Temporarily changes a decoder's bound 2D texture and restore it when this
137// object goes out of scope. Also temporarily switches to using active texture
138// unit zero in case the client has changed that to something invalid.
139class ScopedTexture2DBinder {
140 public:
141 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
142 ~ScopedTexture2DBinder();
143
144 private:
145 GLES2DecoderImpl* decoder_;
146 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
147};
148
149// Temporarily changes a decoder's bound render buffer and restore it when this
150// object goes out of scope.
151class ScopedRenderBufferBinder {
152 public:
153 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
154 ~ScopedRenderBufferBinder();
155
156 private:
157 GLES2DecoderImpl* decoder_;
158 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
159};
160
161// Temporarily changes a decoder's bound frame buffer and restore it when this
162// object goes out of scope.
163class ScopedFrameBufferBinder {
164 public:
165 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
166 ~ScopedFrameBufferBinder();
167
168 private:
169 GLES2DecoderImpl* decoder_;
170 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
171};
172
[email protected]34ff8b0c2010-10-01 20:06:02173// Temporarily changes a decoder's bound frame buffer to a resolved version of
174// the multisampled offscreen render buffer if and only if that buffer is
175// currently bound and is multisampled.
176class ScopedResolvedFrameBufferBinder {
177 public:
178 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder);
179 ~ScopedResolvedFrameBufferBinder();
180
181 private:
182 GLES2DecoderImpl* decoder_;
183 bool resolve_and_bind_;
184 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
185};
186
[email protected]6217d392010-03-25 22:08:35187// Encapsulates an OpenGL texture.
188class Texture {
189 public:
190 explicit Texture(GLES2DecoderImpl* decoder);
191 ~Texture();
192
193 // Create a new render texture.
194 void Create();
195
196 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02197 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35198
199 // Copy the contents of the currently bound frame buffer.
200 void Copy(const gfx::Size& size);
201
202 // Destroy the render texture. This must be explicitly called before
203 // destroying this object.
204 void Destroy();
205
[email protected]97872062010-11-03 19:07:05206 // Invalidate the texture. This can be used when a context is lost and it is
207 // not possible to make it current in order to free the resource.
208 void Invalidate();
209
[email protected]6217d392010-03-25 22:08:35210 GLuint id() const {
211 return id_;
212 }
213
[email protected]d37231fa2010-04-09 21:16:02214 gfx::Size size() const {
215 return size_;
216 }
217
[email protected]6217d392010-03-25 22:08:35218 private:
219 GLES2DecoderImpl* decoder_;
220 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02221 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35222 DISALLOW_COPY_AND_ASSIGN(Texture);
223};
224
225// Encapsulates an OpenGL render buffer of any format.
226class RenderBuffer {
227 public:
228 explicit RenderBuffer(GLES2DecoderImpl* decoder);
229 ~RenderBuffer();
230
231 // Create a new render buffer.
232 void Create();
233
234 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02235 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35236
237 // Destroy the render buffer. This must be explicitly called before destroying
238 // this object.
239 void Destroy();
240
[email protected]97872062010-11-03 19:07:05241 // Invalidate the render buffer. This can be used when a context is lost and
242 // it is not possible to make it current in order to free the resource.
243 void Invalidate();
244
[email protected]6217d392010-03-25 22:08:35245 GLuint id() const {
246 return id_;
247 }
248
249 private:
250 GLES2DecoderImpl* decoder_;
251 GLuint id_;
252 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
253};
254
255// Encapsulates an OpenGL frame buffer.
256class FrameBuffer {
257 public:
258 explicit FrameBuffer(GLES2DecoderImpl* decoder);
259 ~FrameBuffer();
260
261 // Create a new frame buffer.
262 void Create();
263
264 // Attach a color render buffer to a frame buffer.
265 void AttachRenderTexture(Texture* texture);
266
[email protected]b9363b22010-06-09 22:06:15267 // Attach a render buffer to a frame buffer. Note that this unbinds any
268 // currently bound frame buffer.
269 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35270
271 // Clear the given attached buffers.
272 void Clear(GLbitfield buffers);
273
274 // Destroy the frame buffer. This must be explicitly called before destroying
275 // this object.
276 void Destroy();
277
[email protected]97872062010-11-03 19:07:05278 // Invalidate the frame buffer. This can be used when a context is lost and it
279 // is not possible to make it current in order to free the resource.
280 void Invalidate();
281
[email protected]6217d392010-03-25 22:08:35282 // See glCheckFramebufferStatusEXT.
283 GLenum CheckStatus();
284
285 GLuint id() const {
286 return id_;
287 }
288
289 private:
290 GLES2DecoderImpl* decoder_;
291 GLuint id_;
292 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
293};
[email protected]34ff8b0c2010-10-01 20:06:02294
295class ContextCreationAttribParser {
296 public:
297 ContextCreationAttribParser();
298 bool Parse(const std::vector<int32>& attribs);
299
300 // -1 if invalid or unspecified.
301 int32 alpha_size_;
302 int32 blue_size_;
303 int32 green_size_;
304 int32 red_size_;
305 int32 depth_size_;
306 int32 stencil_size_;
307 int32 samples_;
308 int32 sample_buffers_;
309};
310
311ContextCreationAttribParser::ContextCreationAttribParser()
312 : alpha_size_(-1),
313 blue_size_(-1),
314 green_size_(-1),
315 red_size_(-1),
316 depth_size_(-1),
317 stencil_size_(-1),
318 samples_(-1),
319 sample_buffers_(-1) {
320}
321
322bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
323 // From <EGL/egl.h>.
324 const int32 EGL_ALPHA_SIZE = 0x3021;
325 const int32 EGL_BLUE_SIZE = 0x3022;
326 const int32 EGL_GREEN_SIZE = 0x3023;
327 const int32 EGL_RED_SIZE = 0x3024;
328 const int32 EGL_DEPTH_SIZE = 0x3025;
329 const int32 EGL_STENCIL_SIZE = 0x3026;
330 const int32 EGL_SAMPLES = 0x3031;
331 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
332 const int32 EGL_NONE = 0x3038;
333
334 for (size_t i = 0; i < attribs.size(); i += 2) {
335 const int32 attrib = attribs[i];
336 if (i + 1 >= attribs.size()) {
337 if (attrib == EGL_NONE)
338 return true;
339
340 DLOG(ERROR) << "Missing value after context creation attribute: "
341 << attrib;
342 return false;
343 }
344
345 const int32 value = attribs[i+1];
346 switch (attrib) {
347 case EGL_ALPHA_SIZE:
348 alpha_size_ = value;
349 break;
350 case EGL_BLUE_SIZE:
351 blue_size_ = value;
352 break;
353 case EGL_GREEN_SIZE:
354 green_size_ = value;
355 break;
356 case EGL_RED_SIZE:
357 red_size_ = value;
358 break;
359 case EGL_DEPTH_SIZE:
360 depth_size_ = value;
361 break;
362 case EGL_STENCIL_SIZE:
363 stencil_size_ = value;
364 break;
365 case EGL_SAMPLES:
366 samples_ = value;
367 break;
368 case EGL_SAMPLE_BUFFERS:
369 sample_buffers_ = value;
370 break;
371 case EGL_NONE:
372 // Terminate list, even if more attributes.
373 return true;
374 default:
375 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
376 return false;
377 }
378 }
379
380 return true;
381}
382
[email protected]43f28f832010-02-03 02:28:48383// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32384
[email protected]ddb1e5a2010-12-13 20:10:45385bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
386 uint32* service_texture_id) {
387 return false;
388}
389
[email protected]a3ded6d2010-10-19 06:44:39390GLES2Decoder::GLES2Decoder()
391 : debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32392}
393
[email protected]3916c97e2010-02-25 03:20:50394GLES2Decoder::~GLES2Decoder() {
395}
396
[email protected]f39f4b3f2010-05-12 17:04:08397class VertexAttribManager {
[email protected]96449d2c2009-11-25 00:01:32398 public:
[email protected]07f54fcc2009-12-22 02:46:30399 // Info about Vertex Attributes. This is used to track what the user currently
400 // has bound on each Vertex Attribute so that checking can be done at
401 // glDrawXXX time.
402 class VertexAttribInfo {
403 public:
[email protected]f39f4b3f2010-05-12 17:04:08404 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
[email protected]b1122982010-05-17 23:04:24405 struct Vec4 {
406 float v[4];
407 };
[email protected]f39f4b3f2010-05-12 17:04:08408
[email protected]07f54fcc2009-12-22 02:46:30409 VertexAttribInfo()
[email protected]f39f4b3f2010-05-12 17:04:08410 : index_(0),
411 enabled_(false),
412 size_(4),
413 type_(GL_FLOAT),
[email protected]07f54fcc2009-12-22 02:46:30414 offset_(0),
[email protected]b1122982010-05-17 23:04:24415 normalized_(GL_FALSE),
416 gl_stride_(0),
[email protected]f39f4b3f2010-05-12 17:04:08417 real_stride_(16),
418 list_(NULL) {
[email protected]b1122982010-05-17 23:04:24419 value_.v[0] = 0.0f;
420 value_.v[1] = 0.0f;
421 value_.v[2] = 0.0f;
422 value_.v[3] = 1.0f;
[email protected]07f54fcc2009-12-22 02:46:30423 }
[email protected]3916c97e2010-02-25 03:20:50424
[email protected]07f54fcc2009-12-22 02:46:30425 // Returns true if this VertexAttrib can access index.
[email protected]f39f4b3f2010-05-12 17:04:08426 bool CanAccess(GLuint index) const;
[email protected]07f54fcc2009-12-22 02:46:30427
[email protected]3916c97e2010-02-25 03:20:50428 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30429 return buffer_;
430 }
431
[email protected]8bf5a3e2010-01-29 04:21:36432 GLsizei offset() const {
433 return offset_;
434 }
435
[email protected]f39f4b3f2010-05-12 17:04:08436 GLuint index() const {
437 return index_;
438 }
439
[email protected]b1122982010-05-17 23:04:24440 GLint size() const {
441 return size_;
442 }
443
444 GLenum type() const {
445 return type_;
446 }
447
448 GLboolean normalized() const {
449 return normalized_;
450 }
451
452 GLsizei gl_stride() const {
453 return gl_stride_;
454 }
455
[email protected]f39f4b3f2010-05-12 17:04:08456 bool enabled() const {
457 return enabled_;
458 }
459
[email protected]b1122982010-05-17 23:04:24460 void set_value(const Vec4& value) {
461 value_ = value;
462 }
463
464 const Vec4& value() const {
465 return value_;
466 }
467
[email protected]07f54fcc2009-12-22 02:46:30468 private:
[email protected]f39f4b3f2010-05-12 17:04:08469 friend class VertexAttribManager;
470
471 void set_enabled(bool enabled) {
472 enabled_ = enabled;
473 }
474
475 void set_index(GLuint index) {
476 index_ = index;
477 }
478
479 void SetList(VertexAttribInfoList* new_list) {
480 DCHECK(new_list);
481
482 if (list_) {
483 list_->erase(it_);
484 }
485
486 it_ = new_list->insert(new_list->end(), this);
487 list_ = new_list;
488 }
489
[email protected]8fbedc02010-11-18 18:43:40490 void SetInfo(
491 BufferManager::BufferInfo* buffer,
492 GLint size,
493 GLenum type,
494 GLboolean normalized,
495 GLsizei gl_stride,
496 GLsizei real_stride,
497 GLsizei offset) {
498 DCHECK_GT(real_stride, 0);
499 buffer_ = buffer;
500 size_ = size;
501 type_ = type;
502 normalized_ = normalized;
503 gl_stride_ = gl_stride;
504 real_stride_ = real_stride;
505 offset_ = offset;
506 }
507
[email protected]f39f4b3f2010-05-12 17:04:08508 // The index of this attrib.
509 GLuint index_;
510
[email protected]07f54fcc2009-12-22 02:46:30511 // Whether or not this attribute is enabled.
512 bool enabled_;
513
514 // number of components (1, 2, 3, 4)
515 GLint size_;
516
517 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
518 GLenum type_;
519
520 // The offset into the buffer.
521 GLsizei offset_;
522
[email protected]b1122982010-05-17 23:04:24523 GLboolean normalized_;
524
525 // The stride passed to glVertexAttribPointer.
526 GLsizei gl_stride_;
527
[email protected]07f54fcc2009-12-22 02:46:30528 // The stride that will be used to access the buffer. This is the actual
529 // stide, NOT the GL bogus stride. In other words there is never a stride
530 // of 0.
531 GLsizei real_stride_;
532
[email protected]b1122982010-05-17 23:04:24533 // The current value of the attrib.
534 Vec4 value_;
535
[email protected]3916c97e2010-02-25 03:20:50536 // The buffer bound to this attribute.
537 BufferManager::BufferInfo::Ref buffer_;
[email protected]f39f4b3f2010-05-12 17:04:08538
539 // List this info is on.
540 VertexAttribInfoList* list_;
541
542 // Iterator for list this info is on. Enabled/Disabled
543 VertexAttribInfoList::iterator it_;
[email protected]07f54fcc2009-12-22 02:46:30544 };
545
[email protected]f39f4b3f2010-05-12 17:04:08546 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
547
548 VertexAttribManager()
[email protected]8fbedc02010-11-18 18:43:40549 : max_vertex_attribs_(0),
550 num_fixed_attribs_(0) {
[email protected]f39f4b3f2010-05-12 17:04:08551 }
552
553 void Initialize(uint32 num_vertex_attribs);
554
555 bool Enable(GLuint index, bool enable);
556
[email protected]8fbedc02010-11-18 18:43:40557 bool HaveFixedAttribs() const {
558 return num_fixed_attribs_ != 0;
559 }
560
[email protected]f39f4b3f2010-05-12 17:04:08561 const VertexAttribInfoList& GetEnabledVertexAttribInfos() const {
562 return enabled_vertex_attribs_;
563 }
564
565 VertexAttribInfo* GetVertexAttribInfo(GLuint index) {
[email protected]b1122982010-05-17 23:04:24566 if (index < max_vertex_attribs_) {
567 return &vertex_attrib_infos_[index];
568 }
569 return NULL;
[email protected]f39f4b3f2010-05-12 17:04:08570 }
571
[email protected]8fbedc02010-11-18 18:43:40572 void SetAttribInfo(
573 GLuint index,
574 BufferManager::BufferInfo* buffer,
575 GLint size,
576 GLenum type,
577 GLboolean normalized,
578 GLsizei gl_stride,
579 GLsizei real_stride,
580 GLsizei offset) {
581 VertexAttribInfo* info = GetVertexAttribInfo(index);
582 if (info) {
583 if (info->type() == GL_FIXED) {
584 --num_fixed_attribs_;
585 }
586 if (type == GL_FIXED) {
587 ++num_fixed_attribs_;
588 }
589 info->SetInfo(
590 buffer, size, type, normalized, gl_stride, real_stride, offset);
591 }
592 }
593
594
[email protected]f39f4b3f2010-05-12 17:04:08595 private:
596 uint32 max_vertex_attribs_;
597
[email protected]8fbedc02010-11-18 18:43:40598 // number of attribs using type GL_FIXED.
599 int num_fixed_attribs_;
600
[email protected]f39f4b3f2010-05-12 17:04:08601 // Info for each vertex attribute saved so we can check at glDrawXXX time
602 // if it is safe to draw.
603 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
604
605 // Lists for which vertex attribs are enabled, disabled.
606 VertexAttribInfoList enabled_vertex_attribs_;
607 VertexAttribInfoList disabled_vertex_attribs_;
608};
609
610bool VertexAttribManager::VertexAttribInfo::CanAccess(GLuint index) const {
611 if (!enabled_) {
612 return true;
613 }
614
615 if (!buffer_ || buffer_->IsDeleted()) {
616 return false;
617 }
618
619 // The number of elements that can be accessed.
620 GLsizeiptr buffer_size = buffer_->size();
621 if (offset_ > buffer_size || real_stride_ == 0) {
622 return false;
623 }
624
625 uint32 usable_size = buffer_size - offset_;
626 GLuint num_elements = usable_size / real_stride_ +
627 ((usable_size % real_stride_) >=
628 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
629 return index < num_elements;
630}
631
632
633void VertexAttribManager::Initialize(uint32 max_vertex_attribs) {
634 max_vertex_attribs_ = max_vertex_attribs;
635 vertex_attrib_infos_.reset(
636 new VertexAttribInfo[max_vertex_attribs]);
637 for (uint32 vv = 0; vv < max_vertex_attribs; ++vv) {
638 vertex_attrib_infos_[vv].set_index(vv);
639 vertex_attrib_infos_[vv].SetList(&disabled_vertex_attribs_);
640 }
641}
642
643bool VertexAttribManager::Enable(GLuint index, bool enable) {
644 if (index >= max_vertex_attribs_) {
645 return false;
646 }
647 VertexAttribInfo& info = vertex_attrib_infos_[index];
648 if (info.enabled() != enable) {
649 info.set_enabled(enable);
650 info.SetList(enable ? &enabled_vertex_attribs_ : &disabled_vertex_attribs_);
651 }
652 return true;
653}
654
655// This class implements GLES2Decoder so we don't have to expose all the GLES2
656// cmd stuff to outside this class.
657class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
658 public GLES2Decoder {
659 public:
660 explicit GLES2DecoderImpl(ContextGroup* group);
661
[email protected]96449d2c2009-11-25 00:01:32662 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14663 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50664 unsigned int arg_count,
665 const void* args);
[email protected]96449d2c2009-11-25 00:01:32666
667 // Overridden from AsyncAPIInterface.
668 virtual const char* GetCommandName(unsigned int command_id) const;
669
670 // Overridden from GLES2Decoder.
[email protected]5a6db6c2010-04-22 18:32:06671 virtual bool Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:35672 const gfx::Size& size,
[email protected]a3ded6d2010-10-19 06:44:39673 const char* allowed_extensions,
[email protected]34ff8b0c2010-10-01 20:06:02674 const std::vector<int32>& attribs,
[email protected]d37231fa2010-04-09 21:16:02675 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35676 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32677 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35678 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]c71caa82010-06-02 23:25:45679 virtual bool UpdateOffscreenFrameBufferSize();
[email protected]eb54a562010-01-20 21:55:18680 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55681 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30682 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39683 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48684
[email protected]7ff86b92010-11-25 17:50:00685 virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
[email protected]43f28f832010-02-03 02:28:48686 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
[email protected]1318e922010-09-17 22:03:16687 virtual bool GetServiceTextureId(uint32 client_texture_id,
688 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48689
[email protected]8e3e0662010-08-23 18:46:30690 // Restores the current state to the user's settings.
691 void RestoreCurrentFramebufferBindings();
692 void RestoreCurrentRenderbufferBindings();
693 void RestoreCurrentTexture2DBindings();
694
[email protected]96449d2c2009-11-25 00:01:32695 private:
[email protected]6217d392010-03-25 22:08:35696 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02697 friend class ScopedResolvedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35698 friend class RenderBuffer;
699 friend class FrameBuffer;
700
[email protected]3916c97e2010-02-25 03:20:50701 // State associated with each texture unit.
702 struct TextureUnit {
703 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
704
705 // The last target that was bound to this texture unit.
706 GLenum bind_target;
707
708 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
709 TextureManager::TextureInfo::Ref bound_texture_2d;
710
711 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
712 // glBindTexture
713 TextureManager::TextureInfo::Ref bound_texture_cube_map;
714 };
715
[email protected]c2f8c8402010-12-06 18:07:24716 // Initialize or re-initialize the shader translator.
717 bool InitializeShaderTranslator();
718
[email protected]ae51d192010-04-27 00:48:03719 // Helpers for the glGen and glDelete functions.
720 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
721 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
722 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
723 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
724 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
725 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
726 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
727 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47728
[email protected]3916c97e2010-02-25 03:20:50729 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50730 BufferManager* buffer_manager() {
731 return group_->buffer_manager();
732 }
733
[email protected]a25fa872010-03-25 02:57:58734 RenderbufferManager* renderbuffer_manager() {
735 return group_->renderbuffer_manager();
736 }
737
738 FramebufferManager* framebuffer_manager() {
739 return group_->framebuffer_manager();
740 }
741
[email protected]3916c97e2010-02-25 03:20:50742 ProgramManager* program_manager() {
743 return group_->program_manager();
744 }
745
746 ShaderManager* shader_manager() {
747 return group_->shader_manager();
748 }
749
750 TextureManager* texture_manager() {
751 return group_->texture_manager();
752 }
753
[email protected]34ff8b0c2010-10-01 20:06:02754 bool IsOffscreenBufferMultisampled() const {
755 return offscreen_target_samples_ > 1;
756 }
757
[email protected]a93bb842010-02-16 23:03:47758 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03759 TextureManager::TextureInfo* CreateTextureInfo(
760 GLuint client_id, GLuint service_id) {
[email protected]915a59a12010-09-30 21:29:11761 return texture_manager()->CreateTextureInfo(
762 feature_info_, client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47763 }
764
765 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03766 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50767 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03768 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50769 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47770 }
771
772 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03773 void RemoveTextureInfo(GLuint client_id) {
[email protected]915a59a12010-09-30 21:29:11774 texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]3916c97e2010-02-25 03:20:50775 }
[email protected]a93bb842010-02-16 23:03:47776
[email protected]d37231fa2010-04-09 21:16:02777 // Get the size (in pixels) of the currently bound frame buffer (either FBO
778 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30779 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02780
[email protected]9edc6b22010-12-23 02:00:26781 // Get the format of the currently bound frame buffer (either FBO or regular
782 // back buffer)
783 GLenum GetBoundReadFrameBufferInternalFormat();
784
[email protected]a93bb842010-02-16 23:03:47785 // Wrapper for CompressedTexImage2D commands.
786 error::Error DoCompressedTexImage2D(
787 GLenum target,
788 GLint level,
789 GLenum internal_format,
790 GLsizei width,
791 GLsizei height,
792 GLint border,
793 GLsizei image_size,
794 const void* data);
795
[email protected]cadde4a2010-07-31 17:10:43796 // Wrapper for CompressedTexSubImage2D.
797 void DoCompressedTexSubImage2D(
798 GLenum target,
799 GLint level,
800 GLint xoffset,
801 GLint yoffset,
802 GLsizei width,
803 GLsizei height,
804 GLenum format,
805 GLsizei imageSize,
806 const void * data);
807
808 // Wrapper for CopyTexImage2D.
809 void DoCopyTexImage2D(
810 GLenum target,
811 GLint level,
812 GLenum internal_format,
813 GLint x,
814 GLint y,
815 GLsizei width,
816 GLsizei height,
817 GLint border);
818
819 // Wrapper for CopyTexSubImage2D.
820 void DoCopyTexSubImage2D(
821 GLenum target,
822 GLint level,
823 GLint xoffset,
824 GLint yoffset,
825 GLint x,
826 GLint y,
827 GLsizei width,
828 GLsizei height);
829
[email protected]a93bb842010-02-16 23:03:47830 // Wrapper for TexImage2D commands.
831 error::Error DoTexImage2D(
832 GLenum target,
833 GLint level,
834 GLenum internal_format,
835 GLsizei width,
836 GLsizei height,
837 GLint border,
838 GLenum format,
839 GLenum type,
840 const void* pixels,
841 uint32 pixels_size);
842
[email protected]cadde4a2010-07-31 17:10:43843 // Wrapper for TexSubImage2D.
844 void DoTexSubImage2D(
845 GLenum target,
846 GLint level,
847 GLint xoffset,
848 GLint yoffset,
849 GLsizei width,
850 GLsizei height,
851 GLenum format,
852 GLenum type,
853 const void * data);
854
[email protected]a93bb842010-02-16 23:03:47855 // Creates a ProgramInfo for the given program.
[email protected]ae51d192010-04-27 00:48:03856 void CreateProgramInfo(GLuint client_id, GLuint service_id) {
857 program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47858 }
859
[email protected]07f54fcc2009-12-22 02:46:30860 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03861 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14862 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46863 }
[email protected]07f54fcc2009-12-22 02:46:30864
[email protected]6b8cf1a2010-05-06 16:13:58865 // Gets the program info for the given program. If it's not a program
866 // generates a GL error. Returns NULL if not program.
867 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
868 GLuint client_id, const char* function_name) {
869 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
870 if (!info) {
871 if (GetShaderInfo(client_id)) {
872 SetGLError(GL_INVALID_OPERATION,
873 (std::string(function_name) +
874 ": shader passed for program").c_str());
875 } else {
876 SetGLError(GL_INVALID_VALUE,
877 (std::string(function_name) + ": unknown program").c_str());
878 }
879 }
880 return info;
881 }
882
883
[email protected]45bf5152010-02-12 00:11:31884 // Creates a ShaderInfo for the given shader.
[email protected]7cea56d92010-04-28 17:21:38885 void CreateShaderInfo(GLuint client_id,
886 GLuint service_id,
887 GLenum shader_type) {
888 shader_manager()->CreateShaderInfo(client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31889 }
890
891 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03892 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14893 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31894 }
895
[email protected]6b8cf1a2010-05-06 16:13:58896 // Gets the shader info for the given shader. If it's not a shader generates a
897 // GL error. Returns NULL if not shader.
898 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
899 GLuint client_id, const char* function_name) {
900 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
901 if (!info) {
902 if (GetProgramInfo(client_id)) {
903 SetGLError(
904 GL_INVALID_OPERATION,
905 (std::string(function_name) +
906 ": program passed for shader").c_str());
907 } else {
908 SetGLError(GL_INVALID_VALUE,
909 (std::string(function_name) + ": unknown shader").c_str());
910 }
911 }
912 return info;
913 }
914
[email protected]a93bb842010-02-16 23:03:47915 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03916 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
917 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47918 }
919
[email protected]07f54fcc2009-12-22 02:46:30920 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03921 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
922 BufferManager::BufferInfo* info =
923 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50924 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46925 }
[email protected]07f54fcc2009-12-22 02:46:30926
[email protected]a93bb842010-02-16 23:03:47927 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
928 // on glDeleteBuffers so we can make sure the user does not try to render
929 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03930 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47931
[email protected]a25fa872010-03-25 02:57:58932 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03933 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
934 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58935 }
936
937 // Gets the framebuffer info for the given framebuffer.
938 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03939 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58940 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03941 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58942 return (info && !info->IsDeleted()) ? info : NULL;
943 }
944
945 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03946 void RemoveFramebufferInfo(GLuint client_id) {
947 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58948 }
949
950 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03951 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
952 return renderbuffer_manager()->CreateRenderbufferInfo(
953 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58954 }
955
956 // Gets the renderbuffer info for the given renderbuffer.
957 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03958 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58959 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03960 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58961 return (info && !info->IsDeleted()) ? info : NULL;
962 }
963
964 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03965 void RemoveRenderbufferInfo(GLuint client_id) {
966 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58967 }
968
[email protected]558847a2010-03-24 07:02:54969 error::Error GetAttribLocationHelper(
970 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
971 const std::string& name_str);
972
973 error::Error GetUniformLocationHelper(
974 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
975 const std::string& name_str);
976
[email protected]3916c97e2010-02-25 03:20:50977 // Helper for glShaderSource.
978 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03979 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30980
[email protected]3a2e7c7b2010-08-06 01:12:28981 // Clears any uncleared render buffers attached to the given frame buffer.
[email protected]8e3e0662010-08-23 18:46:30982 void ClearUnclearedRenderbuffers(
983 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28984
[email protected]c007aa02010-09-02 22:22:40985 // Restore all GL state that affects clearing.
986 void RestoreClearState();
987
[email protected]3a2e7c7b2010-08-06 01:12:28988 // Remembers the state of some capabilities.
989 void SetCapabilityState(GLenum cap, bool enabled);
990
[email protected]939e7362010-05-13 20:49:10991 // Checks if the current program exists and is valid. If not generates the
992 // appropriate GL error. Returns true if the current program is in a usable
993 // state.
994 bool CheckCurrentProgram(const char* function_name);
995
996 // Checks if the current program exists and is valid and that location is not
997 // -1. If the current program is not valid generates the appropriate GL
998 // error. Returns true if the current program is in a usable state and
999 // location is not -1.
1000 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1001
1002 // Gets the type of a uniform for a location in the current program. Sets GL
1003 // errors if the current program is not valid. Returns true if the current
1004 // program is valid and the location exists.
1005 bool GetUniformTypeByLocation(
1006 GLint location, const char* function_name, GLenum* type);
1007
[email protected]b273e432010-04-12 17:23:581008 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1009 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1010
[email protected]96449d2c2009-11-25 00:01:321011 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:031012 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321013
1014 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:031015 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321016
[email protected]3916c97e2010-02-25 03:20:501017 // Wrapper for glActiveTexture
1018 void DoActiveTexture(GLenum texture_unit);
1019
[email protected]ae51d192010-04-27 00:48:031020 // Wrapper for glAttachShader
1021 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1022
[email protected]96449d2c2009-11-25 00:01:321023 // Wrapper for glBindBuffer since we need to track the current targets.
1024 void DoBindBuffer(GLenum target, GLuint buffer);
1025
[email protected]86093972010-03-11 00:13:561026 // Wrapper for glBindFramebuffer since we need to track the current targets.
1027 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1028
1029 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1030 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1031
[email protected]a93bb842010-02-16 23:03:471032 // Wrapper for glBindTexture since we need to track the current targets.
1033 void DoBindTexture(GLenum target, GLuint texture);
1034
[email protected]8e3e0662010-08-23 18:46:301035 // Wrapper for glBlitFramebufferEXT.
1036 void DoBlitFramebufferEXT(
1037 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1038 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1039 GLbitfield mask, GLenum filter);
1040
[email protected]36cef8ce2010-03-16 07:34:451041 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111042 void DoBufferData(
1043 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1044
[email protected]36cef8ce2010-03-16 07:34:451045 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111046 void DoBufferSubData(
1047 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1048
[email protected]36cef8ce2010-03-16 07:34:451049 // Wrapper for glCheckFramebufferStatus
1050 GLenum DoCheckFramebufferStatus(GLenum target);
1051
[email protected]3a2e7c7b2010-08-06 01:12:281052 // Wrappers for clear and mask settings functions.
1053 void DoClearColor(
1054 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1055 void DoClearDepthf(GLclampf depth);
1056 void DoClearStencil(GLint s);
1057 void DoColorMask(
1058 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1059 void DoDepthMask(GLboolean depth);
1060 void DoStencilMask(GLuint mask);
1061 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1062
[email protected]45bf5152010-02-12 00:11:311063 // Wrapper for glCompileShader.
1064 void DoCompileShader(GLuint shader);
1065
[email protected]269200b12010-11-18 22:53:061066 // Helper for DeleteSharedIdsCHROMIUM commands.
1067 void DoDeleteSharedIdsCHROMIUM(
1068 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101069
[email protected]ae51d192010-04-27 00:48:031070 // Wrapper for glDetachShader
1071 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1072
[email protected]07f54fcc2009-12-22 02:46:301073 // Wrapper for glDrawArrays.
1074 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
1075
[email protected]3a2e7c7b2010-08-06 01:12:281076 // Wrapper for glDisable
1077 void DoDisable(GLenum cap);
1078
[email protected]07f54fcc2009-12-22 02:46:301079 // Wrapper for glDisableVertexAttribArray.
1080 void DoDisableVertexAttribArray(GLuint index);
1081
[email protected]3a2e7c7b2010-08-06 01:12:281082 // Wrapper for glEnable
1083 void DoEnable(GLenum cap);
1084
[email protected]07f54fcc2009-12-22 02:46:301085 // Wrapper for glEnableVertexAttribArray.
1086 void DoEnableVertexAttribArray(GLuint index);
1087
[email protected]36cef8ce2010-03-16 07:34:451088 // Wrapper for glFramebufferRenderbufffer.
1089 void DoFramebufferRenderbuffer(
1090 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1091 GLuint renderbuffer);
1092
1093 // Wrapper for glFramebufferTexture2D.
1094 void DoFramebufferTexture2D(
1095 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1096 GLint level);
1097
[email protected]a93bb842010-02-16 23:03:471098 // Wrapper for glGenerateMipmap
1099 void DoGenerateMipmap(GLenum target);
1100
[email protected]269200b12010-11-18 22:53:061101 // Helper for GenSharedIdsCHROMIUM commands.
1102 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101103 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1104
[email protected]b273e432010-04-12 17:23:581105 // Wrapper for DoGetBooleanv.
1106 void DoGetBooleanv(GLenum pname, GLboolean* params);
1107
1108 // Wrapper for DoGetFloatv.
1109 void DoGetFloatv(GLenum pname, GLfloat* params);
1110
[email protected]36cef8ce2010-03-16 07:34:451111 // Wrapper for glGetFramebufferAttachmentParameteriv.
1112 void DoGetFramebufferAttachmentParameteriv(
1113 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1114
[email protected]a0c3e972010-04-21 00:49:131115 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581116 void DoGetIntegerv(GLenum pname, GLint* params);
1117
[email protected]29a9eb52010-04-13 09:04:231118 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061119 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231120 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1121
[email protected]a0c3e972010-04-21 00:49:131122 // Wrapper for glGetProgramiv.
1123 void DoGetProgramiv(
1124 GLuint program_id, GLenum pname, GLint* params);
1125
[email protected]36cef8ce2010-03-16 07:34:451126 // Wrapper for glRenderbufferParameteriv.
1127 void DoGetRenderbufferParameteriv(
1128 GLenum target, GLenum pname, GLint* params);
1129
[email protected]ddd968b82010-03-02 00:44:291130 // Wrapper for glGetShaderiv
1131 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1132
[email protected]b1122982010-05-17 23:04:241133 // Wrappers for glGetVertexAttrib.
1134 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1135 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1136
[email protected]1958e0e2010-04-22 05:17:151137 // Wrappers for glIsXXX functions.
1138 bool DoIsBuffer(GLuint client_id);
1139 bool DoIsFramebuffer(GLuint client_id);
1140 bool DoIsProgram(GLuint client_id);
1141 bool DoIsRenderbuffer(GLuint client_id);
1142 bool DoIsShader(GLuint client_id);
1143 bool DoIsTexture(GLuint client_id);
1144
[email protected]07f54fcc2009-12-22 02:46:301145 // Wrapper for glLinkProgram
1146 void DoLinkProgram(GLuint program);
1147
[email protected]269200b12010-11-18 22:53:061148 // Helper for RegisterSharedIdsCHROMIUM.
1149 void DoRegisterSharedIdsCHROMIUM(
1150 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101151
[email protected]36cef8ce2010-03-16 07:34:451152 // Wrapper for glRenderbufferStorage.
1153 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031154 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451155
[email protected]8e3e0662010-08-23 18:46:301156 // Wrapper for glRenderbufferStorageMultisampleEXT.
1157 void DoRenderbufferStorageMultisample(
1158 GLenum target, GLsizei samples, GLenum internalformat,
1159 GLsizei width, GLsizei height);
1160
[email protected]b273e432010-04-12 17:23:581161 // Wrapper for glReleaseShaderCompiler.
1162 void DoReleaseShaderCompiler() { }
1163
[email protected]3916c97e2010-02-25 03:20:501164 // Wrappers for glTexParameter functions.
1165 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1166 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1167 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1168 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1169
1170 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1171 // spec only these 2 functions can be used to set sampler uniforms.
1172 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101173 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
1174
1175 // Wrappers for glUniformfv because some drivers don't correctly accept
1176 // bool uniforms.
1177 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1178 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1179 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1180 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501181
[email protected]b1122982010-05-17 23:04:241182 // Wrappers for glVertexAttrib??
1183 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1184 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1185 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1186 void DoVertexAttrib4f(
1187 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1188 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1189 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1190 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1191 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1192
[email protected]07f54fcc2009-12-22 02:46:301193 // Wrapper for glUseProgram
1194 void DoUseProgram(GLuint program);
1195
[email protected]ae51d192010-04-27 00:48:031196 // Wrapper for glValidateProgram.
1197 void DoValidateProgram(GLuint program_client_id);
1198
[email protected]269200b12010-11-18 22:53:061199 void DoCopyTextureToParentTextureCHROMIUM(GLuint client_texture_id,
[email protected]c007aa02010-09-02 22:22:401200 GLuint parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:561201
[email protected]43ecf372010-11-16 19:19:391202 void DoResizeCHROMIUM(GLuint width, GLuint height);
1203
[email protected]4e8a5b122010-05-08 22:00:101204 // Gets the number of values that will be returned by glGetXXX. Returns
1205 // false if pname is unknown.
1206 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1207
[email protected]96449d2c2009-11-25 00:01:321208 // Gets the GLError through our wrapper.
1209 GLenum GetGLError();
1210
1211 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:291212 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:321213
[email protected]07f54fcc2009-12-22 02:46:301214 // Copies the real GL errors to the wrapper. This is so we can
1215 // make sure there are no native GL errors before calling some GL function
1216 // so that on return we know any error generated was for that specific
1217 // command.
1218 void CopyRealGLErrorsToWrapper();
1219
[email protected]6217d392010-03-25 22:08:351220 // Clear all real GL errors. This is to prevent the client from seeing any
1221 // errors caused by GL calls that it was not responsible for issuing.
1222 void ClearRealGLErrors();
1223
[email protected]07f54fcc2009-12-22 02:46:301224 // Checks if the current program and vertex attributes are valid for drawing.
1225 bool IsDrawValid(GLuint max_vertex_accessed);
1226
[email protected]b1122982010-05-17 23:04:241227 // Returns true if attrib0 was simulated.
1228 bool SimulateAttrib0(GLuint max_vertex_accessed);
1229 void RestoreStateForSimulatedAttrib0();
1230
[email protected]ef526492010-06-02 23:12:251231 // Returns true if textures were set.
1232 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501233 void RestoreStateForNonRenderableTextures();
1234
[email protected]8fbedc02010-11-18 18:43:401235 // Returns true if GL_FIXED attribs were simulated.
1236 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1237 void RestoreStateForSimulatedFixedAttribs();
1238
[email protected]07f54fcc2009-12-22 02:46:301239 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501240 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301241 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501242 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1243 bound_array_buffer_ : bound_element_array_buffer_;
1244 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301245 }
1246
[email protected]a93bb842010-02-16 23:03:471247 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501248 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1249 TextureUnit& unit = texture_units_[active_texture_unit_];
1250 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471251 switch (target) {
1252 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501253 info = unit.bound_texture_2d;
1254 break;
[email protected]a93bb842010-02-16 23:03:471255 case GL_TEXTURE_CUBE_MAP:
1256 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1257 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1258 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1259 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1260 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1261 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501262 info = unit.bound_texture_cube_map;
1263 break;
[email protected]1aef98132010-02-23 18:00:071264 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1265 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1266 // because |texture_| is used by the FBO rendering mechanism for readback
1267 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471268 default:
1269 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501270 return NULL;
[email protected]a93bb842010-02-16 23:03:471271 }
[email protected]3916c97e2010-02-25 03:20:501272 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471273 }
1274
[email protected]8e3e0662010-08-23 18:46:301275 // Gets the framebuffer info for a particular target.
1276 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1277 GLenum target) {
1278 FramebufferManager::FramebufferInfo* info = NULL;
1279 switch (target) {
1280 case GL_FRAMEBUFFER:
1281 case GL_DRAW_FRAMEBUFFER:
1282 info = bound_draw_framebuffer_;
1283 break;
1284 case GL_READ_FRAMEBUFFER:
1285 info = bound_read_framebuffer_;
1286 break;
1287 default:
1288 NOTREACHED();
1289 break;
1290 }
1291 return (info && !info->IsDeleted()) ? info : NULL;
1292 }
1293
[email protected]f7b85372010-02-03 01:11:371294 // Validates the program and location for a glGetUniform call and returns
1295 // a SizeResult setup to receive the result. Returns true if glGetUniform
1296 // should be called.
1297 bool GetUniformSetup(
1298 GLuint program, GLint location,
1299 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101300 error::Error* error, GLuint* service_id, void** result,
1301 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371302
[email protected]96449d2c2009-11-25 00:01:321303 // Generate a member function prototype for each command in an automated and
1304 // typesafe way.
1305 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141306 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191307 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321308 const gles2::name& args); \
1309
1310 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1311
1312 #undef GLES2_CMD_OP
1313
[email protected]2f2d7042010-04-14 21:45:581314 // The GL context this decoder renders to on behalf of the client.
[email protected]66791e382010-07-14 20:48:301315 scoped_ptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021316
[email protected]a3ded6d2010-10-19 06:44:391317 // The ContextGroup for this decoder uses to track resources.
1318 ContextGroup::Ref group_;
1319
[email protected]6217d392010-03-25 22:08:351320 // A parent decoder can access this decoders saved offscreen frame buffer.
1321 // The parent pointer is reset if the parent is destroyed.
1322 base::WeakPtr<GLES2DecoderImpl> parent_;
1323
1324 // Width and height to which an offscreen frame buffer should be resized on
1325 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021326 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351327
[email protected]34ff8b0c2010-10-01 20:06:021328 // Current width and height of the offscreen frame buffer.
1329 gfx::Size offscreen_size_;
1330
[email protected]96449d2c2009-11-25 00:01:321331 // Current GL error bits.
1332 uint32 error_bits_;
1333
[email protected]96449d2c2009-11-25 00:01:321334 // Util to help with GL.
1335 GLES2Util util_;
1336
1337 // pack alignment as last set by glPixelStorei
1338 GLint pack_alignment_;
1339
1340 // unpack alignment as last set by glPixelStorei
1341 GLint unpack_alignment_;
1342
1343 // The currently bound array buffer. If this is 0 it is illegal to call
1344 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501345 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321346
1347 // The currently bound element array buffer. If this is 0 it is illegal
1348 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501349 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301350
[email protected]f39f4b3f2010-05-12 17:04:081351 // Class that manages vertex attribs.
1352 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301353
[email protected]b1122982010-05-17 23:04:241354 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1355 GLuint attrib_0_buffer_id_;
1356
1357 // The value currently in attrib_0.
1358 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1359
1360 // The size of attrib 0.
1361 GLsizei attrib_0_size_;
1362
[email protected]8fbedc02010-11-18 18:43:401363 // The buffer used to simulate GL_FIXED attribs.
1364 GLuint fixed_attrib_buffer_id_;
1365
1366 // The size of fiixed attrib buffer.
1367 GLsizei fixed_attrib_buffer_size_;
1368
[email protected]3916c97e2010-02-25 03:20:501369 // Current active texture by 0 - n index.
1370 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1371 // be 2.
1372 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301373
[email protected]3916c97e2010-02-25 03:20:501374 // Which textures are bound to texture units through glActiveTexture.
1375 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471376
[email protected]3a2e7c7b2010-08-06 01:12:281377 // state saved for clearing so we can clear render buffers and then
1378 // restore to these values.
1379 GLclampf clear_red_;
1380 GLclampf clear_green_;
1381 GLclampf clear_blue_;
1382 GLclampf clear_alpha_;
1383 GLboolean mask_red_;
1384 GLboolean mask_green_;
1385 GLboolean mask_blue_;
1386 GLboolean mask_alpha_;
1387 GLint clear_stencil_;
1388 GLuint mask_stencil_front_;
1389 GLuint mask_stencil_back_;
1390 GLclampf clear_depth_;
1391 GLboolean mask_depth_;
1392 bool enable_scissor_test_;
1393
[email protected]1d32bc82010-01-13 22:06:461394 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501395 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301396
[email protected]8e3e0662010-08-23 18:46:301397 // The currently bound framebuffers
1398 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1399 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561400
1401 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081402 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561403
[email protected]b9363b22010-06-09 22:06:151404 // The offscreen frame buffer that the client renders to. With EGL, the
1405 // depth and stencil buffers are separate. With regular GL there is a single
1406 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1407 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351408 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1409 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021410 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151411 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1412 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021413 GLenum offscreen_target_color_format_;
1414 GLenum offscreen_target_depth_format_;
1415 GLenum offscreen_target_stencil_format_;
1416 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351417
[email protected]a3a93e7b2010-08-28 00:48:561418 GLuint copy_texture_to_parent_texture_fb_;
1419
[email protected]34ff8b0c2010-10-01 20:06:021420 // The copy that is saved when SwapBuffers is called. It is also
1421 // used as the destination for multi-sample resolves.
1422 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351423 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]97872062010-11-03 19:07:051424 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351425
[email protected]7ff86b92010-11-25 17:50:001426 scoped_ptr<Callback1<gfx::Size>::Type> resize_callback_;
[email protected]43f28f832010-02-03 02:28:481427 scoped_ptr<Callback0::Type> swap_buffers_callback_;
1428
[email protected]8eee29c2010-04-29 03:38:291429 // The last error message set.
1430 std::string last_error_;
1431
[email protected]a3a93e7b2010-08-28 00:48:561432 // The current decoder error.
1433 error::Error current_decoder_error_;
1434
[email protected]b1d2dcb2010-05-17 19:24:181435 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451436 scoped_ptr<ShaderTranslator> vertex_translator_;
1437 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181438
[email protected]915a59a12010-09-30 21:29:111439 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051440 const Validators* validators_;
[email protected]915a59a12010-09-30 21:29:111441 FeatureInfo* feature_info_;
[email protected]9438b012010-06-15 22:55:051442
[email protected]96449d2c2009-11-25 00:01:321443 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1444};
1445
[email protected]6217d392010-03-25 22:08:351446ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1447 : decoder_(decoder) {
1448 decoder_->CopyRealGLErrorsToWrapper();
1449}
1450
1451ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1452 decoder_->ClearRealGLErrors();
1453}
1454
1455ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1456 GLuint id)
1457 : decoder_(decoder) {
1458 ScopedGLErrorSuppressor suppressor(decoder_);
1459
1460 // TODO(apatrick): Check if there are any other states that need to be reset
1461 // before binding a new texture.
1462 glActiveTexture(GL_TEXTURE0);
1463 glBindTexture(GL_TEXTURE_2D, id);
1464}
1465
1466ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1467 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301468 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351469}
1470
1471ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1472 GLuint id)
1473 : decoder_(decoder) {
1474 ScopedGLErrorSuppressor suppressor(decoder_);
1475 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1476}
1477
1478ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1479 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301480 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351481}
1482
1483ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1484 GLuint id)
1485 : decoder_(decoder) {
1486 ScopedGLErrorSuppressor suppressor(decoder_);
1487 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1488}
1489
1490ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1491 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301492 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351493}
1494
[email protected]34ff8b0c2010-10-01 20:06:021495ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1496 GLES2DecoderImpl* decoder) : decoder_(decoder) {
1497 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1498 decoder_->IsOffscreenBufferMultisampled() &&
1499 !decoder_->bound_read_framebuffer_.get());
1500 if (!resolve_and_bind_)
1501 return;
1502
1503 ScopedGLErrorSuppressor suppressor(decoder_);
1504 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1505 decoder_->offscreen_target_frame_buffer_->id());
1506 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT,
1507 decoder_->offscreen_saved_frame_buffer_->id());
1508 const int width = decoder_->offscreen_size_.width();
1509 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181510 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021511 if (IsAngle()) {
1512 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1513 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1514 } else {
1515 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1516 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1517 }
1518 glBindFramebufferEXT(GL_FRAMEBUFFER,
1519 decoder_->offscreen_saved_frame_buffer_->id());
1520}
1521
1522ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1523 if (!resolve_and_bind_)
1524 return;
1525
1526 ScopedGLErrorSuppressor suppressor(decoder_);
1527 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181528 if (decoder_->enable_scissor_test_) {
1529 glEnable(GL_SCISSOR_TEST);
1530 }
[email protected]34ff8b0c2010-10-01 20:06:021531}
1532
[email protected]6217d392010-03-25 22:08:351533Texture::Texture(GLES2DecoderImpl* decoder)
1534 : decoder_(decoder),
1535 id_(0) {
1536}
1537
1538Texture::~Texture() {
1539 // This does not destroy the render texture because that would require that
1540 // the associated GL context was current. Just check that it was explicitly
1541 // destroyed.
1542 DCHECK_EQ(id_, 0u);
1543}
1544
1545void Texture::Create() {
1546 ScopedGLErrorSuppressor suppressor(decoder_);
1547 Destroy();
1548 glGenTextures(1, &id_);
1549}
1550
[email protected]34ff8b0c2010-10-01 20:06:021551bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351552 DCHECK_NE(id_, 0u);
1553 ScopedGLErrorSuppressor suppressor(decoder_);
1554 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]8c515f82010-11-09 03:40:041555 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1556 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1557 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1558 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351559
1560 glTexImage2D(GL_TEXTURE_2D,
1561 0, // mip level
[email protected]34ff8b0c2010-10-01 20:06:021562 format,
[email protected]6217d392010-03-25 22:08:351563 size.width(),
1564 size.height(),
1565 0, // border
[email protected]34ff8b0c2010-10-01 20:06:021566 format,
[email protected]6217d392010-03-25 22:08:351567 GL_UNSIGNED_BYTE,
1568 NULL);
1569
[email protected]d37231fa2010-04-09 21:16:021570 size_ = size;
1571
[email protected]6217d392010-03-25 22:08:351572 return glGetError() == GL_NO_ERROR;
1573}
1574
1575void Texture::Copy(const gfx::Size& size) {
1576 DCHECK_NE(id_, 0u);
1577 ScopedGLErrorSuppressor suppressor(decoder_);
1578 ScopedTexture2DBinder binder(decoder_, id_);
1579 glCopyTexImage2D(GL_TEXTURE_2D,
1580 0, // level
1581 GL_RGBA,
1582 0, 0,
1583 size.width(),
1584 size.height(),
1585 0); // border
1586}
1587
1588void Texture::Destroy() {
1589 if (id_ != 0) {
1590 ScopedGLErrorSuppressor suppressor(decoder_);
1591 glDeleteTextures(1, &id_);
1592 id_ = 0;
1593 }
1594}
1595
[email protected]97872062010-11-03 19:07:051596void Texture::Invalidate() {
1597 id_ = 0;
1598}
1599
[email protected]6217d392010-03-25 22:08:351600RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1601 : decoder_(decoder),
1602 id_(0) {
1603}
1604
1605RenderBuffer::~RenderBuffer() {
1606 // This does not destroy the render buffer because that would require that
1607 // the associated GL context was current. Just check that it was explicitly
1608 // destroyed.
1609 DCHECK_EQ(id_, 0u);
1610}
1611
1612void RenderBuffer::Create() {
1613 ScopedGLErrorSuppressor suppressor(decoder_);
1614 Destroy();
1615 glGenRenderbuffersEXT(1, &id_);
1616}
1617
[email protected]34ff8b0c2010-10-01 20:06:021618bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1619 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351620 ScopedGLErrorSuppressor suppressor(decoder_);
1621 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021622 if (samples <= 1) {
1623 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1624 format,
1625 size.width(),
1626 size.height());
1627 } else {
1628 if (IsAngle()) {
1629 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1630 samples,
1631 format,
1632 size.width(),
1633 size.height());
1634 } else {
1635 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1636 samples,
1637 format,
1638 size.width(),
1639 size.height());
1640 }
1641 }
[email protected]6217d392010-03-25 22:08:351642 return glGetError() == GL_NO_ERROR;
1643}
1644
1645void RenderBuffer::Destroy() {
1646 if (id_ != 0) {
1647 ScopedGLErrorSuppressor suppressor(decoder_);
1648 glDeleteRenderbuffersEXT(1, &id_);
1649 id_ = 0;
1650 }
1651}
1652
[email protected]97872062010-11-03 19:07:051653void RenderBuffer::Invalidate() {
1654 id_ = 0;
1655}
1656
[email protected]6217d392010-03-25 22:08:351657FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1658 : decoder_(decoder),
1659 id_(0) {
1660}
1661
1662FrameBuffer::~FrameBuffer() {
1663 // This does not destroy the frame buffer because that would require that
1664 // the associated GL context was current. Just check that it was explicitly
1665 // destroyed.
1666 DCHECK_EQ(id_, 0u);
1667}
1668
1669void FrameBuffer::Create() {
1670 ScopedGLErrorSuppressor suppressor(decoder_);
1671 Destroy();
1672 glGenFramebuffersEXT(1, &id_);
1673}
1674
1675void FrameBuffer::AttachRenderTexture(Texture* texture) {
1676 DCHECK_NE(id_, 0u);
1677 ScopedGLErrorSuppressor suppressor(decoder_);
1678 ScopedFrameBufferBinder binder(decoder_, id_);
1679 GLuint attach_id = texture ? texture->id() : 0;
1680 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1681 GL_COLOR_ATTACHMENT0,
1682 GL_TEXTURE_2D,
1683 attach_id,
1684 0);
1685}
1686
[email protected]b9363b22010-06-09 22:06:151687void FrameBuffer::AttachRenderBuffer(GLenum target,
1688 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351689 DCHECK_NE(id_, 0u);
1690 ScopedGLErrorSuppressor suppressor(decoder_);
1691 ScopedFrameBufferBinder binder(decoder_, id_);
1692 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1693 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151694 target,
[email protected]6217d392010-03-25 22:08:351695 GL_RENDERBUFFER,
1696 attach_id);
1697}
1698
1699void FrameBuffer::Clear(GLbitfield buffers) {
1700 ScopedGLErrorSuppressor suppressor(decoder_);
1701 ScopedFrameBufferBinder binder(decoder_, id_);
1702 glClear(buffers);
1703}
1704
1705void FrameBuffer::Destroy() {
1706 if (id_ != 0) {
1707 ScopedGLErrorSuppressor suppressor(decoder_);
1708 glDeleteFramebuffersEXT(1, &id_);
1709 id_ = 0;
1710 }
1711}
1712
[email protected]97872062010-11-03 19:07:051713void FrameBuffer::Invalidate() {
1714 id_ = 0;
1715}
1716
[email protected]6217d392010-03-25 22:08:351717GLenum FrameBuffer::CheckStatus() {
1718 DCHECK_NE(id_, 0u);
1719 ScopedGLErrorSuppressor suppressor(decoder_);
1720 ScopedFrameBufferBinder binder(decoder_, id_);
1721 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1722}
1723
[email protected]3916c97e2010-02-25 03:20:501724GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1725 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321726}
1727
[email protected]3916c97e2010-02-25 03:20:501728GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391729 : GLES2Decoder(),
1730 group_(ContextGroup::Ref(group ? group : new ContextGroup())),
[email protected]96449d2c2009-11-25 00:01:321731 error_bits_(0),
1732 util_(0), // TODO(gman): Set to actual num compress texture formats.
1733 pack_alignment_(4),
1734 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241735 attrib_0_buffer_id_(0),
1736 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401737 fixed_attrib_buffer_id_(0),
1738 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501739 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281740 clear_red_(0),
1741 clear_green_(0),
1742 clear_blue_(0),
1743 clear_alpha_(0),
1744 mask_red_(true),
1745 mask_green_(true),
1746 mask_blue_(true),
1747 mask_alpha_(true),
1748 clear_stencil_(0),
1749 mask_stencil_front_(-1),
1750 mask_stencil_back_(-1),
1751 clear_depth_(1.0f),
1752 mask_depth_(true),
1753 enable_scissor_test_(false),
[email protected]34ff8b0c2010-10-01 20:06:021754 offscreen_target_color_format_(0),
1755 offscreen_target_depth_format_(0),
1756 offscreen_target_stencil_format_(0),
1757 offscreen_target_samples_(0),
[email protected]97872062010-11-03 19:07:051758 offscreen_saved_color_format_(0),
[email protected]a3a93e7b2010-08-28 00:48:561759 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051760 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111761 validators_(group_->feature_info()->validators()),
[email protected]34ff8b0c2010-10-01 20:06:021762 feature_info_(group_->feature_info()) {
[email protected]b1122982010-05-17 23:04:241763 attrib_0_value_.v[0] = 0.0f;
1764 attrib_0_value_.v[1] = 0.0f;
1765 attrib_0_value_.v[2] = 0.0f;
1766 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151767
[email protected]c2f8c8402010-12-06 18:07:241768 // The shader translator is used for WebGL even when running on EGL
1769 // because additional restrictions are needed (like only enabling
1770 // GL_OES_standard_derivatives on demand). It is used for the unit
1771 // tests because
1772 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1773 // empty string to CompileShader and this is not a valid shader.
1774 // TODO(apatrick): fix this test.
1775 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1776 !feature_info_->feature_flags().chromium_webglsl) ||
[email protected]b9363b22010-06-09 22:06:151777 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1778 use_shader_translator_ = false;
1779 }
[email protected]96449d2c2009-11-25 00:01:321780}
1781
[email protected]5a6db6c2010-04-22 18:32:061782bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:351783 const gfx::Size& size,
[email protected]a3ded6d2010-10-19 06:44:391784 const char* allowed_extensions,
[email protected]34ff8b0c2010-10-01 20:06:021785 const std::vector<int32>& attribs,
[email protected]d37231fa2010-04-09 21:16:021786 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:351787 uint32 parent_client_texture_id) {
[email protected]4bedba72010-04-20 22:08:541788 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301789 DCHECK(!context_.get());
1790
1791 // Take ownership of the GLContext.
1792 context_.reset(context);
[email protected]d37231fa2010-04-09 21:16:021793
[email protected]6217d392010-03-25 22:08:351794 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021795 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351796 if (parent)
1797 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1798
[email protected]246a70452010-03-05 21:53:501799 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011800 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1801 << "MakeCurrent failed.";
[email protected]246a70452010-03-05 21:53:501802 Destroy();
1803 return false;
[email protected]eb54a562010-01-20 21:55:181804 }
1805
[email protected]a3ded6d2010-10-19 06:44:391806 if (!group_->Initialize(allowed_extensions)) {
1807 LOG(ERROR) << "GPUProcessor::InitializeCommon failed because group "
1808 << "failed to initialize.";
1809 Destroy();
[email protected]ae1741092010-11-17 19:16:031810 return false;
[email protected]a3ded6d2010-10-19 06:44:391811 }
1812
[email protected]246a70452010-03-05 21:53:501813 CHECK_GL_ERROR();
1814
[email protected]f39f4b3f2010-05-12 17:04:081815 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321816
[email protected]b1122982010-05-17 23:04:241817 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1818 // OpenGL ES 2.0 does not have this issue.
1819 glEnableVertexAttribArray(0);
1820 glGenBuffersARB(1, &attrib_0_buffer_id_);
1821 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1822 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1823 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401824 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081825
[email protected]246a70452010-03-05 21:53:501826 texture_units_.reset(
1827 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151828 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491829 glActiveTexture(GL_TEXTURE0 + tt);
1830 // Do cube map first because we want the last bind to be 2D.
1831 TextureManager::TextureInfo* info =
[email protected]1958e0e2010-04-22 05:17:151832 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491833 texture_units_[tt].bound_texture_cube_map = info;
1834 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1835 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1836 texture_units_[tt].bound_texture_2d = info;
1837 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151838 }
[email protected]00f893d2010-08-24 18:55:491839 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501840 CHECK_GL_ERROR();
1841
[email protected]d37231fa2010-04-09 21:16:021842 if (context_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:021843 ContextCreationAttribParser attrib_parser;
1844 if (!attrib_parser.Parse(attribs))
1845 return false;
1846
1847 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:541848 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:021849 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
1850 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:431851 // max_sample_count must be initialized to a sane value. If
1852 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
1853 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:021854 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
1855 offscreen_target_samples_ = std::min(attrib_parser.samples_,
1856 max_sample_count);
1857 } else {
1858 offscreen_target_samples_ = 1;
1859 }
1860
1861 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1862 const bool rgb8_supported =
1863 context_->HasExtension("GL_OES_rgb8_rgba8");
1864 // The only available default render buffer formats in GLES2 have very
1865 // little precision. Don't enable multisampling unless 8-bit render
1866 // buffer formats are available--instead fall back to 8-bit textures.
1867 if (rgb8_supported && offscreen_target_samples_ > 1) {
1868 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1869 GL_RGBA8 : GL_RGB8;
1870 } else {
1871 offscreen_target_samples_ = 1;
1872 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1873 GL_RGBA : GL_RGB;
1874 }
1875
1876 // ANGLE only supports packed depth/stencil formats, so use it if it is
1877 // available.
1878 const bool depth24_stencil8_supported =
1879 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271880 VLOG(1) << "GL_OES_packed_depth_stencil "
1881 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:001882 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1883 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021884 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1885 offscreen_target_stencil_format_ = 0;
1886 } else {
1887 // It may be the case that this depth/stencil combination is not
1888 // supported, but this will be checked later by CheckFramebufferStatus.
1889 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1890 GL_DEPTH_COMPONENT16 : 0;
1891 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1892 GL_STENCIL_INDEX8 : 0;
1893 }
1894 } else {
1895 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1896 GL_RGBA : GL_RGB;
1897
1898 // If depth is requested at all, use the packed depth stencil format if
1899 // it's available, as some desktop GL drivers don't support any non-packed
1900 // formats for depth attachments.
1901 const bool depth24_stencil8_supported =
1902 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271903 VLOG(1) << "GL_EXT_packed_depth_stencil "
1904 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:021905
[email protected]71ee3642010-10-14 18:08:001906 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1907 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021908 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1909 offscreen_target_stencil_format_ = 0;
1910 } else {
1911 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1912 GL_DEPTH_COMPONENT : 0;
1913 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1914 GL_STENCIL_INDEX : 0;
1915 }
1916 }
1917
[email protected]97872062010-11-03 19:07:051918 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
1919 GL_RGBA : GL_RGB;
1920
[email protected]6217d392010-03-25 22:08:351921 // Create the target frame buffer. This is the one that the client renders
1922 // directly to.
1923 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1924 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021925 // Due to GLES2 format limitations, either the color texture (for
1926 // non-multisampling) or the color render buffer (for multisampling) will be
1927 // attached to the offscreen frame buffer. The render buffer has more
1928 // limited formats available to it, but the texture can't do multisampling.
1929 if (IsOffscreenBufferMultisampled()) {
1930 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
1931 offscreen_target_color_render_buffer_->Create();
1932 } else {
1933 offscreen_target_color_texture_.reset(new Texture(this));
1934 offscreen_target_color_texture_->Create();
1935 }
1936 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151937 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021938 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151939 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:351940
1941 // Create the saved offscreen texture. The target frame buffer is copied
1942 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021943 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
1944 offscreen_saved_frame_buffer_->Create();
1945 //
[email protected]6217d392010-03-25 22:08:351946 offscreen_saved_color_texture_.reset(new Texture(this));
1947 offscreen_saved_color_texture_->Create();
1948
[email protected]6217d392010-03-25 22:08:351949 // Map the ID of the saved offscreen texture into the parent so that
1950 // it can reference it.
1951 if (parent_) {
1952 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]6217d392010-03-25 22:08:351953 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:031954 parent_->CreateTextureInfo(parent_client_texture_id, service_id);
[email protected]6217d392010-03-25 22:08:351955 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
1956 }
1957
1958 // Allocate the render buffers at their initial size and check the status
1959 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021960 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351961 if (!UpdateOffscreenFrameBufferSize()) {
[email protected]d0498742010-09-20 20:27:011962 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:351963 Destroy();
1964 return false;
1965 }
1966
1967 // Bind to the new default frame buffer (the offscreen target frame buffer).
1968 // This should now be associated with ID zero.
1969 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]a3a93e7b2010-08-28 00:48:561970
1971 glGenFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:351972 }
1973
[email protected]76a0ee102010-04-07 21:03:041974 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1975 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1976 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:371977 // mailing list archives. It also implicitly enables the desktop GL
1978 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
1979 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:151980 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1981 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:371982 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:151983 }
[email protected]de17df392010-04-23 21:09:411984
[email protected]c2f8c8402010-12-06 18:07:241985 if (!InitializeShaderTranslator()) {
1986 return false;
[email protected]de17df392010-04-23 21:09:411987 }
[email protected]76a0ee102010-04-07 21:03:041988
[email protected]246a70452010-03-05 21:53:501989 return true;
[email protected]96449d2c2009-11-25 00:01:321990}
1991
[email protected]c2f8c8402010-12-06 18:07:241992bool GLES2DecoderImpl::InitializeShaderTranslator() {
1993 // Re-check the state of use_shader_translator_ each time this is called.
1994 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1995 feature_info_->feature_flags().chromium_webglsl &&
1996 !use_shader_translator_) {
1997 use_shader_translator_ = true;
1998 }
1999 if (!use_shader_translator_) {
2000 return true;
2001 }
2002 ShBuiltInResources resources;
2003 ShInitBuiltInResources(&resources);
2004 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2005 resources.MaxVertexUniformVectors =
2006 group_->max_vertex_uniform_vectors();
2007 resources.MaxVaryingVectors = group_->max_varying_vectors();
2008 resources.MaxVertexTextureImageUnits =
2009 group_->max_vertex_texture_image_units();
2010 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2011 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2012 resources.MaxFragmentUniformVectors =
2013 group_->max_fragment_uniform_vectors();
2014 resources.MaxDrawBuffers = 1;
2015 resources.OES_standard_derivatives =
2016 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
2017 vertex_translator_.reset(new ShaderTranslator);
2018 ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ?
2019 SH_WEBGL_SPEC : SH_GLES2_SPEC;
2020 bool is_glsl_es =
2021 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
2022 if (!vertex_translator_->Init(
2023 SH_VERTEX_SHADER, shader_spec, &resources, is_glsl_es)) {
2024 LOG(ERROR) << "Could not initialize vertex shader translator.";
2025 Destroy();
2026 return false;
2027 }
2028 fragment_translator_.reset(new ShaderTranslator);
2029 if (!fragment_translator_->Init(
2030 SH_FRAGMENT_SHADER, shader_spec, &resources, is_glsl_es)) {
2031 LOG(ERROR) << "Could not initialize fragment shader translator.";
2032 Destroy();
2033 return false;
2034 }
2035 return true;
2036}
2037
[email protected]ae51d192010-04-27 00:48:032038bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472039 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032040 if (GetBufferInfo(client_ids[ii])) {
2041 return false;
2042 }
2043 }
2044 scoped_array<GLuint> service_ids(new GLuint[n]);
2045 glGenBuffersARB(n, service_ids.get());
2046 for (GLsizei ii = 0; ii < n; ++ii) {
2047 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2048 }
2049 return true;
2050}
2051
2052bool GLES2DecoderImpl::GenFramebuffersHelper(
2053 GLsizei n, const GLuint* client_ids) {
2054 for (GLsizei ii = 0; ii < n; ++ii) {
2055 if (GetFramebufferInfo(client_ids[ii])) {
2056 return false;
2057 }
2058 }
2059 scoped_array<GLuint> service_ids(new GLuint[n]);
2060 glGenFramebuffersEXT(n, service_ids.get());
2061 for (GLsizei ii = 0; ii < n; ++ii) {
2062 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2063 }
2064 return true;
2065}
2066
2067bool GLES2DecoderImpl::GenRenderbuffersHelper(
2068 GLsizei n, const GLuint* client_ids) {
2069 for (GLsizei ii = 0; ii < n; ++ii) {
2070 if (GetRenderbufferInfo(client_ids[ii])) {
2071 return false;
2072 }
2073 }
2074 scoped_array<GLuint> service_ids(new GLuint[n]);
2075 glGenRenderbuffersEXT(n, service_ids.get());
2076 for (GLsizei ii = 0; ii < n; ++ii) {
2077 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2078 }
2079 return true;
2080}
2081
2082bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2083 for (GLsizei ii = 0; ii < n; ++ii) {
2084 if (GetTextureInfo(client_ids[ii])) {
2085 return false;
2086 }
2087 }
2088 scoped_array<GLuint> service_ids(new GLuint[n]);
2089 glGenTextures(n, service_ids.get());
2090 for (GLsizei ii = 0; ii < n; ++ii) {
2091 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2092 }
2093 return true;
2094}
2095
2096void GLES2DecoderImpl::DeleteBuffersHelper(
2097 GLsizei n, const GLuint* client_ids) {
2098 for (GLsizei ii = 0; ii < n; ++ii) {
2099 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
2100 if (info) {
2101 GLuint service_id = info->service_id();
2102 glDeleteBuffersARB(1, &service_id);
2103 RemoveBufferInfo(client_ids[ii]);
2104 }
[email protected]a93bb842010-02-16 23:03:472105 }
[email protected]07f54fcc2009-12-22 02:46:302106}
2107
[email protected]ae51d192010-04-27 00:48:032108void GLES2DecoderImpl::DeleteFramebuffersHelper(
2109 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582110 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032111 FramebufferManager::FramebufferInfo* info =
2112 GetFramebufferInfo(client_ids[ii]);
2113 if (info) {
2114 GLuint service_id = info->service_id();
2115 glDeleteFramebuffersEXT(1, &service_id);
2116 RemoveFramebufferInfo(client_ids[ii]);
2117 }
[email protected]a25fa872010-03-25 02:57:582118 }
[email protected]07f54fcc2009-12-22 02:46:302119}
2120
[email protected]ae51d192010-04-27 00:48:032121void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2122 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582123 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032124 RenderbufferManager::RenderbufferInfo* info =
2125 GetRenderbufferInfo(client_ids[ii]);
2126 if (info) {
2127 GLuint service_id = info->service_id();
2128 glDeleteRenderbuffersEXT(1, &service_id);
2129 RemoveRenderbufferInfo(client_ids[ii]);
2130 }
[email protected]a25fa872010-03-25 02:57:582131 }
[email protected]07f54fcc2009-12-22 02:46:302132}
2133
[email protected]ae51d192010-04-27 00:48:032134void GLES2DecoderImpl::DeleteTexturesHelper(
2135 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472136 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032137 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
2138 if (info) {
2139 GLuint service_id = info->service_id();
2140 glDeleteTextures(1, &service_id);
2141 RemoveTextureInfo(client_ids[ii]);
2142 }
[email protected]a93bb842010-02-16 23:03:472143 }
[email protected]07f54fcc2009-12-22 02:46:302144}
2145
[email protected]43f28f832010-02-03 02:28:482146// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322147
[email protected]eb54a562010-01-20 21:55:182148bool GLES2DecoderImpl::MakeCurrent() {
[email protected]66791e382010-07-14 20:48:302149 return context_.get() ? context_->MakeCurrent() : false;
[email protected]eb54a562010-01-20 21:55:182150}
2151
[email protected]8e3e0662010-08-23 18:46:302152void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2153 glBindRenderbufferEXT(
2154 GL_RENDERBUFFER,
2155 bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
2156}
2157
2158static void RebindCurrentFramebuffer(
2159 GLenum target,
2160 FramebufferManager::FramebufferInfo* info,
2161 FrameBuffer* offscreen_frame_buffer) {
2162 GLuint framebuffer_id = info ? info->service_id() : 0;
2163 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2164 framebuffer_id = offscreen_frame_buffer->id();
2165 }
2166 glBindFramebufferEXT(target, framebuffer_id);
2167}
2168
2169void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]a3ded6d2010-10-19 06:44:392170 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302171 RebindCurrentFramebuffer(
2172 GL_FRAMEBUFFER,
2173 bound_draw_framebuffer_.get(),
2174 offscreen_target_frame_buffer_.get());
2175 } else {
2176 RebindCurrentFramebuffer(
2177 GL_READ_FRAMEBUFFER_EXT,
2178 bound_read_framebuffer_.get(),
2179 offscreen_target_frame_buffer_.get());
2180 RebindCurrentFramebuffer(
2181 GL_DRAW_FRAMEBUFFER_EXT,
2182 bound_draw_framebuffer_.get(),
2183 offscreen_target_frame_buffer_.get());
2184 }
2185}
2186
2187void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2188 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2189 GLuint last_id;
2190 if (info.bound_texture_2d) {
2191 last_id = info.bound_texture_2d->service_id();
2192 } else {
2193 last_id = 0;
2194 }
2195
2196 glBindTexture(GL_TEXTURE_2D, last_id);
2197 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2198}
2199
2200gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2201 if (bound_read_framebuffer_ != 0) {
[email protected]9edc6b22010-12-23 02:00:262202 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2203 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2204 if (attachment) {
2205 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502206 }
[email protected]9edc6b22010-12-23 02:00:262207 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022208 } else if (offscreen_target_frame_buffer_.get()) {
2209 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352210 } else {
[email protected]d37231fa2010-04-09 21:16:022211 return context_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022212 }
[email protected]246a70452010-03-05 21:53:502213}
2214
[email protected]9edc6b22010-12-23 02:00:262215GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
2216 if (bound_read_framebuffer_ != 0) {
2217 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2218 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2219 if (attachment) {
2220 return attachment->internal_format();
2221 }
2222 return 0;
2223 } else if (offscreen_target_frame_buffer_.get()) {
2224 return offscreen_target_color_format_;
2225 } else {
2226 // TODO(gman): return correct format
2227 return GL_RGBA;
2228 }
2229}
2230
[email protected]6217d392010-03-25 22:08:352231bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]34ff8b0c2010-10-01 20:06:022232 if (offscreen_size_ == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:352233 return true;
2234
[email protected]34ff8b0c2010-10-01 20:06:022235 offscreen_size_ = pending_offscreen_size_;
2236
[email protected]6217d392010-03-25 22:08:352237 // Reallocate the offscreen target buffers.
[email protected]34ff8b0c2010-10-01 20:06:022238 DCHECK(offscreen_target_color_format_);
2239 if (IsOffscreenBufferMultisampled()) {
2240 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2241 pending_offscreen_size_, offscreen_target_color_format_,
2242 offscreen_target_samples_)) {
2243 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2244 << "to allocate storage for offscreen target color buffer.";
2245 return false;
2246 }
2247 } else {
2248 if (!offscreen_target_color_texture_->AllocateStorage(
2249 pending_offscreen_size_, offscreen_target_color_format_)) {
2250 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2251 << "to allocate storage for offscreen target color texture.";
2252 return false;
2253 }
2254 }
2255 if (offscreen_target_depth_format_ &&
2256 !offscreen_target_depth_render_buffer_->AllocateStorage(
2257 pending_offscreen_size_, offscreen_target_depth_format_,
2258 offscreen_target_samples_)) {
[email protected]d0498742010-09-20 20:27:012259 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
[email protected]34ff8b0c2010-10-01 20:06:022260 << "to allocate storage for offscreen target depth buffer.";
2261 return false;
2262 }
2263 if (offscreen_target_stencil_format_ &&
2264 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2265 pending_offscreen_size_, offscreen_target_stencil_format_,
2266 offscreen_target_samples_)) {
2267 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2268 << "to allocate storage for offscreen target stencil buffer.";
[email protected]6217d392010-03-25 22:08:352269 return false;
2270 }
2271
[email protected]2f2d7042010-04-14 21:45:582272 // Attach the offscreen target buffers to the target frame buffer.
[email protected]34ff8b0c2010-10-01 20:06:022273 if (IsOffscreenBufferMultisampled()) {
[email protected]b9363b22010-06-09 22:06:152274 offscreen_target_frame_buffer_->AttachRenderBuffer(
[email protected]34ff8b0c2010-10-01 20:06:022275 GL_COLOR_ATTACHMENT0,
2276 offscreen_target_color_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152277 } else {
[email protected]34ff8b0c2010-10-01 20:06:022278 offscreen_target_frame_buffer_->AttachRenderTexture(
2279 offscreen_target_color_texture_.get());
2280 }
2281 if (offscreen_target_depth_format_) {
2282 offscreen_target_frame_buffer_->AttachRenderBuffer(
2283 GL_DEPTH_ATTACHMENT,
2284 offscreen_target_depth_render_buffer_.get());
2285 }
2286 const bool packed_depth_stencil =
2287 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2288 if (packed_depth_stencil) {
[email protected]b9363b22010-06-09 22:06:152289 offscreen_target_frame_buffer_->AttachRenderBuffer(
2290 GL_STENCIL_ATTACHMENT,
2291 offscreen_target_depth_render_buffer_.get());
[email protected]34ff8b0c2010-10-01 20:06:022292 } else if (offscreen_target_stencil_format_) {
2293 offscreen_target_frame_buffer_->AttachRenderBuffer(
2294 GL_STENCIL_ATTACHMENT,
2295 offscreen_target_stencil_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152296 }
[email protected]34ff8b0c2010-10-01 20:06:022297
[email protected]6217d392010-03-25 22:08:352298 if (offscreen_target_frame_buffer_->CheckStatus() !=
2299 GL_FRAMEBUFFER_COMPLETE) {
[email protected]d0498742010-09-20 20:27:012300 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2301 << "because offscreen FBO was incomplete.";
[email protected]6217d392010-03-25 22:08:352302 return false;
2303 }
2304
[email protected]c007aa02010-09-02 22:22:402305 // Clear the target frame buffer.
2306 {
2307 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]3f0add5e2010-09-13 20:16:282308 glClearColor(0, 0, 0, 0);
[email protected]c007aa02010-09-02 22:22:402309 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2310 glClearStencil(0);
2311 glStencilMaskSeparate(GL_FRONT, GL_TRUE);
2312 glStencilMaskSeparate(GL_BACK, GL_TRUE);
2313 glClearDepth(0);
2314 glDepthMask(GL_TRUE);
2315 glDisable(GL_SCISSOR_TEST);
[email protected]2f2d7042010-04-14 21:45:582316 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402317 RestoreClearState();
[email protected]2f2d7042010-04-14 21:45:582318 }
[email protected]2f2d7042010-04-14 21:45:582319
[email protected]34ff8b0c2010-10-01 20:06:022320 if (parent_ || IsOffscreenBufferMultisampled()) {
[email protected]97872062010-11-03 19:07:052321 DCHECK(offscreen_saved_color_format_);
2322 offscreen_saved_color_texture_->AllocateStorage(
2323 pending_offscreen_size_, offscreen_saved_color_format_);
[email protected]d37231fa2010-04-09 21:16:022324
[email protected]34ff8b0c2010-10-01 20:06:022325 offscreen_saved_frame_buffer_->AttachRenderTexture(
2326 offscreen_saved_color_texture_.get());
2327 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2328 GL_FRAMEBUFFER_COMPLETE) {
2329 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2330 << "because offscreen saved FBO was incomplete.";
2331 return false;
2332 }
2333 }
2334
2335 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582336 // Update the info about the offscreen saved color texture in the parent.
2337 // The reference to the parent is a weak pointer and will become null if the
2338 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352339 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142340 GLuint client_id;
[email protected]262d7aa2010-12-03 22:07:292341 TextureManager* parent_texture_manager = parent_->texture_manager();
2342 CHECK(parent_texture_manager->GetClientId(service_id, &client_id));
[email protected]8d25d042010-06-16 19:48:142343 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352344 DCHECK(info);
2345
[email protected]262d7aa2010-12-03 22:07:292346 parent_texture_manager->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:112347 feature_info_,
[email protected]ef526492010-06-02 23:12:252348 info,
2349 GL_TEXTURE_2D,
2350 0, // level
2351 GL_RGBA,
2352 pending_offscreen_size_.width(),
2353 pending_offscreen_size_.height(),
2354 1, // depth
2355 0, // border
2356 GL_RGBA,
2357 GL_UNSIGNED_BYTE);
[email protected]262d7aa2010-12-03 22:07:292358 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042359 feature_info_,
2360 info,
2361 GL_TEXTURE_MAG_FILTER,
2362 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292363 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042364 feature_info_,
2365 info,
2366 GL_TEXTURE_MIN_FILTER,
2367 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292368 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042369 feature_info_,
2370 info,
2371 GL_TEXTURE_WRAP_S,
2372 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292373 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042374 feature_info_,
2375 info,
2376 GL_TEXTURE_WRAP_T,
2377 GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:352378
[email protected]c007aa02010-09-02 22:22:402379 // Clear the offscreen color texture.
2380 {
[email protected]34ff8b0c2010-10-01 20:06:022381 ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:402382 glClearColor(0, 0, 0, 0);
2383 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2384 glDisable(GL_SCISSOR_TEST);
[email protected]0c8c9d22010-06-25 17:36:392385 glClear(GL_COLOR_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402386 RestoreClearState();
[email protected]0c8c9d22010-06-25 17:36:392387 }
[email protected]0c8c9d22010-06-25 17:36:392388 }
[email protected]e566b955d2010-06-22 19:26:512389
[email protected]6217d392010-03-25 22:08:352390 return true;
2391}
2392
[email protected]7ff86b92010-11-25 17:50:002393void GLES2DecoderImpl::SetResizeCallback(Callback1<gfx::Size>::Type* callback) {
2394 resize_callback_.reset(callback);
2395}
2396
[email protected]43f28f832010-02-03 02:28:482397void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
2398 swap_buffers_callback_.reset(callback);
2399}
2400
[email protected]1318e922010-09-17 22:03:162401bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2402 uint32* service_texture_id) {
2403 TextureManager::TextureInfo* texture =
2404 texture_manager()->GetTextureInfo(client_texture_id);
2405 if (texture) {
2406 *service_texture_id = texture->service_id();
2407 return true;
2408 }
2409 return false;
2410}
2411
[email protected]96449d2c2009-11-25 00:01:322412void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392413 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052414
2415 if (group_.get())
2416 group_->set_have_context(have_context);
2417
[email protected]eadc96792010-10-27 19:39:392418 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142419 if (current_program_) {
2420 program_manager()->UnuseProgram(shader_manager(), current_program_);
2421 current_program_ = NULL;
2422 }
2423
[email protected]b1122982010-05-17 23:04:242424 if (attrib_0_buffer_id_) {
2425 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2426 }
[email protected]8fbedc02010-11-18 18:43:402427 if (fixed_attrib_buffer_id_) {
2428 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2429 }
[email protected]b1122982010-05-17 23:04:242430
[email protected]4bedba72010-04-20 22:08:542431 // Remove the saved frame buffer mapping from the parent decoder. The
2432 // parent pointer is a weak pointer so it will be null if the parent has
2433 // already been destroyed.
2434 if (parent_) {
2435 // First check the texture has been mapped into the parent. This might not
2436 // be the case if initialization failed midway through.
2437 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]ae51d192010-04-27 00:48:032438 GLuint client_id = 0;
2439 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]915a59a12010-09-30 21:29:112440 parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]4bedba72010-04-20 22:08:542441 }
[email protected]a3a93e7b2010-08-28 00:48:562442
2443 glDeleteFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:352444 }
[email protected]6217d392010-03-25 22:08:352445
[email protected]97872062010-11-03 19:07:052446 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542447 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052448 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542449 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052450 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022451 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052452 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152453 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052454 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152455 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052456 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022457 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052458 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542459 offscreen_saved_color_texture_->Destroy();
[email protected]66791e382010-07-14 20:48:302460
[email protected]eadc96792010-10-27 19:39:392461 // must release the ContextGroup before destroying the context as its
2462 // destructor uses GL.
2463 group_ = NULL;
2464
[email protected]66791e382010-07-14 20:48:302465 context_->Destroy();
2466 context_.reset();
[email protected]97872062010-11-03 19:07:052467 } else {
2468 if (offscreen_target_frame_buffer_.get())
2469 offscreen_target_frame_buffer_->Invalidate();
2470 if (offscreen_target_color_texture_.get())
2471 offscreen_target_color_texture_->Invalidate();
2472 if (offscreen_target_color_render_buffer_.get())
2473 offscreen_target_color_render_buffer_->Invalidate();
2474 if (offscreen_target_depth_render_buffer_.get())
2475 offscreen_target_depth_render_buffer_->Invalidate();
2476 if (offscreen_target_stencil_render_buffer_.get())
2477 offscreen_target_stencil_render_buffer_->Invalidate();
2478 if (offscreen_saved_frame_buffer_.get())
2479 offscreen_saved_frame_buffer_->Invalidate();
2480 if (offscreen_saved_color_texture_.get())
2481 offscreen_saved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022482 }
[email protected]97872062010-11-03 19:07:052483
2484 offscreen_target_frame_buffer_.reset();
2485 offscreen_target_color_texture_.reset();
2486 offscreen_target_color_render_buffer_.reset();
2487 offscreen_target_depth_render_buffer_.reset();
2488 offscreen_target_stencil_render_buffer_.reset();
2489 offscreen_saved_frame_buffer_.reset();
2490 offscreen_saved_color_texture_.reset();
[email protected]96449d2c2009-11-25 00:01:322491}
2492
[email protected]6217d392010-03-25 22:08:352493void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2494 // We can't resize the render buffers immediately because there might be a
2495 // partial frame rendered into them and we don't want the tail end of that
2496 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:022497 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352498}
2499
[email protected]269200b12010-11-18 22:53:062500void GLES2DecoderImpl::DoCopyTextureToParentTextureCHROMIUM(
[email protected]c007aa02010-09-02 22:22:402501 GLuint client_texture_id,
2502 GLuint parent_client_texture_id) {
[email protected]a3a93e7b2010-08-28 00:48:562503 if (parent_) {
[email protected]c007aa02010-09-02 22:22:402504 TextureManager::TextureInfo* texture = texture_manager()->GetTextureInfo(
2505 client_texture_id);
2506 TextureManager::TextureInfo* parent_texture =
2507 parent_->texture_manager()->GetTextureInfo(parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:562508 if (!texture || !parent_texture) {
2509 current_decoder_error_ = error::kInvalidArguments;
2510 return;
2511 }
2512 ScopedFrameBufferBinder fb_binder(this, copy_texture_to_parent_texture_fb_);
2513 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2514 GL_COLOR_ATTACHMENT0,
2515 GL_TEXTURE_2D,
2516 texture->service_id(),
2517 0);
2518 ScopedTexture2DBinder tex_binder(this, parent_texture->service_id());
2519 GLsizei width, height;
2520 parent_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
2521 glCopyTexImage2D(GL_TEXTURE_2D,
2522 0, // level
2523 GL_RGBA,
[email protected]c007aa02010-09-02 22:22:402524 0, 0, // x, y
[email protected]a3a93e7b2010-08-28 00:48:562525 width,
2526 height,
2527 0); // border
2528 }
2529}
2530
[email protected]43ecf372010-11-16 19:19:392531void GLES2DecoderImpl::DoResizeCHROMIUM(GLuint width, GLuint height) {
[email protected]7ff86b92010-11-25 17:50:002532#if defined(OS_LINUX)
2533 // Make sure that we are done drawing to the back buffer before resizing.
2534 glFinish();
2535#endif
2536 if (resize_callback_.get()) {
2537 gfx::Size size(width, height);
2538 resize_callback_->Run(size);
2539 }
[email protected]43ecf372010-11-16 19:19:392540}
2541
[email protected]96449d2c2009-11-25 00:01:322542const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2543 if (command_id > kStartPoint && command_id < kNumCommands) {
2544 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2545 }
2546 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2547}
2548
2549// Decode command with its arguments, and call the corresponding GL function.
2550// Note: args is a pointer to the command buffer. As such, it could be changed
2551// by a (malicious) client at any time, so if validation has to happen, it
2552// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142553error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322554 unsigned int command,
2555 unsigned int arg_count,
2556 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142557 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192558 if (debug()) {
2559 // TODO(gman): Change output to something useful for NaCl.
[email protected]d366c482010-10-20 00:11:272560 DVLOG(1) << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192561 }
[email protected]96449d2c2009-11-25 00:01:322562 unsigned int command_index = command - kStartPoint - 1;
2563 if (command_index < arraysize(g_command_info)) {
2564 const CommandInfo& info = g_command_info[command_index];
2565 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2566 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2567 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192568 uint32 immediate_data_size =
2569 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322570 switch (command) {
2571 #define GLES2_CMD_OP(name) \
2572 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192573 result = Handle ## name( \
2574 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322575 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192576 break; \
[email protected]96449d2c2009-11-25 00:01:322577
2578 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322579 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382580 }
2581 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302582 GLenum error;
2583 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382584 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292585 SetGLError(error, NULL);
[email protected]d366c482010-10-20 00:11:272586 DVLOG(1) << "GL ERROR: " << error << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192587 }
[email protected]96449d2c2009-11-25 00:01:322588 }
2589 } else {
[email protected]f7a64ee2010-02-01 22:24:142590 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322591 }
[email protected]b9849abf2009-11-25 19:13:192592 } else {
2593 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322594 }
[email protected]a3a93e7b2010-08-28 00:48:562595 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
2596 result = current_decoder_error_;
2597 current_decoder_error_ = error::kNoError;
2598 }
[email protected]b9849abf2009-11-25 19:13:192599 return result;
[email protected]96449d2c2009-11-25 00:01:322600}
2601
[email protected]ae51d192010-04-27 00:48:032602void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2603 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502604}
2605
[email protected]ae51d192010-04-27 00:48:032606bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2607 if (GetProgramInfo(client_id)) {
2608 return false;
2609 }
[email protected]96449d2c2009-11-25 00:01:322610 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032611 if (service_id != 0) {
2612 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322613 }
[email protected]ae51d192010-04-27 00:48:032614 return true;
[email protected]96449d2c2009-11-25 00:01:322615}
2616
[email protected]ae51d192010-04-27 00:48:032617bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2618 if (GetShaderInfo(client_id)) {
2619 return false;
[email protected]96449d2c2009-11-25 00:01:322620 }
[email protected]ae51d192010-04-27 00:48:032621 GLuint service_id = glCreateShader(type);
2622 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382623 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032624 }
2625 return true;
[email protected]96449d2c2009-11-25 00:01:322626}
2627
[email protected]3916c97e2010-02-25 03:20:502628void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452629 GLuint texture_index = texture_unit - GL_TEXTURE0;
2630 if (texture_index > group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292631 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502632 return;
2633 }
[email protected]36cef8ce2010-03-16 07:34:452634 active_texture_unit_ = texture_index;
2635 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502636}
2637
[email protected]051b1372010-04-12 02:42:082638void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502639 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082640 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032641 if (client_id != 0) {
2642 info = GetBufferInfo(client_id);
2643 if (!info) {
2644 // It's a new id so make a buffer info for it.
2645 glGenBuffersARB(1, &service_id);
2646 CreateBufferInfo(client_id, service_id);
2647 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102648 IdAllocator* id_allocator =
2649 group_->GetIdAllocator(id_namespaces::kBuffers);
2650 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032651 }
[email protected]051b1372010-04-12 02:42:082652 }
[email protected]ae51d192010-04-27 00:48:032653 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102654 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292655 SetGLError(GL_INVALID_OPERATION,
2656 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472657 return;
2658 }
[email protected]ae51d192010-04-27 00:48:032659 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472660 }
[email protected]96449d2c2009-11-25 00:01:322661 switch (target) {
2662 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502663 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322664 break;
2665 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502666 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322667 break;
2668 default:
[email protected]a93bb842010-02-16 23:03:472669 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322670 break;
2671 }
[email protected]051b1372010-04-12 02:42:082672 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322673}
2674
[email protected]051b1372010-04-12 02:42:082675void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2676 FramebufferManager::FramebufferInfo* info = NULL;
2677 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032678 if (client_id != 0) {
2679 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082680 if (!info) {
[email protected]ae51d192010-04-27 00:48:032681 // It's a new id so make a framebuffer info for it.
2682 glGenFramebuffersEXT(1, &service_id);
2683 CreateFramebufferInfo(client_id, service_id);
2684 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102685 IdAllocator* id_allocator =
2686 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2687 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032688 } else {
2689 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082690 }
[email protected]06c8b082011-01-05 18:00:362691 info->MarkAsValid();
[email protected]eff9a222010-12-21 21:48:562692 } else {
2693 service_id = context_->GetBackingFrameBufferObject();
[email protected]051b1372010-04-12 02:42:082694 }
[email protected]8e3e0662010-08-23 18:46:302695
2696 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
2697 bound_draw_framebuffer_ = info;
2698 }
2699 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
2700 bound_read_framebuffer_ = info;
2701 }
[email protected]6217d392010-03-25 22:08:352702
2703 // When rendering to an offscreen frame buffer, instead of unbinding from
2704 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:082705 if (info == NULL && offscreen_target_frame_buffer_.get())
2706 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:352707
[email protected]051b1372010-04-12 02:42:082708 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562709}
2710
[email protected]051b1372010-04-12 02:42:082711void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2712 RenderbufferManager::RenderbufferInfo* info = NULL;
2713 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032714 if (client_id != 0) {
2715 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082716 if (!info) {
[email protected]ae51d192010-04-27 00:48:032717 // It's a new id so make a renderbuffer info for it.
2718 glGenRenderbuffersEXT(1, &service_id);
2719 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102720 info = GetRenderbufferInfo(client_id);
2721 IdAllocator* id_allocator =
2722 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2723 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032724 } else {
2725 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082726 }
[email protected]06c8b082011-01-05 18:00:362727 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:082728 }
2729 bound_renderbuffer_ = info;
2730 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562731}
2732
[email protected]051b1372010-04-12 02:42:082733void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032734 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082735 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032736 if (client_id != 0) {
2737 info = GetTextureInfo(client_id);
2738 if (!info) {
2739 // It's a new id so make a texture info for it.
2740 glGenTextures(1, &service_id);
2741 CreateTextureInfo(client_id, service_id);
2742 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:102743 IdAllocator* id_allocator =
2744 group_->GetIdAllocator(id_namespaces::kTextures);
2745 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032746 }
2747 } else {
2748 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082749 }
[email protected]ae51d192010-04-27 00:48:032750
[email protected]1958e0e2010-04-22 05:17:152751 // Check the texture exists
2752 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032753 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292754 SetGLError(GL_INVALID_OPERATION,
2755 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152756 return;
2757 }
2758 if (info->target() == 0) {
2759 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472760 }
[email protected]ae51d192010-04-27 00:48:032761 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502762 TextureUnit& unit = texture_units_[active_texture_unit_];
2763 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472764 switch (target) {
2765 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502766 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472767 break;
2768 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502769 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472770 break;
2771 default:
2772 NOTREACHED(); // Validation should prevent us getting here.
2773 break;
2774 }
2775}
2776
[email protected]07f54fcc2009-12-22 02:46:302777void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082778 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]b1122982010-05-17 23:04:242779 if (index != 0) {
2780 glDisableVertexAttribArray(index);
2781 }
[email protected]07f54fcc2009-12-22 02:46:302782 } else {
[email protected]8eee29c2010-04-29 03:38:292783 SetGLError(GL_INVALID_VALUE,
2784 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302785 }
2786}
2787
2788void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082789 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302790 glEnableVertexAttribArray(index);
2791 } else {
[email protected]8eee29c2010-04-29 03:38:292792 SetGLError(GL_INVALID_VALUE,
2793 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302794 }
2795}
2796
[email protected]a93bb842010-02-16 23:03:472797void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502798 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]915a59a12010-09-30 21:29:112799 if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) {
[email protected]8eee29c2010-04-29 03:38:292800 SetGLError(GL_INVALID_OPERATION,
2801 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472802 return;
2803 }
2804 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:472805}
2806
[email protected]b273e432010-04-12 17:23:582807bool GLES2DecoderImpl::GetHelper(
2808 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582809 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152810 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2811 switch (pname) {
[email protected]b273e432010-04-12 17:23:582812 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2813 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102814 if (params) {
[email protected]5094b0f2010-11-09 19:45:242815 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:102816 }
[email protected]b273e432010-04-12 17:23:582817 return true;
2818 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2819 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102820 if (params) {
[email protected]5094b0f2010-11-09 19:45:242821 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:102822 }
[email protected]b273e432010-04-12 17:23:582823 return true;
2824 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2825 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102826 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482827 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102828 }
[email protected]b273e432010-04-12 17:23:582829 return true;
2830 case GL_MAX_VARYING_VECTORS:
2831 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102832 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482833 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102834 }
[email protected]b273e432010-04-12 17:23:582835 return true;
2836 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2837 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102838 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482839 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102840 }
[email protected]b273e432010-04-12 17:23:582841 return true;
[email protected]5094b0f2010-11-09 19:45:242842 case GL_MAX_VIEWPORT_DIMS:
2843 if (offscreen_target_frame_buffer_.get()) {
2844 *num_written = 2;
2845 if (params) {
2846 params[0] = renderbuffer_manager()->max_renderbuffer_size();
2847 params[1] = renderbuffer_manager()->max_renderbuffer_size();
2848 }
2849 return true;
2850 }
[email protected]b9363b22010-06-09 22:06:152851 }
2852 }
2853 switch (pname) {
[email protected]656dcaad2010-05-07 17:18:372854 case GL_COMPRESSED_TEXTURE_FORMATS:
2855 *num_written = 0;
2856 // We don't support compressed textures.
2857 return true;
[email protected]b273e432010-04-12 17:23:582858 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
2859 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102860 if (params) {
2861 *params = 0; // We don't support compressed textures.
2862 }
[email protected]b273e432010-04-12 17:23:582863 return true;
2864 case GL_NUM_SHADER_BINARY_FORMATS:
2865 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102866 if (params) {
2867 *params = 0; // We don't support binary shader formats.
2868 }
[email protected]b273e432010-04-12 17:23:582869 return true;
2870 case GL_SHADER_BINARY_FORMATS:
2871 *num_written = 0;
2872 return true; // We don't support binary shader format.s
2873 case GL_SHADER_COMPILER:
2874 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102875 if (params) {
2876 *params = GL_TRUE;
2877 }
[email protected]b273e432010-04-12 17:23:582878 return true;
[email protected]6b8cf1a2010-05-06 16:13:582879 case GL_ARRAY_BUFFER_BINDING:
2880 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102881 if (params) {
2882 if (bound_array_buffer_) {
2883 GLuint client_id = 0;
2884 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
2885 &client_id);
2886 *params = client_id;
2887 } else {
2888 *params = 0;
2889 }
[email protected]6b8cf1a2010-05-06 16:13:582890 }
2891 return true;
2892 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
2893 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102894 if (params) {
2895 if (bound_element_array_buffer_) {
2896 GLuint client_id = 0;
2897 buffer_manager()->GetClientId(
2898 bound_element_array_buffer_->service_id(),
2899 &client_id);
2900 *params = client_id;
2901 } else {
2902 *params = 0;
2903 }
[email protected]6b8cf1a2010-05-06 16:13:582904 }
2905 return true;
2906 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:302907 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:582908 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102909 if (params) {
[email protected]8e3e0662010-08-23 18:46:302910 if (bound_draw_framebuffer_) {
[email protected]4e8a5b122010-05-08 22:00:102911 GLuint client_id = 0;
2912 framebuffer_manager()->GetClientId(
[email protected]8e3e0662010-08-23 18:46:302913 bound_draw_framebuffer_->service_id(), &client_id);
2914 *params = client_id;
2915 } else {
2916 *params = 0;
2917 }
2918 }
2919 return true;
2920 case GL_READ_FRAMEBUFFER_BINDING:
2921 *num_written = 1;
2922 if (params) {
2923 if (bound_read_framebuffer_) {
2924 GLuint client_id = 0;
2925 framebuffer_manager()->GetClientId(
2926 bound_read_framebuffer_->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:102927 *params = client_id;
2928 } else {
2929 *params = 0;
2930 }
[email protected]6b8cf1a2010-05-06 16:13:582931 }
2932 return true;
2933 case GL_RENDERBUFFER_BINDING:
2934 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102935 if (params) {
2936 if (bound_renderbuffer_) {
2937 GLuint client_id = 0;
2938 renderbuffer_manager()->GetClientId(
2939 bound_renderbuffer_->service_id(), &client_id);
2940 *params = client_id;
2941 } else {
2942 *params = 0;
2943 }
[email protected]6b8cf1a2010-05-06 16:13:582944 }
2945 return true;
2946 case GL_CURRENT_PROGRAM:
2947 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102948 if (params) {
2949 if (current_program_) {
2950 GLuint client_id = 0;
2951 program_manager()->GetClientId(
2952 current_program_->service_id(), &client_id);
2953 *params = client_id;
2954 } else {
2955 *params = 0;
2956 }
[email protected]6b8cf1a2010-05-06 16:13:582957 }
2958 return true;
[email protected]4e8a5b122010-05-08 22:00:102959 case GL_TEXTURE_BINDING_2D:
2960 *num_written = 1;
2961 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582962 TextureUnit& unit = texture_units_[active_texture_unit_];
2963 if (unit.bound_texture_2d) {
2964 GLuint client_id = 0;
2965 texture_manager()->GetClientId(
2966 unit.bound_texture_2d->service_id(), &client_id);
2967 *params = client_id;
2968 } else {
2969 *params = 0;
2970 }
[email protected]6b8cf1a2010-05-06 16:13:582971 }
[email protected]4e8a5b122010-05-08 22:00:102972 return true;
2973 case GL_TEXTURE_BINDING_CUBE_MAP:
2974 *num_written = 1;
2975 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582976 TextureUnit& unit = texture_units_[active_texture_unit_];
2977 if (unit.bound_texture_cube_map) {
2978 GLuint client_id = 0;
2979 texture_manager()->GetClientId(
2980 unit.bound_texture_cube_map->service_id(), &client_id);
2981 *params = client_id;
2982 } else {
2983 *params = 0;
2984 }
[email protected]6b8cf1a2010-05-06 16:13:582985 }
[email protected]4e8a5b122010-05-08 22:00:102986 return true;
[email protected]b273e432010-04-12 17:23:582987 default:
[email protected]4e8a5b122010-05-08 22:00:102988 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:532989 return false;
[email protected]b273e432010-04-12 17:23:582990 }
2991}
2992
[email protected]4e8a5b122010-05-08 22:00:102993bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
2994 GLenum pname, GLsizei* num_values) {
2995 return GetHelper(pname, NULL, num_values);
2996}
2997
[email protected]b273e432010-04-12 17:23:582998void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
2999 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103000 GLsizei num_written = 0;
3001 if (GetHelper(pname, NULL, &num_written)) {
3002 scoped_array<GLint> values(new GLint[num_written]);
3003 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583004 for (GLsizei ii = 0; ii < num_written; ++ii) {
3005 params[ii] = static_cast<GLboolean>(values[ii]);
3006 }
3007 } else {
3008 glGetBooleanv(pname, params);
3009 }
3010}
3011
3012void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3013 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103014 GLsizei num_written = 0;
3015 if (GetHelper(pname, NULL, &num_written)) {
3016 scoped_array<GLint> values(new GLint[num_written]);
3017 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583018 for (GLsizei ii = 0; ii < num_written; ++ii) {
3019 params[ii] = static_cast<GLfloat>(values[ii]);
3020 }
3021 } else {
3022 glGetFloatv(pname, params);
3023 }
3024}
3025
3026void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3027 DCHECK(params);
3028 GLsizei num_written;
3029 if (!GetHelper(pname, params, &num_written)) {
3030 glGetIntegerv(pname, params);
3031 }
3032}
3033
[email protected]a0c3e972010-04-21 00:49:133034void GLES2DecoderImpl::DoGetProgramiv(
3035 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583036 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3037 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133038 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133039 return;
3040 }
3041 info->GetProgramiv(pname, params);
3042}
3043
[email protected]558847a2010-03-24 07:02:543044error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3045 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:583046 GLuint program = static_cast<GLuint>(c.program);
3047 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3048 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033049 if (!info) {
[email protected]558847a2010-03-24 07:02:543050 return error::kNoError;
3051 }
3052 GLuint index = static_cast<GLuint>(c.index);
3053 uint32 name_size = c.data_size;
3054 const char* name = GetSharedMemoryAs<const char*>(
3055 c.name_shm_id, c.name_shm_offset, name_size);
3056 if (name == NULL) {
3057 return error::kOutOfBounds;
3058 }
3059 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033060 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543061 return error::kNoError;
3062}
3063
3064error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3065 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583066 GLuint program = static_cast<GLuint>(c.program);
3067 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3068 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033069 if (!info) {
[email protected]558847a2010-03-24 07:02:543070 return error::kNoError;
3071 }
3072 GLuint index = static_cast<GLuint>(c.index);
3073 uint32 name_size = c.data_size;
3074 const char* name = GetImmediateDataAs<const char*>(
3075 c, name_size, immediate_data_size);
3076 if (name == NULL) {
3077 return error::kOutOfBounds;
3078 }
3079 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033080 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543081 return error::kNoError;
3082}
3083
3084error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3085 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583086 GLuint program = static_cast<GLuint>(c.program);
3087 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3088 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033089 if (!info) {
[email protected]558847a2010-03-24 07:02:543090 return error::kNoError;
3091 }
3092 GLuint index = static_cast<GLuint>(c.index);
3093 Bucket* bucket = GetBucket(c.name_bucket_id);
3094 if (!bucket || bucket->size() == 0) {
3095 return error::kInvalidArguments;
3096 }
3097 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183098 if (!bucket->GetAsString(&name_str)) {
3099 return error::kInvalidArguments;
3100 }
[email protected]ae51d192010-04-27 00:48:033101 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543102 return error::kNoError;
3103}
3104
[email protected]f7a64ee2010-02-01 22:24:143105error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463106 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033107 GLuint client_id = c.shader;
3108 if (client_id) {
3109 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3110 if (info) {
[email protected]ca488e12010-12-13 20:06:143111 if (!info->IsDeleted()) {
3112 glDeleteShader(info->service_id());
3113 shader_manager()->MarkAsDeleted(info);
3114 }
[email protected]ae51d192010-04-27 00:48:033115 } else {
[email protected]8eee29c2010-04-29 03:38:293116 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033117 }
[email protected]96449d2c2009-11-25 00:01:323118 }
[email protected]f7a64ee2010-02-01 22:24:143119 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323120}
3121
[email protected]f7a64ee2010-02-01 22:24:143122error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463123 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033124 GLuint client_id = c.program;
3125 if (client_id) {
3126 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3127 if (info) {
[email protected]ca488e12010-12-13 20:06:143128 if (!info->IsDeleted()) {
3129 glDeleteProgram(info->service_id());
3130 program_manager()->MarkAsDeleted(shader_manager(), info);
3131 }
[email protected]ae51d192010-04-27 00:48:033132 } else {
[email protected]8eee29c2010-04-29 03:38:293133 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033134 }
[email protected]96449d2c2009-11-25 00:01:323135 }
[email protected]f7a64ee2010-02-01 22:24:143136 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323137}
3138
[email protected]269200b12010-11-18 22:53:063139void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103140 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3141 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3142 for (GLsizei ii = 0; ii < n; ++ii) {
3143 id_allocator->FreeID(ids[ii]);
3144 }
3145}
3146
[email protected]269200b12010-11-18 22:53:063147error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3148 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103149 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3150 GLsizei n = static_cast<GLsizei>(c.n);
3151 uint32 data_size;
3152 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3153 return error::kOutOfBounds;
3154 }
3155 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3156 c.ids_shm_id, c.ids_shm_offset, data_size);
3157 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063158 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103159 return error::kNoError;
3160 }
3161 if (ids == NULL) {
3162 return error::kOutOfBounds;
3163 }
[email protected]269200b12010-11-18 22:53:063164 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103165 return error::kNoError;
3166}
3167
[email protected]269200b12010-11-18 22:53:063168void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103169 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
3170 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3171 if (id_offset == 0) {
3172 for (GLsizei ii = 0; ii < n; ++ii) {
3173 ids[ii] = id_allocator->AllocateID();
3174 }
3175 } else {
3176 for (GLsizei ii = 0; ii < n; ++ii) {
3177 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3178 id_offset = ids[ii] + 1;
3179 }
3180 }
3181}
3182
[email protected]269200b12010-11-18 22:53:063183error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3184 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103185 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3186 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3187 GLsizei n = static_cast<GLsizei>(c.n);
3188 uint32 data_size;
3189 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3190 return error::kOutOfBounds;
3191 }
3192 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3193 c.ids_shm_id, c.ids_shm_offset, data_size);
3194 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063195 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103196 return error::kNoError;
3197 }
3198 if (ids == NULL) {
3199 return error::kOutOfBounds;
3200 }
[email protected]269200b12010-11-18 22:53:063201 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103202 return error::kNoError;
3203}
3204
[email protected]269200b12010-11-18 22:53:063205void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103206 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3207 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3208 for (GLsizei ii = 0; ii < n; ++ii) {
3209 if (!id_allocator->MarkAsUsed(ids[ii])) {
3210 for (GLsizei jj = 0; jj < ii; ++jj) {
3211 id_allocator->FreeID(ids[jj]);
3212 }
3213 SetGLError(
3214 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063215 "RegisterSharedIdsCHROMIUM: attempt to register "
3216 "id that already exists");
[email protected]066849e32010-05-03 19:14:103217 return;
3218 }
3219 }
3220}
3221
[email protected]269200b12010-11-18 22:53:063222error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3223 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103224 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3225 GLsizei n = static_cast<GLsizei>(c.n);
3226 uint32 data_size;
3227 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3228 return error::kOutOfBounds;
3229 }
3230 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3231 c.ids_shm_id, c.ids_shm_offset, data_size);
3232 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063233 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103234 return error::kNoError;
3235 }
3236 if (ids == NULL) {
3237 return error::kOutOfBounds;
3238 }
[email protected]269200b12010-11-18 22:53:063239 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103240 return error::kNoError;
3241}
3242
[email protected]07f54fcc2009-12-22 02:46:303243void GLES2DecoderImpl::DoDrawArrays(
3244 GLenum mode, GLint first, GLsizei count) {
[email protected]d81e8c52010-06-07 17:58:323245 // We have to check this here because the prototype for glDrawArrays
3246 // is GLint not GLsizei.
3247 if (first < 0) {
[email protected]7601c3f2010-12-22 00:41:203248 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
[email protected]d81e8c52010-06-07 17:58:323249 return;
3250 }
[email protected]6c788fb72010-08-26 02:16:313251
3252 if (count == 0) {
3253 return;
3254 }
3255
[email protected]8fbedc02010-11-18 18:43:403256 GLuint max_vertex_accessed = first + count - 1;
3257 if (IsDrawValid(max_vertex_accessed)) {
3258 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
3259 bool simulated_fixed_attribs = false;
3260 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
3261 bool textures_set = SetBlackTextureForNonRenderableTextures();
3262 glDrawArrays(mode, first, count);
3263 if (textures_set) {
3264 RestoreStateForNonRenderableTextures();
3265 }
3266 if (simulated_fixed_attribs) {
3267 RestoreStateForSimulatedFixedAttribs();
3268 }
[email protected]3916c97e2010-02-25 03:20:503269 }
[email protected]b1122982010-05-17 23:04:243270 if (simulated_attrib_0) {
3271 RestoreStateForSimulatedAttrib0();
3272 }
[email protected]07f54fcc2009-12-22 02:46:303273 }
3274}
3275
[email protected]36cef8ce2010-03-16 07:34:453276void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3277 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033278 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303279 FramebufferManager::FramebufferInfo* framebuffer_info =
3280 GetFramebufferInfoForTarget(target);
3281 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293282 SetGLError(GL_INVALID_OPERATION,
3283 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453284 return;
3285 }
[email protected]ae51d192010-04-27 00:48:033286 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283287 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033288 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283289 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033290 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293291 SetGLError(GL_INVALID_OPERATION,
3292 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033293 return;
3294 }
3295 service_id = info->service_id();
3296 }
[email protected]9edc6b22010-12-23 02:00:263297 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033298 glFramebufferRenderbufferEXT(
3299 target, attachment, renderbuffertarget, service_id);
[email protected]9edc6b22010-12-23 02:00:263300 GLenum error = glGetError();
3301 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303302 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]9edc6b22010-12-23 02:00:263303 if (service_id == 0 ||
3304 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3305 if (info) {
3306 ClearUnclearedRenderbuffers(target, framebuffer_info);
3307 }
[email protected]3a2e7c7b2010-08-06 01:12:283308 }
3309 }
3310}
3311
3312void GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
3313 switch (cap) {
3314 case GL_SCISSOR_TEST:
3315 enable_scissor_test_ = enabled;
3316 break;
3317 default:
3318 break;
3319 }
3320}
3321
3322void GLES2DecoderImpl::DoDisable(GLenum cap) {
3323 SetCapabilityState(cap, false);
3324 glDisable(cap);
3325}
3326
3327void GLES2DecoderImpl::DoEnable(GLenum cap) {
3328 SetCapabilityState(cap, true);
3329 glEnable(cap);
3330}
3331
3332void GLES2DecoderImpl::DoClearColor(
3333 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
3334 clear_red_ = red;
3335 clear_green_ = green;
3336 clear_blue_ = blue;
3337 clear_alpha_ = alpha;
3338 glClearColor(red, green, blue, alpha);
3339}
3340
3341void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
3342 clear_depth_ = depth;
3343 glClearDepth(depth);
3344}
3345
3346void GLES2DecoderImpl::DoClearStencil(GLint s) {
3347 clear_stencil_ = s;
3348 glClearStencil(s);
3349}
3350
3351void GLES2DecoderImpl::DoColorMask(
3352 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
3353 mask_red_ = red;
3354 mask_green_ = green;
3355 mask_blue_ = blue;
3356 mask_alpha_ = alpha;
3357 glColorMask(red, green, blue, alpha);
3358}
3359
3360void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
3361 mask_depth_ = depth;
3362 glDepthMask(depth);
3363}
3364
3365void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
3366 mask_stencil_front_ = mask;
3367 mask_stencil_back_ = mask;
3368 glStencilMask(mask);
3369}
3370
3371void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
3372 if (face == GL_FRONT) {
3373 mask_stencil_front_ = mask;
3374 } else {
3375 mask_stencil_back_ = mask;
3376 }
3377 glStencilMaskSeparate(face, mask);
3378}
3379
3380// NOTE: There's an assumption here that Texture attachments
3381// are cleared because they are textures so we only need to clear
3382// the renderbuffers.
3383void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
[email protected]8e3e0662010-08-23 18:46:303384 GLenum target, FramebufferManager::FramebufferInfo* info) {
3385 if (target == GL_READ_FRAMEBUFFER_EXT) {
3386 // TODO(gman): bind this to the DRAW point, clear then bind back to READ
3387 }
[email protected]3a2e7c7b2010-08-06 01:12:283388 GLbitfield clear_bits = 0;
3389 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
3390 glClearColor(0, 0, 0, 0);
3391 glColorMask(true, true, true, true);
3392 clear_bits |= GL_COLOR_BUFFER_BIT;
3393 }
3394
3395 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
3396 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3397 glClearStencil(0);
3398 glStencilMask(-1);
3399 clear_bits |= GL_STENCIL_BUFFER_BIT;
3400 }
3401
3402 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
3403 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3404 glClearDepth(1.0f);
3405 glDepthMask(true);
3406 clear_bits |= GL_DEPTH_BUFFER_BIT;
3407 }
3408
3409 glDisable(GL_SCISSOR_TEST);
3410 glClear(clear_bits);
3411
3412 info->MarkAttachedRenderbuffersAsCleared();
3413
[email protected]c007aa02010-09-02 22:22:403414 RestoreClearState();
3415
3416 if (target == GL_READ_FRAMEBUFFER_EXT) {
3417 // TODO(gman): rebind draw.
3418 }
3419}
3420
3421void GLES2DecoderImpl::RestoreClearState() {
[email protected]3a2e7c7b2010-08-06 01:12:283422 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
3423 glColorMask(mask_red_, mask_green_, mask_blue_, mask_alpha_);
3424 glClearStencil(clear_stencil_);
3425 glStencilMaskSeparate(GL_FRONT, mask_stencil_front_);
3426 glStencilMaskSeparate(GL_BACK, mask_stencil_back_);
3427 glClearDepth(clear_depth_);
3428 glDepthMask(mask_depth_);
3429 if (enable_scissor_test_) {
3430 glEnable(GL_SCISSOR_TEST);
3431 }
[email protected]36cef8ce2010-03-16 07:34:453432}
3433
3434GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]8e3e0662010-08-23 18:46:303435 FramebufferManager::FramebufferInfo* info =
3436 GetFramebufferInfoForTarget(target);
3437 if (!info) {
[email protected]36cef8ce2010-03-16 07:34:453438 return GL_FRAMEBUFFER_COMPLETE;
3439 }
3440 return glCheckFramebufferStatusEXT(target);
3441}
3442
3443void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033444 GLenum target, GLenum attachment, GLenum textarget,
3445 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303446 FramebufferManager::FramebufferInfo* framebuffer_info =
3447 GetFramebufferInfoForTarget(target);
3448 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293449 SetGLError(GL_INVALID_OPERATION,
3450 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453451 return;
3452 }
[email protected]ae51d192010-04-27 00:48:033453 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283454 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033455 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283456 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033457 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293458 SetGLError(GL_INVALID_OPERATION,
3459 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033460 return;
3461 }
3462 service_id = info->service_id();
3463 }
[email protected]9edc6b22010-12-23 02:00:263464 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033465 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]9edc6b22010-12-23 02:00:263466 GLenum error = glGetError();
3467 if (error == GL_NO_ERROR) {
3468 framebuffer_info->AttachTexture(attachment, info, textarget, level);
3469 if (service_id != 0 &&
3470 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3471 ClearUnclearedRenderbuffers(target, framebuffer_info);
3472 }
[email protected]3a2e7c7b2010-08-06 01:12:283473 }
[email protected]36cef8ce2010-03-16 07:34:453474}
3475
3476void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3477 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303478 FramebufferManager::FramebufferInfo* framebuffer_info =
3479 GetFramebufferInfoForTarget(target);
3480 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293481 SetGLError(GL_INVALID_OPERATION,
3482 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453483 return;
3484 }
3485 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573486 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3487 GLint type = 0;
3488 GLuint client_id = 0;
3489 glGetFramebufferAttachmentParameterivEXT(
3490 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3491 switch (type) {
3492 case GL_RENDERBUFFER: {
3493 renderbuffer_manager()->GetClientId(*params, &client_id);
3494 break;
3495 }
3496 case GL_TEXTURE: {
3497 texture_manager()->GetClientId(*params, &client_id);
3498 break;
3499 }
3500 default:
3501 break;
3502 }
3503 *params = client_id;
3504 }
[email protected]36cef8ce2010-03-16 07:34:453505}
3506
3507void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
3508 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:083509 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293510 SetGLError(GL_INVALID_OPERATION,
3511 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453512 return;
3513 }
[email protected]b71f52c2010-06-18 22:20:203514 if (pname == GL_RENDERBUFFER_INTERNAL_FORMAT) {
3515 *params = bound_renderbuffer_->internal_format();
3516 return;
3517 }
[email protected]36cef8ce2010-03-16 07:34:453518 glGetRenderbufferParameterivEXT(target, pname, params);
3519}
3520
[email protected]8e3e0662010-08-23 18:46:303521void GLES2DecoderImpl::DoBlitFramebufferEXT(
3522 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3523 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3524 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:393525 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303526 SetGLError(GL_INVALID_OPERATION,
3527 "glBlitFramebufferEXT: function not available");
3528 }
[email protected]5094b0f2010-11-09 19:45:243529 if (IsAngle()) {
3530 glBlitFramebufferANGLE(
3531 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3532 } else {
3533 glBlitFramebufferEXT(
3534 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3535 }
[email protected]8e3e0662010-08-23 18:46:303536}
3537
3538void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
3539 GLenum target, GLsizei samples, GLenum internalformat,
3540 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:393541 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303542 SetGLError(GL_INVALID_OPERATION,
3543 "glRenderbufferStorageMultisampleEXT: function not available");
3544 return;
3545 }
[email protected]8e3e0662010-08-23 18:46:303546
[email protected]9edc6b22010-12-23 02:00:263547 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:303548 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263549 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:303550 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263551 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:303552 break;
3553 case GL_RGBA4:
3554 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263555 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:303556 break;
3557 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263558 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:303559 break;
3560 }
3561 }
3562
[email protected]9edc6b22010-12-23 02:00:263563 CopyRealGLErrorsToWrapper();
[email protected]8e3e0662010-08-23 18:46:303564 glRenderbufferStorageMultisampleEXT(
[email protected]9edc6b22010-12-23 02:00:263565 target, samples, impl_format, width, height);
3566 GLenum error = glGetError();
3567 if (error == GL_NO_ERROR) {
3568 bound_renderbuffer_->SetInfo(samples, internalformat, width, height);
3569 }
[email protected]8e3e0662010-08-23 18:46:303570}
3571
[email protected]36cef8ce2010-03-16 07:34:453572void GLES2DecoderImpl::DoRenderbufferStorage(
3573 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:083574 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293575 SetGLError(GL_INVALID_OPERATION,
3576 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453577 return;
3578 }
[email protected]876f6fee2010-08-02 23:10:323579
[email protected]9edc6b22010-12-23 02:00:263580 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:323581 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263582 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:323583 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263584 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:323585 break;
3586 case GL_RGBA4:
3587 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263588 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:323589 break;
3590 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263591 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:323592 break;
3593 }
[email protected]b71f52c2010-06-18 22:20:203594 }
[email protected]876f6fee2010-08-02 23:10:323595
[email protected]9edc6b22010-12-23 02:00:263596 CopyRealGLErrorsToWrapper();
3597 glRenderbufferStorageEXT(target, impl_format, width, height);
3598 GLenum error = glGetError();
3599 if (error == GL_NO_ERROR) {
3600 bound_renderbuffer_->SetInfo(0, internalformat, width, height);
3601 }
[email protected]36cef8ce2010-03-16 07:34:453602}
3603
[email protected]07f54fcc2009-12-22 02:46:303604void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]6b8cf1a2010-05-06 16:13:583605 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3606 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:473607 if (!info) {
[email protected]a93bb842010-02-16 23:03:473608 return;
3609 }
[email protected]d81e8c52010-06-07 17:58:323610 if (!info->CanLink()) {
[email protected]d81e8c52010-06-07 17:58:323611 return;
3612 }
[email protected]ae51d192010-04-27 00:48:033613 glLinkProgram(info->service_id());
[email protected]6b8cf1a2010-05-06 16:13:583614 GLint success = 0;
3615 glGetProgramiv(info->service_id(), GL_LINK_STATUS, &success);
3616 if (success) {
[email protected]a93bb842010-02-16 23:03:473617 info->Update();
[email protected]6b8cf1a2010-05-06 16:13:583618 } else {
3619 info->Reset();
[email protected]07f54fcc2009-12-22 02:46:303620 }
3621};
3622
[email protected]3916c97e2010-02-25 03:20:503623void GLES2DecoderImpl::DoTexParameterf(
3624 GLenum target, GLenum pname, GLfloat param) {
3625 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:303626 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293627 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]07f54fcc2009-12-22 02:46:303628 } else {
[email protected]915a59a12010-09-30 21:29:113629 texture_manager()->SetParameter(
3630 feature_info_, info, pname, static_cast<GLint>(param));
[email protected]3916c97e2010-02-25 03:20:503631 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:303632 }
3633}
3634
[email protected]3916c97e2010-02-25 03:20:503635void GLES2DecoderImpl::DoTexParameteri(
3636 GLenum target, GLenum pname, GLint param) {
3637 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3638 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293639 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503640 } else {
[email protected]915a59a12010-09-30 21:29:113641 texture_manager()->SetParameter(feature_info_, info, pname, param);
[email protected]3916c97e2010-02-25 03:20:503642 glTexParameteri(target, pname, param);
3643 }
3644}
3645
3646void GLES2DecoderImpl::DoTexParameterfv(
3647 GLenum target, GLenum pname, const GLfloat* params) {
3648 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3649 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293650 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503651 } else {
[email protected]ef526492010-06-02 23:12:253652 texture_manager()->SetParameter(
[email protected]915a59a12010-09-30 21:29:113653 feature_info_, info, pname, *reinterpret_cast<const GLint*>(params));
[email protected]3916c97e2010-02-25 03:20:503654 glTexParameterfv(target, pname, params);
3655 }
3656}
3657
3658void GLES2DecoderImpl::DoTexParameteriv(
3659 GLenum target, GLenum pname, const GLint* params) {
3660 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3661 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293662 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:503663 } else {
[email protected]915a59a12010-09-30 21:29:113664 texture_manager()->SetParameter(feature_info_, info, pname, *params);
[email protected]3916c97e2010-02-25 03:20:503665 glTexParameteriv(target, pname, params);
3666 }
3667}
3668
[email protected]939e7362010-05-13 20:49:103669bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:143670 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:103671 // The program does not exist.
3672 SetGLError(GL_INVALID_OPERATION,
3673 (std::string(function_name) + ": no program in use").c_str());
3674 return false;
3675 }
[email protected]ca488e12010-12-13 20:06:143676 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:103677 SetGLError(GL_INVALID_OPERATION,
3678 (std::string(function_name) + ": program not linked").c_str());
3679 return false;
3680 }
3681 return true;
3682}
3683
3684bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
3685 GLint location, const char* function_name) {
3686 if (!CheckCurrentProgram(function_name)) {
3687 return false;
3688 }
3689 return location != -1;
3690}
3691
3692bool GLES2DecoderImpl::GetUniformTypeByLocation(
3693 GLint location, const char* function_name, GLenum* type) {
3694 if (!CheckCurrentProgramForUniform(location, function_name)) {
3695 return false;
3696 }
3697 if (!current_program_->GetUniformTypeByLocation(location, type)) {
3698 SetGLError(GL_INVALID_OPERATION,
3699 (std::string(function_name) + ": program not linked").c_str());
3700 return false;
3701 }
3702 return true;
3703}
3704
3705
3706void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
3707 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:503708 return;
3709 }
3710 current_program_->SetSamplers(location, 1, &v0);
3711 glUniform1i(location, v0);
3712}
3713
3714void GLES2DecoderImpl::DoUniform1iv(
3715 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:103716 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:503717 return;
3718 }
3719 current_program_->SetSamplers(location, count, value);
3720 glUniform1iv(location, count, value);
3721}
3722
[email protected]939e7362010-05-13 20:49:103723void GLES2DecoderImpl::DoUniform1fv(
3724 GLint location, GLsizei count, const GLfloat* value) {
3725 GLenum type;
3726 if (!GetUniformTypeByLocation(location, "glUniform1fv", &type)) {
3727 return;
3728 }
3729 if (type == GL_BOOL) {
3730 scoped_array<GLint> temp(new GLint[count]);
3731 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:533732 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103733 }
3734 DoUniform1iv(location, count, temp.get());
3735 } else {
3736 glUniform1fv(location, count, value);
3737 }
3738}
3739
3740void GLES2DecoderImpl::DoUniform2fv(
3741 GLint location, GLsizei count, const GLfloat* value) {
3742 GLenum type;
3743 if (!GetUniformTypeByLocation(location, "glUniform2fv", &type)) {
3744 return;
3745 }
3746 if (type == GL_BOOL_VEC2) {
3747 GLsizei num_values = count * 2;
3748 scoped_array<GLint> temp(new GLint[num_values]);
3749 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533750 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103751 }
3752 glUniform2iv(location, count, temp.get());
3753 } else {
3754 glUniform2fv(location, count, value);
3755 }
3756}
3757
3758void GLES2DecoderImpl::DoUniform3fv(
3759 GLint location, GLsizei count, const GLfloat* value) {
3760 GLenum type;
3761 if (!GetUniformTypeByLocation(location, "glUniform3fv", &type)) {
3762 return;
3763 }
3764 if (type == GL_BOOL_VEC3) {
3765 GLsizei num_values = count * 3;
3766 scoped_array<GLint> temp(new GLint[num_values]);
3767 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533768 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103769 }
3770 glUniform3iv(location, count, temp.get());
3771 } else {
3772 glUniform3fv(location, count, value);
3773 }
3774}
3775
3776void GLES2DecoderImpl::DoUniform4fv(
3777 GLint location, GLsizei count, const GLfloat* value) {
3778 GLenum type;
3779 if (!GetUniformTypeByLocation(location, "glUniform4fv", &type)) {
3780 return;
3781 }
3782 if (type == GL_BOOL_VEC4) {
3783 GLsizei num_values = count * 4;
3784 scoped_array<GLint> temp(new GLint[num_values]);
3785 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533786 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103787 }
3788 glUniform4iv(location, count, temp.get());
3789 } else {
3790 glUniform4fv(location, count, value);
3791 }
3792}
3793
[email protected]3916c97e2010-02-25 03:20:503794void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:033795 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:503796 ProgramManager::ProgramInfo* info = NULL;
3797 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:583798 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:503799 if (!info) {
[email protected]ae51d192010-04-27 00:48:033800 return;
3801 }
3802 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:503803 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:293804 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:503805 return;
3806 }
[email protected]ae51d192010-04-27 00:48:033807 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:503808 }
[email protected]ca488e12010-12-13 20:06:143809 if (current_program_) {
3810 program_manager()->UnuseProgram(shader_manager(), current_program_);
3811 }
[email protected]3916c97e2010-02-25 03:20:503812 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:143813 if (current_program_) {
3814 program_manager()->UseProgram(current_program_);
3815 }
[email protected]ae51d192010-04-27 00:48:033816 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:503817}
3818
[email protected]96449d2c2009-11-25 00:01:323819GLenum GLES2DecoderImpl::GetGLError() {
3820 // Check the GL error first, then our wrapped error.
3821 GLenum error = glGetError();
3822 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:373823 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:323824 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:293825 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:323826 break;
3827 }
3828 }
3829 }
3830
3831 if (error != GL_NO_ERROR) {
3832 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:293833 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:323834 }
3835 return error;
3836}
3837
[email protected]8eee29c2010-04-29 03:38:293838void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
3839 if (msg) {
3840 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:013841 LOG(ERROR) << last_error_;
[email protected]8eee29c2010-04-29 03:38:293842 }
[email protected]ddd968b82010-03-02 00:44:293843 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:323844}
3845
[email protected]07f54fcc2009-12-22 02:46:303846void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
3847 GLenum error;
3848 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:293849 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:303850 }
3851}
3852
[email protected]6217d392010-03-25 22:08:353853void GLES2DecoderImpl::ClearRealGLErrors() {
3854 GLenum error;
3855 while ((error = glGetError()) != GL_NO_ERROR) {
3856 NOTREACHED() << "GL error " << error << " was unhandled.";
3857 }
3858}
3859
[email protected]ef526492010-06-02 23:12:253860bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:503861 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:253862 // Only check if there are some unrenderable textures.
3863 if (!texture_manager()->HaveUnrenderableTextures()) {
3864 return false;
3865 }
3866 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:503867 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
3868 current_program_->sampler_indices();
3869 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
3870 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
3871 current_program_->GetUniformInfo(sampler_indices[ii]);
3872 DCHECK(uniform_info);
3873 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
3874 GLuint texture_unit_index = uniform_info->texture_units[jj];
3875 if (texture_unit_index < group_->max_texture_units()) {
3876 TextureUnit& texture_unit = texture_units_[texture_unit_index];
3877 TextureManager::TextureInfo* texture_info =
3878 uniform_info->type == GL_SAMPLER_2D ?
3879 texture_unit.bound_texture_2d :
3880 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:113881 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]ef526492010-06-02 23:12:253882 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:503883 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
3884 glBindTexture(
3885 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
3886 GL_TEXTURE_CUBE_MAP,
[email protected]00f893d2010-08-24 18:55:493887 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:503888 }
3889 }
3890 // else: should this be an error?
3891 }
3892 }
[email protected]ef526492010-06-02 23:12:253893 return textures_set;
[email protected]3916c97e2010-02-25 03:20:503894}
3895
3896void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
3897 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:503898 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
3899 current_program_->sampler_indices();
3900 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
3901 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
3902 current_program_->GetUniformInfo(sampler_indices[ii]);
3903 DCHECK(uniform_info);
3904 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
3905 GLuint texture_unit_index = uniform_info->texture_units[jj];
3906 if (texture_unit_index < group_->max_texture_units()) {
3907 TextureUnit& texture_unit = texture_units_[texture_unit_index];
3908 TextureManager::TextureInfo* texture_info =
3909 uniform_info->type == GL_SAMPLER_2D ?
3910 texture_unit.bound_texture_2d :
3911 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:113912 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]3916c97e2010-02-25 03:20:503913 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
3914 // Get the texture info that was previously bound here.
3915 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
3916 texture_unit.bound_texture_2d :
3917 texture_unit.bound_texture_cube_map;
3918 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:033919 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:503920 }
3921 }
3922 }
3923 }
3924 // Set the active texture back to whatever the user had it as.
3925 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:303926}
3927
3928bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:033929 // NOTE: We specifically do not check current_program->IsValid() because
3930 // it could never be invalid since glUseProgram would have failed. While
3931 // glLinkProgram could later mark the program as invalid the previous
3932 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:143933 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:503934 // The program does not exist.
3935 // But GL says no ERROR.
3936 return false;
3937 }
[email protected]f39f4b3f2010-05-12 17:04:083938 // Validate all attribs currently enabled. If they are used by the current
3939 // program then check that they have enough elements to handle the draw call.
3940 // If they are not used by the current program check that they have a buffer
3941 // assigned.
3942 const VertexAttribManager::VertexAttribInfoList& infos =
3943 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
3944 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:403945 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:083946 const VertexAttribManager::VertexAttribInfo* info = *it;
3947 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
3948 current_program_->GetAttribInfoByLocation(info->index());
3949 if (attrib_info) {
3950 // This attrib is used in the current program.
3951 if (!info->CanAccess(max_vertex_accessed)) {
3952 SetGLError(GL_INVALID_OPERATION,
3953 "glDrawXXX: attempt to access out of range vertices");
3954 return false;
3955 }
3956 } else {
3957 // This attrib is not used in the current program.
3958 if (!info->buffer() || info->buffer()->IsDeleted()) {
3959 SetGLError(
3960 GL_INVALID_OPERATION,
3961 "glDrawXXX: attempt to render with no buffer attached to enabled "
3962 "attrib");
3963 return false;
3964 }
[email protected]1d32bc82010-01-13 22:06:463965 }
[email protected]07f54fcc2009-12-22 02:46:303966 }
[email protected]3916c97e2010-02-25 03:20:503967 return true;
[email protected]b1122982010-05-17 23:04:243968}
3969
3970bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
[email protected]876f6fee2010-08-02 23:10:323971 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
3972 return false;
3973
[email protected]b1122982010-05-17 23:04:243974 const VertexAttribManager::VertexAttribInfo* info =
3975 vertex_attrib_manager_.GetVertexAttribInfo(0);
3976 // If it's enabled or it's not used then we don't need to do anything.
3977 if (info->enabled() || !current_program_->GetAttribInfoByLocation(0)) {
3978 return false;
3979 }
3980
3981 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
3982
3983 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
3984
3985 // Make a buffer with a single repeated vec4 value enough to
3986 // simulate the constant value that is supposed to be here.
3987 // This is required to emulate GLES2 on GL.
3988 GLsizei num_vertices = max_vertex_accessed + 1;
3989 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
3990 if (size_needed > attrib_0_size_ ||
3991 info->value().v[0] != attrib_0_value_.v[0] ||
3992 info->value().v[1] != attrib_0_value_.v[1] ||
3993 info->value().v[2] != attrib_0_value_.v[2] ||
3994 info->value().v[3] != attrib_0_value_.v[3]) {
3995 scoped_array<Vec4> temp(new Vec4[num_vertices]);
3996 for (GLsizei ii = 0; ii < num_vertices; ++ii) {
3997 temp[ii] = info->value();
3998 }
3999 glBufferData(
4000 GL_ARRAY_BUFFER,
4001 size_needed,
4002 &temp[0].v[0],
4003 GL_DYNAMIC_DRAW);
4004 attrib_0_value_ = info->value();
4005 attrib_0_size_ = size_needed;
4006 }
4007
4008 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4009
4010 return true;
[email protected]b1122982010-05-17 23:04:244011}
4012
4013void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4014 const VertexAttribManager::VertexAttribInfo* info =
4015 vertex_attrib_manager_.GetVertexAttribInfo(0);
4016 const void* ptr = reinterpret_cast<const void*>(info->offset());
4017 BufferManager::BufferInfo* buffer_info = info->buffer();
4018 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4019 glVertexAttribPointer(
4020 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4021 ptr);
4022 glBindBuffer(GL_ARRAY_BUFFER,
4023 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4024}
[email protected]07f54fcc2009-12-22 02:46:304025
[email protected]8fbedc02010-11-18 18:43:404026bool GLES2DecoderImpl::SimulateFixedAttribs(
4027 GLuint max_vertex_accessed, bool* simulated) {
4028 DCHECK(simulated);
4029 *simulated = false;
4030 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4031 return true;
4032
4033 if (!vertex_attrib_manager_.HaveFixedAttribs()) {
4034 return true;
4035 }
4036
4037 // NOTE: we could be smart and try to check if a buffer is used
4038 // twice in 2 different attribs, find the overlapping parts and therefore
4039 // duplicate the minimum amount of data but this whole code path is not meant
4040 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4041 // tests so we just add to the buffer attrib used.
4042
4043 // Compute the number of elements needed.
4044 int num_vertices = max_vertex_accessed + 1;
4045 int elements_needed = 0;
4046 const VertexAttribManager::VertexAttribInfoList& infos =
4047 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4048 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4049 infos.begin(); it != infos.end(); ++it) {
4050 const VertexAttribManager::VertexAttribInfo* info = *it;
4051 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4052 current_program_->GetAttribInfoByLocation(info->index());
4053 if (attrib_info &&
4054 info->CanAccess(max_vertex_accessed) &&
4055 info->type() == GL_FIXED) {
4056 int elements_used = 0;
4057 if (!SafeMultiply(
4058 static_cast<int>(num_vertices),
4059 info->size(), &elements_used) ||
4060 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4061 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4062 return false;
4063 }
4064 }
4065 }
4066
4067 const int kSizeOfFloat = sizeof(float); // NOLINT
4068 int size_needed = 0;
4069 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed)) {
4070 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4071 return false;
4072 }
4073
4074
4075 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
4076 if (size_needed > fixed_attrib_buffer_size_) {
4077 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4078 }
4079
4080 // Copy the elements and convert to float
4081 GLintptr offset = 0;
4082 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4083 infos.begin(); it != infos.end(); ++it) {
4084 const VertexAttribManager::VertexAttribInfo* info = *it;
4085 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4086 current_program_->GetAttribInfoByLocation(info->index());
4087 if (attrib_info &&
4088 info->CanAccess(max_vertex_accessed) &&
4089 info->type() == GL_FIXED) {
4090 int num_elements = info->size() * kSizeOfFloat;
4091 int size = num_elements * num_vertices;
4092 scoped_array<float> data(new float[size]);
4093 const int32* src = reinterpret_cast<const int32 *>(
4094 info->buffer()->GetRange(info->offset(), size));
4095 const int32* end = src + num_elements;
4096 float* dst = data.get();
4097 while (src != end) {
4098 *dst++ = static_cast<float>(*src++) / 65536.0f;
4099 }
4100 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
4101 glVertexAttribPointer(
4102 info->index(), info->size(), GL_FLOAT, false, 0,
4103 reinterpret_cast<GLvoid*>(offset));
4104 offset += size;
4105 }
4106 }
4107 *simulated = true;
4108 return true;
4109}
4110
4111void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
4112 // There's no need to call glVertexAttribPointer because we shadow all the
4113 // settings and passing GL_FIXED to it will not work.
4114 glBindBuffer(GL_ARRAY_BUFFER,
4115 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4116}
4117
[email protected]f7a64ee2010-02-01 22:24:144118error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:194119 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:504120 if (!bound_element_array_buffer_ ||
4121 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:294122 SetGLError(GL_INVALID_OPERATION,
4123 "glDrawElements: No element array buffer bound");
4124 return error::kNoError;
4125 }
4126
4127 GLenum mode = c.mode;
4128 GLsizei count = c.count;
4129 GLenum type = c.type;
4130 int32 offset = c.index_offset;
4131 if (count < 0) {
4132 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
4133 return error::kNoError;
4134 }
4135 if (offset < 0) {
4136 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
4137 return error::kNoError;
4138 }
[email protected]9438b012010-06-15 22:55:054139 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:294140 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
4141 return error::kNoError;
4142 }
[email protected]9438b012010-06-15 22:55:054143 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294144 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
4145 return error::kNoError;
4146 }
4147
[email protected]6c788fb72010-08-26 02:16:314148 if (count == 0) {
4149 return error::kNoError;
4150 }
4151
[email protected]8eee29c2010-04-29 03:38:294152 GLuint max_vertex_accessed;
4153 if (!bound_element_array_buffer_->GetMaxValueForRange(
4154 offset, count, type, &max_vertex_accessed)) {
4155 SetGLError(GL_INVALID_OPERATION,
4156 "glDrawElements: range out of bounds for buffer");
4157 return error::kNoError;
4158 }
4159
4160 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:244161 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]8fbedc02010-11-18 18:43:404162 bool simulated_fixed_attribs = false;
4163 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4164 bool textures_set = SetBlackTextureForNonRenderableTextures();
4165 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
4166 glDrawElements(mode, count, type, indices);
4167 if (textures_set) {
4168 RestoreStateForNonRenderableTextures();
4169 }
4170 if (simulated_fixed_attribs) {
4171 RestoreStateForSimulatedFixedAttribs();
4172 }
[email protected]ba3176a2009-12-16 18:19:464173 }
[email protected]b1122982010-05-17 23:04:244174 if (simulated_attrib_0) {
4175 RestoreStateForSimulatedAttrib0();
4176 }
[email protected]96449d2c2009-11-25 00:01:324177 }
[email protected]f7a64ee2010-02-01 22:24:144178 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324179}
4180
[email protected]269200b12010-11-18 22:53:064181GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:234182 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
4183 GLuint max_vertex_accessed = 0;
4184 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:294185 if (!info) {
[email protected]ae51d192010-04-27 00:48:034186 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294187 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064188 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:234189 } else {
4190 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:034191 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:064192 SetGLError(
4193 GL_INVALID_OPERATION,
4194 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:234195 }
4196 }
4197 return max_vertex_accessed;
4198}
4199
[email protected]96449d2c2009-11-25 00:01:324200// Calls glShaderSource for the various versions of the ShaderSource command.
4201// Assumes that data / data_size points to a piece of memory that is in range
4202// of whatever context it came from (shared memory, immediate memory, bucket
4203// memory.)
[email protected]45bf5152010-02-12 00:11:314204error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034205 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:584206 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4207 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:314208 if (!info) {
[email protected]45bf5152010-02-12 00:11:314209 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324210 }
[email protected]45bf5152010-02-12 00:11:314211 // Note: We don't actually call glShaderSource here. We wait until
4212 // the call to glCompileShader.
4213 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:144214 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324215}
4216
[email protected]f7a64ee2010-02-01 22:24:144217error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:194218 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:324219 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314220 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:324221 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:464222 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144223 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324224 }
[email protected]ae51d192010-04-27 00:48:034225 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:324226}
4227
[email protected]f7a64ee2010-02-01 22:24:144228error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:194229 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:324230 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314231 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:304232 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464233 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144234 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324235 }
[email protected]ae51d192010-04-27 00:48:034236 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:314237}
4238
[email protected]558847a2010-03-24 07:02:544239error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
4240 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:544241 Bucket* bucket = GetBucket(c.data_bucket_id);
4242 if (!bucket || bucket->size() == 0) {
4243 return error::kInvalidArguments;
4244 }
4245 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034246 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:544247 bucket->size() - 1);
4248}
4249
[email protected]ae51d192010-04-27 00:48:034250void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584251 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4252 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:314253 if (!info) {
[email protected]45bf5152010-02-12 00:11:314254 return;
4255 }
[email protected]de17df392010-04-23 21:09:414256 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
4257 // glShaderSource and then glCompileShader.
4258 const char* shader_src = info->source().c_str();
[email protected]f57bb282010-11-12 00:51:344259 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:184260 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:344261 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:454262 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:234263
[email protected]a550584e2010-09-17 18:01:454264 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:344265 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:184266 return;
4267 }
[email protected]a550584e2010-09-17 18:01:454268 shader_src = translator->translated_shader();
[email protected]de17df392010-04-23 21:09:414269 }
[email protected]de17df392010-04-23 21:09:414270
[email protected]ae51d192010-04-27 00:48:034271 glShaderSource(info->service_id(), 1, &shader_src, NULL);
4272 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:414273 GLint status = GL_FALSE;
4274 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
4275 if (status) {
[email protected]f57bb282010-11-12 00:51:344276 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:414277 } else {
[email protected]d9977d42010-09-01 20:27:024278 // We cannot reach here if we are using the shader translator.
4279 // All invalid shaders must be rejected by the translator.
4280 // All translated shaders must compile.
4281 LOG_IF(ERROR, use_shader_translator_)
4282 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:334283 GLint max_len = 0;
4284 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
4285 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:414286 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:334287 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
4288 DCHECK(max_len == 0 || len < max_len);
4289 DCHECK(len ==0 || temp[len] == '\0');
[email protected]f57bb282010-11-12 00:51:344290 info->SetStatus(false, std::string(temp.get(), len), NULL);
[email protected]e5186162010-06-14 18:54:414291 }
[email protected]45bf5152010-02-12 00:11:314292};
4293
[email protected]ddd968b82010-03-02 00:44:294294void GLES2DecoderImpl::DoGetShaderiv(
4295 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:584296 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4297 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:294298 if (!info) {
[email protected]ddd968b82010-03-02 00:44:294299 return;
4300 }
[email protected]8f1ccdac2010-05-19 21:01:484301 switch (pname) {
4302 case GL_SHADER_SOURCE_LENGTH:
[email protected]e47cbd22010-12-13 18:46:454303 *params = info->source().size() + 1;
[email protected]8f1ccdac2010-05-19 21:01:484304 return;
4305 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:414306 *params = info->IsValid();
4307 return;
[email protected]8f1ccdac2010-05-19 21:01:484308 case GL_INFO_LOG_LENGTH:
[email protected]e5186162010-06-14 18:54:414309 *params = info->log_info().size() + 1;
4310 return;
[email protected]8f1ccdac2010-05-19 21:01:484311 default:
4312 break;
[email protected]ddd968b82010-03-02 00:44:294313 }
[email protected]8f1ccdac2010-05-19 21:01:484314 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:294315}
4316
[email protected]ae51d192010-04-27 00:48:034317error::Error GLES2DecoderImpl::HandleGetShaderSource(
4318 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
4319 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:034320 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4321 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:584322 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4323 shader, "glGetShaderSource");
[email protected]8eee29c2010-04-29 03:38:294324 if (!info) {
4325 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:294326 return error::kNoError;
4327 }
[email protected]262d7aa2010-12-03 22:07:294328 bucket->SetFromString(info->source().c_str());
[email protected]ae51d192010-04-27 00:48:034329 return error::kNoError;
4330}
4331
4332error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
4333 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
4334 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:584335 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4336 Bucket* bucket = CreateBucket(bucket_id);
4337 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4338 program, "glGetProgramInfoLog");
[email protected]ae51d192010-04-27 00:48:034339 if (!info) {
[email protected]ae51d192010-04-27 00:48:034340 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:314341 }
[email protected]262d7aa2010-12-03 22:07:294342 bucket->SetFromString(info->log_info().c_str());
[email protected]ae51d192010-04-27 00:48:034343 return error::kNoError;
4344}
4345
4346error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
4347 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
4348 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:584349 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4350 Bucket* bucket = CreateBucket(bucket_id);
4351 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4352 shader, "glGetShaderInfoLog");
[email protected]ae51d192010-04-27 00:48:034353 if (!info) {
[email protected]6b8cf1a2010-05-06 16:13:584354 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034355 return error::kNoError;
4356 }
[email protected]262d7aa2010-12-03 22:07:294357 bucket->SetFromString(info->log_info().c_str());
[email protected]ae51d192010-04-27 00:48:034358 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324359}
4360
[email protected]1958e0e2010-04-22 05:17:154361bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364362 const BufferManager::BufferInfo* info = GetBufferInfo(client_id);
4363 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154364}
4365
4366bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364367 const FramebufferManager::FramebufferInfo* info =
4368 GetFramebufferInfo(client_id);
4369 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154370}
4371
4372bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364373 // IsProgram is true for programs as soon as they are created, until they are
4374 // deleted and no longer in use.
[email protected]ae51d192010-04-27 00:48:034375 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154376}
4377
4378bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364379 const RenderbufferManager::RenderbufferInfo* info =
4380 GetRenderbufferInfo(client_id);
4381 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154382}
4383
4384bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364385 // IsShader is true for shaders as soon as they are created, until they
4386 // are deleted and not attached to any programs.
[email protected]ae51d192010-04-27 00:48:034387 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154388}
4389
4390bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364391 const TextureManager::TextureInfo* info = GetTextureInfo(client_id);
4392 return info && info->IsValid();
[email protected]ae51d192010-04-27 00:48:034393}
4394
4395void GLES2DecoderImpl::DoAttachShader(
4396 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584397 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4398 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034399 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034400 return;
[email protected]1958e0e2010-04-22 05:17:154401 }
[email protected]6b8cf1a2010-05-06 16:13:584402 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4403 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034404 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034405 return;
4406 }
[email protected]ca488e12010-12-13 20:06:144407 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:314408 SetGLError(GL_INVALID_OPERATION,
4409 "glAttachShader: can not attach more than"
4410 " one shader of the same type.");
4411 return;
4412 }
[email protected]ae51d192010-04-27 00:48:034413 glAttachShader(program_info->service_id(), shader_info->service_id());
4414}
4415
4416void GLES2DecoderImpl::DoDetachShader(
4417 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584418 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4419 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034420 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034421 return;
4422 }
[email protected]6b8cf1a2010-05-06 16:13:584423 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4424 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034425 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034426 return;
4427 }
4428 glDetachShader(program_info->service_id(), shader_info->service_id());
[email protected]ca488e12010-12-13 20:06:144429 program_info->DetachShader(shader_manager(), shader_info);
[email protected]ae51d192010-04-27 00:48:034430}
4431
4432void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584433 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4434 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:034435 if (!info) {
[email protected]ae51d192010-04-27 00:48:034436 return;
4437 }
[email protected]e5186162010-06-14 18:54:414438 if (!info->CanLink()) {
4439 info->set_log_info("Missing Shader");
4440 return;
4441 }
[email protected]ae51d192010-04-27 00:48:034442 glValidateProgram(info->service_id());
[email protected]e5186162010-06-14 18:54:414443 info->UpdateLogInfo();
[email protected]1958e0e2010-04-22 05:17:154444}
4445
[email protected]b1122982010-05-17 23:04:244446void GLES2DecoderImpl::DoGetVertexAttribfv(
4447 GLuint index, GLenum pname, GLfloat* params) {
4448 VertexAttribManager::VertexAttribInfo* info =
4449 vertex_attrib_manager_.GetVertexAttribInfo(index);
4450 if (!info) {
4451 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
4452 return;
4453 }
4454 switch (pname) {
4455 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4456 BufferManager::BufferInfo* buffer = info->buffer();
4457 if (buffer && !buffer->IsDeleted()) {
4458 GLuint client_id;
4459 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4460 *params = static_cast<GLfloat>(client_id);
4461 }
4462 break;
4463 }
4464 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4465 *params = static_cast<GLfloat>(info->enabled());
4466 break;
4467 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4468 *params = static_cast<GLfloat>(info->size());
4469 break;
4470 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4471 *params = static_cast<GLfloat>(info->gl_stride());
4472 break;
4473 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4474 *params = static_cast<GLfloat>(info->type());
4475 break;
4476 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4477 *params = static_cast<GLfloat>(info->normalized());
4478 break;
4479 case GL_CURRENT_VERTEX_ATTRIB:
4480 params[0] = info->value().v[0];
4481 params[1] = info->value().v[1];
4482 params[2] = info->value().v[2];
4483 params[3] = info->value().v[3];
4484 break;
4485 default:
4486 NOTREACHED();
4487 break;
4488 }
4489}
4490
4491void GLES2DecoderImpl::DoGetVertexAttribiv(
4492 GLuint index, GLenum pname, GLint* params) {
4493 VertexAttribManager::VertexAttribInfo* info =
4494 vertex_attrib_manager_.GetVertexAttribInfo(index);
4495 if (!info) {
4496 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
4497 return;
4498 }
4499 switch (pname) {
4500 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4501 BufferManager::BufferInfo* buffer = info->buffer();
4502 if (buffer && !buffer->IsDeleted()) {
4503 GLuint client_id;
4504 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4505 *params = client_id;
4506 }
4507 break;
4508 }
4509 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4510 *params = info->enabled();
4511 break;
4512 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4513 *params = info->size();
4514 break;
4515 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4516 *params = info->gl_stride();
4517 break;
4518 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4519 *params = info->type();
4520 break;
4521 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4522 *params = static_cast<GLint>(info->normalized());
4523 break;
4524 case GL_CURRENT_VERTEX_ATTRIB:
4525 params[0] = static_cast<GLint>(info->value().v[0]);
4526 params[1] = static_cast<GLint>(info->value().v[1]);
4527 params[2] = static_cast<GLint>(info->value().v[2]);
4528 params[3] = static_cast<GLint>(info->value().v[3]);
4529 break;
4530 default:
4531 NOTREACHED();
4532 break;
4533 }
4534}
4535
4536void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
4537 VertexAttribManager::VertexAttribInfo* info =
4538 vertex_attrib_manager_.GetVertexAttribInfo(index);
4539 if (!info) {
4540 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
4541 return;
4542 }
4543 VertexAttribManager::VertexAttribInfo::Vec4 value;
4544 value.v[0] = v0;
4545 value.v[1] = 0.0f;
4546 value.v[2] = 0.0f;
4547 value.v[3] = 1.0f;
4548 info->set_value(value);
4549 glVertexAttrib1f(index, v0);
4550}
4551
4552void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
4553 VertexAttribManager::VertexAttribInfo* info =
4554 vertex_attrib_manager_.GetVertexAttribInfo(index);
4555 if (!info) {
4556 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
4557 return;
4558 }
4559 VertexAttribManager::VertexAttribInfo::Vec4 value;
4560 value.v[0] = v0;
4561 value.v[1] = v1;
4562 value.v[2] = 0.0f;
4563 value.v[3] = 1.0f;
4564 info->set_value(value);
4565 glVertexAttrib2f(index, v0, v1);
4566}
4567
4568void GLES2DecoderImpl::DoVertexAttrib3f(
4569 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
4570 VertexAttribManager::VertexAttribInfo* info =
4571 vertex_attrib_manager_.GetVertexAttribInfo(index);
4572 if (!info) {
4573 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
4574 return;
4575 }
4576 VertexAttribManager::VertexAttribInfo::Vec4 value;
4577 value.v[0] = v0;
4578 value.v[1] = v1;
4579 value.v[2] = v2;
4580 value.v[3] = 1.0f;
4581 info->set_value(value);
4582 glVertexAttrib3f(index, v0, v1, v2);
4583}
4584
4585void GLES2DecoderImpl::DoVertexAttrib4f(
4586 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
4587 VertexAttribManager::VertexAttribInfo* info =
4588 vertex_attrib_manager_.GetVertexAttribInfo(index);
4589 if (!info) {
4590 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
4591 return;
4592 }
4593 VertexAttribManager::VertexAttribInfo::Vec4 value;
4594 value.v[0] = v0;
4595 value.v[1] = v1;
4596 value.v[2] = v2;
4597 value.v[3] = v3;
4598 info->set_value(value);
4599 glVertexAttrib4f(index, v0, v1, v2, v3);
4600}
4601
4602void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
4603 VertexAttribManager::VertexAttribInfo* info =
4604 vertex_attrib_manager_.GetVertexAttribInfo(index);
4605 if (!info) {
4606 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
4607 return;
4608 }
4609 VertexAttribManager::VertexAttribInfo::Vec4 value;
4610 value.v[0] = v[0];
4611 value.v[1] = 0.0f;
4612 value.v[2] = 0.0f;
4613 value.v[3] = 1.0f;
4614 info->set_value(value);
4615 glVertexAttrib1fv(index, v);
4616}
4617
4618void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
4619 VertexAttribManager::VertexAttribInfo* info =
4620 vertex_attrib_manager_.GetVertexAttribInfo(index);
4621 if (!info) {
4622 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
4623 return;
4624 }
4625 VertexAttribManager::VertexAttribInfo::Vec4 value;
4626 value.v[0] = v[0];
4627 value.v[1] = v[1];
4628 value.v[2] = 0.0f;
4629 value.v[3] = 1.0f;
4630 info->set_value(value);
4631 glVertexAttrib2fv(index, v);
4632}
4633
4634void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
4635 VertexAttribManager::VertexAttribInfo* info =
4636 vertex_attrib_manager_.GetVertexAttribInfo(index);
4637 if (!info) {
4638 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
4639 return;
4640 }
4641 VertexAttribManager::VertexAttribInfo::Vec4 value;
4642 value.v[0] = v[0];
4643 value.v[1] = v[1];
4644 value.v[2] = v[2];
4645 value.v[3] = 1.0f;
4646 info->set_value(value);
4647 glVertexAttrib3fv(index, v);
4648}
4649
4650void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
4651 VertexAttribManager::VertexAttribInfo* info =
4652 vertex_attrib_manager_.GetVertexAttribInfo(index);
4653 if (!info) {
4654 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
4655 return;
4656 }
4657 VertexAttribManager::VertexAttribInfo::Vec4 value;
4658 value.v[0] = v[0];
4659 value.v[1] = v[1];
4660 value.v[2] = v[2];
4661 value.v[3] = v[3];
4662 info->set_value(value);
4663 glVertexAttrib4fv(index, v);
4664}
4665
[email protected]f7a64ee2010-02-01 22:24:144666error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:194667 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:294668 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
4669 SetGLError(GL_INVALID_VALUE,
4670 "glVertexAttribPointer: no array buffer bound");
4671 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324672 }
[email protected]8eee29c2010-04-29 03:38:294673
4674 GLuint indx = c.indx;
4675 GLint size = c.size;
4676 GLenum type = c.type;
4677 GLboolean normalized = c.normalized;
4678 GLsizei stride = c.stride;
4679 GLsizei offset = c.offset;
4680 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:054681 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294682 SetGLError(GL_INVALID_ENUM,
4683 "glVertexAttribPointer: type GL_INVALID_ENUM");
4684 return error::kNoError;
4685 }
[email protected]9438b012010-06-15 22:55:054686 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:314687 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:294688 "glVertexAttribPointer: size GL_INVALID_VALUE");
4689 return error::kNoError;
4690 }
4691 if (indx >= group_->max_vertex_attribs()) {
4692 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
4693 return error::kNoError;
4694 }
4695 if (stride < 0) {
4696 SetGLError(GL_INVALID_VALUE,
4697 "glVertexAttribPointer: stride < 0");
4698 return error::kNoError;
4699 }
4700 if (stride > 255) {
4701 SetGLError(GL_INVALID_VALUE,
4702 "glVertexAttribPointer: stride > 255");
4703 return error::kNoError;
4704 }
4705 if (offset < 0) {
4706 SetGLError(GL_INVALID_VALUE,
4707 "glVertexAttribPointer: offset < 0");
4708 return error::kNoError;
4709 }
4710 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:314711 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:294712 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:314713 SetGLError(GL_INVALID_OPERATION,
4714 "glVertexAttribPointer: offset not valid for type");
4715 return error::kNoError;
4716 }
4717 if (stride % component_size > 0) {
4718 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:294719 "glVertexAttribPointer: stride not valid for type");
4720 return error::kNoError;
4721 }
[email protected]8fbedc02010-11-18 18:43:404722 vertex_attrib_manager_.SetAttribInfo(
4723 indx,
[email protected]8eee29c2010-04-29 03:38:294724 bound_array_buffer_,
4725 size,
4726 type,
[email protected]b1122982010-05-17 23:04:244727 normalized,
4728 stride,
4729 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:294730 offset);
[email protected]8fbedc02010-11-18 18:43:404731 if (type != GL_FIXED) {
4732 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
4733 }
[email protected]f7a64ee2010-02-01 22:24:144734 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324735}
4736
[email protected]f7a64ee2010-02-01 22:24:144737error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:194738 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:314739 GLint x = c.x;
4740 GLint y = c.y;
4741 GLsizei width = c.width;
4742 GLsizei height = c.height;
4743 GLenum format = c.format;
4744 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:564745 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:294746 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:564747 return error::kNoError;
4748 }
[email protected]a51788e2010-02-24 21:54:254749 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:184750 uint32 pixels_size;
4751 if (!GLES2Util::ComputeImageDataSize(
4752 width, height, format, type, pack_alignment_, &pixels_size)) {
4753 return error::kOutOfBounds;
4754 }
[email protected]612d2f82009-12-08 20:49:314755 void* pixels = GetSharedMemoryAs<void*>(
4756 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:254757 Result* result = GetSharedMemoryAs<Result*>(
4758 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4759 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:144760 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464761 }
[email protected]a51788e2010-02-24 21:54:254762
[email protected]9438b012010-06-15 22:55:054763 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:294764 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
4765 return error::kNoError;
4766 }
[email protected]9438b012010-06-15 22:55:054767 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294768 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:124769 return error::kNoError;
4770 }
[email protected]57f223832010-03-19 01:57:564771 if (width == 0 || height == 0) {
4772 return error::kNoError;
4773 }
4774
4775 CopyRealGLErrorsToWrapper();
4776
[email protected]34ff8b0c2010-10-01 20:06:024777 ScopedResolvedFrameBufferBinder binder(this);
4778
[email protected]57f223832010-03-19 01:57:564779 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:304780 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:564781
4782 GLint max_x;
4783 GLint max_y;
4784 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:294785 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:144786 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:314787 }
[email protected]57f223832010-03-19 01:57:564788
[email protected]d37231fa2010-04-09 21:16:024789 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:564790 // The user requested an out of range area. Get the results 1 line
4791 // at a time.
4792 uint32 temp_size;
4793 if (!GLES2Util::ComputeImageDataSize(
4794 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:294795 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564796 return error::kNoError;
4797 }
4798 GLsizei unpadded_row_size = temp_size;
4799 if (!GLES2Util::ComputeImageDataSize(
4800 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:294801 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564802 return error::kNoError;
4803 }
4804 GLsizei padded_row_size = temp_size - unpadded_row_size;
4805 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:294806 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564807 return error::kNoError;
4808 }
4809
4810 GLint dest_x_offset = std::max(-x, 0);
4811 uint32 dest_row_offset;
4812 if (!GLES2Util::ComputeImageDataSize(
4813 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:294814 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:564815 return error::kNoError;
4816 }
4817
4818 // Copy each row into the larger dest rect.
4819 int8* dst = static_cast<int8*>(pixels);
4820 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:024821 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:564822 GLint read_width = read_end_x - read_x;
4823 for (GLint yy = 0; yy < height; ++yy) {
4824 GLint ry = y + yy;
4825
4826 // Clear the row.
4827 memset(dst, 0, unpadded_row_size);
4828
4829 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:024830 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:564831 glReadPixels(
4832 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
4833 }
4834 dst += padded_row_size;
4835 }
4836 } else {
4837 glReadPixels(x, y, width, height, format, type, pixels);
4838 }
[email protected]a51788e2010-02-24 21:54:254839 GLenum error = glGetError();
4840 if (error == GL_NO_ERROR) {
4841 *result = true;
4842 } else {
[email protected]8eee29c2010-04-29 03:38:294843 SetGLError(error, NULL);
[email protected]a51788e2010-02-24 21:54:254844 }
[email protected]f7a64ee2010-02-01 22:24:144845 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324846}
4847
[email protected]f7a64ee2010-02-01 22:24:144848error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:194849 uint32 immediate_data_size, const gles2::PixelStorei& c) {
4850 GLenum pname = c.pname;
4851 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:054852 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:294853 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:124854 return error::kNoError;
4855 }
[email protected]9438b012010-06-15 22:55:054856 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:294857 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:144858 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194859 }
4860 glPixelStorei(pname, param);
4861 switch (pname) {
4862 case GL_PACK_ALIGNMENT:
4863 pack_alignment_ = param;
4864 break;
4865 case GL_UNPACK_ALIGNMENT:
4866 unpack_alignment_ = param;
4867 break;
4868 default:
4869 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:374870 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:194871 break;
4872 }
[email protected]f7a64ee2010-02-01 22:24:144873 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194874}
4875
[email protected]558847a2010-03-24 07:02:544876error::Error GLES2DecoderImpl::GetAttribLocationHelper(
4877 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
4878 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:584879 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4880 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:034881 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:144882 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194883 }
[email protected]ae51d192010-04-27 00:48:034884 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:294885 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:254886 return error::kNoError;
4887 }
[email protected]b9849abf2009-11-25 19:13:194888 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:544889 location_shm_id, location_shm_offset, sizeof(GLint));
4890 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:144891 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194892 }
[email protected]558847a2010-03-24 07:02:544893 // Require the client to init this incase the context is lost and we are no
4894 // longer executing commands.
4895 if (*location != -1) {
4896 return error::kGenericError;
4897 }
[email protected]0bfd9882010-02-05 23:02:254898 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:144899 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194900}
4901
[email protected]558847a2010-03-24 07:02:544902error::Error GLES2DecoderImpl::HandleGetAttribLocation(
4903 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
4904 uint32 name_size = c.data_size;
4905 const char* name = GetSharedMemoryAs<const char*>(
4906 c.name_shm_id, c.name_shm_offset, name_size);
4907 if (!name) {
4908 return error::kOutOfBounds;
4909 }
4910 String name_str(name, name_size);
4911 return GetAttribLocationHelper(
4912 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4913}
4914
[email protected]f7a64ee2010-02-01 22:24:144915error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:194916 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:544917 uint32 name_size = c.data_size;
4918 const char* name = GetImmediateDataAs<const char*>(
4919 c, name_size, immediate_data_size);
4920 if (!name) {
4921 return error::kOutOfBounds;
4922 }
4923 String name_str(name, name_size);
4924 return GetAttribLocationHelper(
4925 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4926}
4927
4928error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
4929 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
4930 Bucket* bucket = GetBucket(c.name_bucket_id);
4931 if (!bucket) {
4932 return error::kInvalidArguments;
4933 }
4934 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184935 if (!bucket->GetAsString(&name_str)) {
4936 return error::kInvalidArguments;
4937 }
[email protected]558847a2010-03-24 07:02:544938 return GetAttribLocationHelper(
4939 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4940}
4941
4942error::Error GLES2DecoderImpl::GetUniformLocationHelper(
4943 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
4944 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:584945 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4946 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:034947 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:144948 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194949 }
[email protected]ae51d192010-04-27 00:48:034950 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:294951 SetGLError(GL_INVALID_OPERATION,
4952 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:254953 return error::kNoError;
4954 }
[email protected]b9849abf2009-11-25 19:13:194955 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:544956 location_shm_id, location_shm_offset, sizeof(GLint));
4957 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:144958 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194959 }
[email protected]558847a2010-03-24 07:02:544960 // Require the client to init this incase the context is lost an we are no
4961 // longer executing commands.
4962 if (*location != -1) {
4963 return error::kGenericError;
4964 }
4965 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:144966 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194967}
4968
[email protected]f7a64ee2010-02-01 22:24:144969error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:194970 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:194971 uint32 name_size = c.data_size;
4972 const char* name = GetSharedMemoryAs<const char*>(
4973 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:544974 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:144975 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194976 }
4977 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:544978 return GetUniformLocationHelper(
4979 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:194980}
4981
[email protected]f7a64ee2010-02-01 22:24:144982error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:194983 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:194984 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:304985 const char* name = GetImmediateDataAs<const char*>(
4986 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:544987 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:144988 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194989 }
4990 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:544991 return GetUniformLocationHelper(
4992 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4993}
4994
4995error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
4996 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
4997 Bucket* bucket = GetBucket(c.name_bucket_id);
4998 if (!bucket) {
4999 return error::kInvalidArguments;
5000 }
5001 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185002 if (!bucket->GetAsString(&name_str)) {
5003 return error::kInvalidArguments;
5004 }
[email protected]558847a2010-03-24 07:02:545005 return GetUniformLocationHelper(
5006 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195007}
5008
[email protected]ddd968b82010-03-02 00:44:295009error::Error GLES2DecoderImpl::HandleGetString(
5010 uint32 immediate_data_size, const gles2::GetString& c) {
5011 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:055012 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:295013 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:295014 return error::kNoError;
5015 }
[email protected]1958e0e2010-04-22 05:17:155016 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
5017 const char* str = NULL;
5018 switch (name) {
5019 case GL_VERSION:
5020 str = "OpenGL ES 2.0 Chromium";
5021 break;
5022 case GL_SHADING_LANGUAGE_VERSION:
5023 str = "OpenGL ES GLSL ES 1.0 Chromium";
5024 break;
5025 case GL_EXTENSIONS:
[email protected]915a59a12010-09-30 21:29:115026 str = feature_info_->extensions().c_str();
[email protected]1958e0e2010-04-22 05:17:155027 break;
5028 default:
5029 str = gl_str;
5030 break;
5031 }
[email protected]ddd968b82010-03-02 00:44:295032 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:155033 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:295034 return error::kNoError;
5035}
5036
[email protected]0c86dbf2010-03-05 08:14:115037void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:155038 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:055039 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295040 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
5041 return;
5042 }
[email protected]9438b012010-06-15 22:55:055043 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:295044 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:115045 return;
[email protected]3b6ec202010-03-05 05:16:235046 }
5047 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:295048 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:285049 return;
[email protected]3b6ec202010-03-05 05:16:235050 }
5051 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
5052 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295053 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285054 return;
[email protected]3b6ec202010-03-05 05:16:235055 }
5056 // Clear the buffer to 0 if no initial data was passed in.
5057 scoped_array<int8> zero;
5058 if (!data) {
5059 zero.reset(new int8[size]);
5060 memset(zero.get(), 0, size);
5061 data = zero.get();
5062 }
5063 CopyRealGLErrorsToWrapper();
5064 glBufferData(target, size, data, usage);
5065 GLenum error = glGetError();
5066 if (error != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:295067 SetGLError(error, NULL);
[email protected]3b6ec202010-03-05 05:16:235068 } else {
[email protected]4e8a5b122010-05-08 22:00:105069 buffer_manager()->SetSize(info, size);
[email protected]0c86dbf2010-03-05 08:14:115070 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:235071 }
[email protected]0c86dbf2010-03-05 08:14:115072}
5073
5074error::Error GLES2DecoderImpl::HandleBufferData(
5075 uint32 immediate_data_size, const gles2::BufferData& c) {
5076 GLenum target = static_cast<GLenum>(c.target);
5077 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
5078 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5079 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5080 GLenum usage = static_cast<GLenum>(c.usage);
5081 const void* data = NULL;
5082 if (data_shm_id != 0 || data_shm_offset != 0) {
5083 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
5084 if (!data) {
5085 return error::kOutOfBounds;
5086 }
5087 }
5088 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:145089 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195090}
5091
[email protected]f7a64ee2010-02-01 22:24:145092error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:195093 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
5094 GLenum target = static_cast<GLenum>(c.target);
5095 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:305096 const void* data = GetImmediateDataAs<const void*>(
5097 c, size, immediate_data_size);
5098 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145099 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:305100 }
[email protected]b9849abf2009-11-25 19:13:195101 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:115102 DoBufferData(target, size, data, usage);
5103 return error::kNoError;
5104}
5105
5106void GLES2DecoderImpl::DoBufferSubData(
5107 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:505108 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475109 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295110 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285111 return;
[email protected]a93bb842010-02-16 23:03:475112 }
[email protected]0c86dbf2010-03-05 08:14:115113 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:295114 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]07f54fcc2009-12-22 02:46:305115 } else {
[email protected]0c86dbf2010-03-05 08:14:115116 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:305117 }
[email protected]b9849abf2009-11-25 19:13:195118}
5119
[email protected]a93bb842010-02-16 23:03:475120error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
5121 GLenum target,
5122 GLint level,
5123 GLenum internal_format,
5124 GLsizei width,
5125 GLsizei height,
5126 GLint border,
5127 GLsizei image_size,
5128 const void* data) {
[email protected]a93bb842010-02-16 23:03:475129 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:055130 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295131 SetGLError(GL_INVALID_ENUM,
5132 "glCompressedTexImage2D: target GL_INVALID_ENUM");
5133 return error::kNoError;
5134 }
[email protected]9438b012010-06-15 22:55:055135 if (!validators_->compressed_texture_format.IsValid(
5136 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295137 SetGLError(GL_INVALID_ENUM,
5138 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:475139 return error::kNoError;
5140 }
[email protected]915a59a12010-09-30 21:29:115141 if (!texture_manager()->ValidForTarget(
5142 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475143 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295144 SetGLError(GL_INVALID_VALUE,
5145 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475146 return error::kNoError;
5147 }
[email protected]3916c97e2010-02-25 03:20:505148 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475149 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295150 SetGLError(GL_INVALID_VALUE,
5151 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:475152 return error::kNoError;
5153 }
5154 scoped_array<int8> zero;
5155 if (!data) {
5156 zero.reset(new int8[image_size]);
5157 memset(zero.get(), 0, image_size);
5158 data = zero.get();
5159 }
[email protected]cadde4a2010-07-31 17:10:435160 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475161 glCompressedTexImage2D(
5162 target, level, internal_format, width, height, border, image_size, data);
[email protected]cadde4a2010-07-31 17:10:435163 GLenum error = glGetError();
5164 if (error == GL_NO_ERROR) {
5165 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115166 feature_info_,
[email protected]cadde4a2010-07-31 17:10:435167 info, target, level, internal_format, width, height, 1, border, 0, 0);
5168 }
[email protected]a93bb842010-02-16 23:03:475169 return error::kNoError;
5170}
5171
[email protected]f7a64ee2010-02-01 22:24:145172error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195173 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
5174 GLenum target = static_cast<GLenum>(c.target);
5175 GLint level = static_cast<GLint>(c.level);
5176 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5177 GLsizei width = static_cast<GLsizei>(c.width);
5178 GLsizei height = static_cast<GLsizei>(c.height);
5179 GLint border = static_cast<GLint>(c.border);
5180 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
5181 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5182 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5183 const void* data = NULL;
5184 if (data_shm_id != 0 || data_shm_offset != 0) {
5185 data = GetSharedMemoryAs<const void*>(
5186 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:465187 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145188 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195189 }
5190 }
[email protected]a93bb842010-02-16 23:03:475191 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195192 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:195193}
5194
[email protected]f7a64ee2010-02-01 22:24:145195error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195196 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
5197 GLenum target = static_cast<GLenum>(c.target);
5198 GLint level = static_cast<GLint>(c.level);
5199 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5200 GLsizei width = static_cast<GLsizei>(c.width);
5201 GLsizei height = static_cast<GLsizei>(c.height);
5202 GLint border = static_cast<GLint>(c.border);
5203 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:305204 const void* data = GetImmediateDataAs<const void*>(
5205 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465206 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145207 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465208 }
[email protected]a93bb842010-02-16 23:03:475209 return DoCompressedTexImage2D(
5210 target, level, internal_format, width, height, border, image_size, data);
5211}
5212
[email protected]b6140d02010-05-17 14:47:165213error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
5214 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
5215 GLenum target = static_cast<GLenum>(c.target);
5216 GLint level = static_cast<GLint>(c.level);
5217 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5218 GLsizei width = static_cast<GLsizei>(c.width);
5219 GLsizei height = static_cast<GLsizei>(c.height);
5220 GLint border = static_cast<GLint>(c.border);
5221 Bucket* bucket = GetBucket(c.bucket_id);
5222 return DoCompressedTexImage2D(
5223 target, level, internal_format, width, height, border,
5224 bucket->size(), bucket->GetData(0, bucket->size()));
5225}
5226
5227error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
5228 uint32 immediate_data_size,
5229 const gles2::CompressedTexSubImage2DBucket& c) {
5230 GLenum target = static_cast<GLenum>(c.target);
5231 GLint level = static_cast<GLint>(c.level);
5232 GLint xoffset = static_cast<GLint>(c.xoffset);
5233 GLint yoffset = static_cast<GLint>(c.yoffset);
5234 GLsizei width = static_cast<GLsizei>(c.width);
5235 GLsizei height = static_cast<GLsizei>(c.height);
5236 GLenum format = static_cast<GLenum>(c.format);
5237 Bucket* bucket = GetBucket(c.bucket_id);
5238 uint32 data_size = bucket->size();
5239 GLsizei imageSize = data_size;
5240 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:055241 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:165242 SetGLError(
5243 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
5244 return error::kNoError;
5245 }
[email protected]9438b012010-06-15 22:55:055246 if (!validators_->compressed_texture_format.IsValid(format)) {
5247 SetGLError(GL_INVALID_ENUM,
5248 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
5249 return error::kNoError;
5250 }
[email protected]b6140d02010-05-17 14:47:165251 if (width < 0) {
5252 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
5253 return error::kNoError;
5254 }
5255 if (height < 0) {
5256 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
5257 return error::kNoError;
5258 }
5259 if (imageSize < 0) {
5260 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
5261 return error::kNoError;
5262 }
[email protected]cadde4a2010-07-31 17:10:435263 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:165264 target, level, xoffset, yoffset, width, height, format, imageSize, data);
5265 return error::kNoError;
5266}
5267
[email protected]a93bb842010-02-16 23:03:475268error::Error GLES2DecoderImpl::DoTexImage2D(
5269 GLenum target,
5270 GLint level,
5271 GLenum internal_format,
5272 GLsizei width,
5273 GLsizei height,
5274 GLint border,
5275 GLenum format,
5276 GLenum type,
5277 const void* pixels,
5278 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:055279 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295280 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
5281 return error::kNoError;
5282 }
[email protected]9438b012010-06-15 22:55:055283 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295284 SetGLError(GL_INVALID_ENUM,
5285 "glTexImage2D: internal_format GL_INVALID_ENUM");
5286 return error::kNoError;
5287 }
[email protected]9438b012010-06-15 22:55:055288 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295289 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
5290 return error::kNoError;
5291 }
[email protected]9438b012010-06-15 22:55:055292 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295293 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145294 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195295 }
[email protected]7b92c412010-07-20 17:48:255296 if (format != internal_format) {
5297 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
5298 return error::kNoError;
5299 }
[email protected]915a59a12010-09-30 21:29:115300 if (!texture_manager()->ValidForTarget(
5301 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475302 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295303 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475304 return error::kNoError;
5305 }
[email protected]3916c97e2010-02-25 03:20:505306 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475307 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295308 SetGLError(GL_INVALID_OPERATION,
5309 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:475310 return error::kNoError;
5311 }
5312 scoped_array<int8> zero;
5313 if (!pixels) {
5314 zero.reset(new int8[pixels_size]);
5315 memset(zero.get(), 0, pixels_size);
5316 pixels = zero.get();
5317 }
[email protected]876f6fee2010-08-02 23:10:325318
[email protected]f5719fb2010-08-04 18:27:185319 GLenum gl_internal_format = internal_format;
[email protected]876f6fee2010-08-02 23:10:325320 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
5321 if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
[email protected]f5719fb2010-08-04 18:27:185322 gl_internal_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:325323 } else if (type == GL_FLOAT) {
5324 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:185325 gl_internal_format = GL_RGBA32F_ARB;
[email protected]876f6fee2010-08-02 23:10:325326 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:185327 gl_internal_format = GL_RGB32F_ARB;
[email protected]876f6fee2010-08-02 23:10:325328 }
5329 } else if (type == GL_HALF_FLOAT_OES) {
5330 if (format == GL_RGBA) {
[email protected]f5719fb2010-08-04 18:27:185331 gl_internal_format = GL_RGBA16F_ARB;
[email protected]876f6fee2010-08-02 23:10:325332 } else if (format == GL_RGB) {
[email protected]f5719fb2010-08-04 18:27:185333 gl_internal_format = GL_RGB16F_ARB;
[email protected]876f6fee2010-08-02 23:10:325334 }
[email protected]7b92c412010-07-20 17:48:255335 }
[email protected]7488d962010-07-16 02:41:585336 }
[email protected]876f6fee2010-08-02 23:10:325337
[email protected]cadde4a2010-07-31 17:10:435338 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475339 glTexImage2D(
[email protected]f5719fb2010-08-04 18:27:185340 target, level, gl_internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475341 pixels);
[email protected]cadde4a2010-07-31 17:10:435342 GLenum error = glGetError();
5343 if (error == GL_NO_ERROR) {
[email protected]915a59a12010-09-30 21:29:115344 texture_manager()->SetLevelInfo(feature_info_, info,
[email protected]cadde4a2010-07-31 17:10:435345 target, level, internal_format, width, height, 1, border, format, type);
5346 }
[email protected]f7a64ee2010-02-01 22:24:145347 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195348}
5349
[email protected]f7a64ee2010-02-01 22:24:145350error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195351 uint32 immediate_data_size, const gles2::TexImage2D& c) {
5352 GLenum target = static_cast<GLenum>(c.target);
5353 GLint level = static_cast<GLint>(c.level);
5354 GLint internal_format = static_cast<GLint>(c.internalformat);
5355 GLsizei width = static_cast<GLsizei>(c.width);
5356 GLsizei height = static_cast<GLsizei>(c.height);
5357 GLint border = static_cast<GLint>(c.border);
5358 GLenum format = static_cast<GLenum>(c.format);
5359 GLenum type = static_cast<GLenum>(c.type);
5360 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
5361 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:185362 uint32 pixels_size;
5363 if (!GLES2Util::ComputeImageDataSize(
5364 width, height, format, type, unpack_alignment_, &pixels_size)) {
5365 return error::kOutOfBounds;
5366 }
[email protected]b9849abf2009-11-25 19:13:195367 const void* pixels = NULL;
5368 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
5369 pixels = GetSharedMemoryAs<const void*>(
5370 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:465371 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145372 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195373 }
5374 }
[email protected]a93bb842010-02-16 23:03:475375 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195376 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475377 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:195378}
5379
[email protected]f7a64ee2010-02-01 22:24:145380error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195381 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
5382 GLenum target = static_cast<GLenum>(c.target);
5383 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:465384 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:195385 GLsizei width = static_cast<GLsizei>(c.width);
5386 GLsizei height = static_cast<GLsizei>(c.height);
5387 GLint border = static_cast<GLint>(c.border);
5388 GLenum format = static_cast<GLenum>(c.format);
5389 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:185390 uint32 size;
5391 if (!GLES2Util::ComputeImageDataSize(
5392 width, height, format, type, unpack_alignment_, &size)) {
5393 return error::kOutOfBounds;
5394 }
[email protected]07f54fcc2009-12-22 02:46:305395 const void* pixels = GetImmediateDataAs<const void*>(
5396 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465397 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145398 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465399 }
[email protected]a93bb842010-02-16 23:03:475400 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:465401 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475402 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:145403 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325404}
5405
[email protected]cadde4a2010-07-31 17:10:435406void GLES2DecoderImpl::DoCompressedTexSubImage2D(
5407 GLenum target,
5408 GLint level,
5409 GLint xoffset,
5410 GLint yoffset,
5411 GLsizei width,
5412 GLsizei height,
5413 GLenum format,
5414 GLsizei image_size,
5415 const void * data) {
5416 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5417 if (!info) {
5418 SetGLError(GL_INVALID_OPERATION,
5419 "glCompressedTexSubImage2D: unknown texture for target");
5420 return;
5421 }
5422 GLenum type = 0;
5423 GLenum dummy = 0;
5424 if (!info->GetLevelType(target, level, &type, &dummy) ||
5425 !info->ValidForTexture(
5426 target, level, xoffset, yoffset, width, height, format, type)) {
5427 SetGLError(GL_INVALID_VALUE,
5428 "glCompressdTexSubImage2D: bad dimensions.");
5429 return;
5430 }
5431 glCompressedTexSubImage2D(
5432 target, level, xoffset, yoffset, width, height, format, image_size, data);
5433}
5434
[email protected]6e288612010-12-21 20:45:035435static void Clip(
5436 GLint start, GLint range, GLint sourceRange,
5437 GLint* out_start, GLint* out_range) {
5438 DCHECK(out_start);
5439 DCHECK(out_range);
5440 if (start < 0) {
5441 range += start;
5442 start = 0;
5443 }
5444 GLint end = start + range;
5445 if (end > sourceRange) {
5446 range -= end - sourceRange;
5447 }
5448 *out_start = start;
5449 *out_range = range;
5450}
5451
5452
[email protected]cadde4a2010-07-31 17:10:435453void GLES2DecoderImpl::DoCopyTexImage2D(
5454 GLenum target,
5455 GLint level,
5456 GLenum internal_format,
5457 GLint x,
5458 GLint y,
5459 GLsizei width,
5460 GLsizei height,
5461 GLint border) {
5462 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5463 if (!info) {
5464 SetGLError(GL_INVALID_OPERATION,
5465 "glCopyTexImage2D: unknown texture for target");
5466 return;
5467 }
[email protected]915a59a12010-09-30 21:29:115468 if (!texture_manager()->ValidForTarget(
5469 feature_info_, target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:185470 border != 0) {
5471 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
5472 return;
5473 }
5474
[email protected]9edc6b22010-12-23 02:00:265475 // Check we have compatible formats.
5476 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5477 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5478 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
5479
5480 if ((channels_needed & channels_exist) != channels_needed) {
5481 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
5482 return;
5483 }
5484
[email protected]cadde4a2010-07-31 17:10:435485 CopyRealGLErrorsToWrapper();
[email protected]34ff8b0c2010-10-01 20:06:025486 ScopedResolvedFrameBufferBinder binder(this);
[email protected]6e288612010-12-21 20:45:035487 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:265488
5489 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:035490 GLint copyX = 0;
5491 GLint copyY = 0;
5492 GLint copyWidth = 0;
5493 GLint copyHeight = 0;
5494 Clip(x, width, size.width(), &copyX, &copyWidth);
5495 Clip(y, height, size.height(), &copyY, &copyHeight);
5496
5497 if (copyX != x ||
5498 copyY != y ||
5499 copyWidth != width ||
5500 copyHeight != height) {
5501 // some part was clipped so clear the texture.
5502 uint32 pixels_size = 0;
5503 if (!GLES2Util::ComputeImageDataSize(
5504 width, height, internal_format, GL_UNSIGNED_BYTE,
5505 unpack_alignment_, &pixels_size)) {
5506 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions too large");
5507 return;
5508 }
5509 scoped_array<char> zero(new char[pixels_size]);
5510 memset(zero.get(), 0, pixels_size);
5511 glTexImage2D(target, level, internal_format, width, height, 0,
5512 internal_format, GL_UNSIGNED_BYTE, zero.get());
5513 if (copyHeight > 0 && copyWidth > 0) {
5514 GLint dx = copyX - x;
5515 GLint dy = copyY - y;
5516 GLint destX = dx;
5517 GLint destY = dy;
5518 glCopyTexSubImage2D(target, level,
5519 destX, destY, copyX, copyY,
5520 copyWidth, copyHeight);
5521 }
5522 } else {
5523 glCopyTexImage2D(target, level, internal_format,
5524 copyX, copyY, copyWidth, copyHeight, border);
5525 }
[email protected]cadde4a2010-07-31 17:10:435526 GLenum error = glGetError();
5527 if (error == GL_NO_ERROR) {
5528 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115529 feature_info_, info, target, level, internal_format, width, height, 1,
5530 border, internal_format, GL_UNSIGNED_BYTE);
[email protected]cadde4a2010-07-31 17:10:435531 }
5532}
5533
5534void GLES2DecoderImpl::DoCopyTexSubImage2D(
5535 GLenum target,
5536 GLint level,
5537 GLint xoffset,
5538 GLint yoffset,
5539 GLint x,
5540 GLint y,
5541 GLsizei width,
5542 GLsizei height) {
5543 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5544 if (!info) {
5545 SetGLError(GL_INVALID_OPERATION,
5546 "glCopyTexSubImage2D: unknown texture for target");
5547 return;
5548 }
5549 GLenum type = 0;
5550 GLenum format = 0;
5551 if (!info->GetLevelType(target, level, &type, &format) ||
5552 !info->ValidForTexture(
5553 target, level, xoffset, yoffset, width, height, format, type)) {
5554 SetGLError(GL_INVALID_VALUE,
5555 "glCopyTexSubImage2D: bad dimensions.");
5556 return;
5557 }
[email protected]9edc6b22010-12-23 02:00:265558
5559 // Check we have compatible formats.
5560 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5561 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5562 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
5563
5564 if ((channels_needed & channels_exist) != channels_needed) {
5565 SetGLError(
5566 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
5567 return;
5568 }
5569
[email protected]34ff8b0c2010-10-01 20:06:025570 ScopedResolvedFrameBufferBinder binder(this);
[email protected]6e288612010-12-21 20:45:035571 gfx::Size size = GetBoundReadFrameBufferSize();
5572 GLint copyX = 0;
5573 GLint copyY = 0;
5574 GLint copyWidth = 0;
5575 GLint copyHeight = 0;
5576 Clip(x, width, size.width(), &copyX, &copyWidth);
5577 Clip(y, height, size.height(), &copyY, &copyHeight);
5578 if (copyX != x ||
5579 copyY != y ||
5580 copyWidth != width ||
5581 copyHeight != height) {
5582 // some part was clipped so clear the texture.
5583 uint32 pixels_size = 0;
5584 if (!GLES2Util::ComputeImageDataSize(
5585 width, height, format, type, unpack_alignment_, &pixels_size)) {
5586 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
5587 return;
5588 }
5589 scoped_array<char> zero(new char[pixels_size]);
5590 memset(zero.get(), 0, pixels_size);
5591 glTexSubImage2D(
5592 target, level, xoffset, yoffset, width, height,
5593 format, type, zero.get());
5594 }
5595 if (copyHeight > 0 && copyWidth > 0) {
5596 GLint dx = copyX - x;
5597 GLint dy = copyY - y;
5598 GLint destX = xoffset + dx;
5599 GLint destY = yoffset + dy;
5600 glCopyTexSubImage2D(target, level,
5601 destX, destY, copyX, copyY,
5602 copyWidth, copyHeight);
5603 }
[email protected]cadde4a2010-07-31 17:10:435604}
5605
5606void GLES2DecoderImpl::DoTexSubImage2D(
5607 GLenum target,
5608 GLint level,
5609 GLint xoffset,
5610 GLint yoffset,
5611 GLsizei width,
5612 GLsizei height,
5613 GLenum format,
5614 GLenum type,
5615 const void * data) {
5616 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5617 if (!info) {
5618 SetGLError(GL_INVALID_OPERATION,
5619 "glTexSubImage2D: unknown texture for target");
5620 return;
5621 }
5622 if (!info->ValidForTexture(
5623 target, level, xoffset, yoffset, width, height, format, type)) {
5624 SetGLError(GL_INVALID_VALUE,
5625 "glTexSubImage2D: bad dimensions.");
5626 return;
5627 }
5628 glTexSubImage2D(
5629 target, level, xoffset, yoffset, width, height, format, type, data);
5630}
5631
[email protected]f7a64ee2010-02-01 22:24:145632error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:195633 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:365634 GLuint index = static_cast<GLuint>(c.index);
5635 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:255636 typedef gles2::GetVertexAttribPointerv::Result Result;
5637 Result* result = GetSharedMemoryAs<Result*>(
5638 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:365639 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:145640 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:365641 }
[email protected]07d0cc82010-02-17 04:51:405642 // Check that the client initialized the result.
5643 if (result->size != 0) {
5644 return error::kInvalidArguments;
5645 }
[email protected]9438b012010-06-15 22:55:055646 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295647 SetGLError(GL_INVALID_ENUM,
5648 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145649 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:365650 }
[email protected]3916c97e2010-02-25 03:20:505651 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:295652 SetGLError(GL_INVALID_VALUE,
5653 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:145654 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:365655 }
[email protected]0bfd9882010-02-05 23:02:255656 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:085657 *result->GetData() =
5658 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:145659 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325660}
5661
[email protected]f7b85372010-02-03 01:11:375662bool GLES2DecoderImpl::GetUniformSetup(
5663 GLuint program, GLint location,
5664 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:105665 error::Error* error, GLuint* service_id, void** result_pointer,
5666 GLenum* result_type) {
5667 DCHECK(error);
5668 DCHECK(service_id);
5669 DCHECK(result_pointer);
5670 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:375671 *error = error::kNoError;
5672 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:255673 SizedResult<GLint>* result;
5674 result = GetSharedMemoryAs<SizedResult<GLint>*>(
5675 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
5676 if (!result) {
[email protected]f7b85372010-02-03 01:11:375677 *error = error::kOutOfBounds;
5678 return false;
5679 }
[email protected]0bfd9882010-02-05 23:02:255680 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:375681 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:255682 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:585683 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5684 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:375685 if (!info) {
[email protected]ae51d192010-04-27 00:48:035686 return false;
5687 }
5688 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:375689 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:295690 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:375691 return false;
5692 }
[email protected]ae51d192010-04-27 00:48:035693 *service_id = info->service_id();
[email protected]0bfd9882010-02-05 23:02:255694 GLenum type;
5695 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:375696 // No such location.
[email protected]8eee29c2010-04-29 03:38:295697 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:375698 return false;
5699 }
[email protected]3916c97e2010-02-25 03:20:505700 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:375701 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:295702 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:375703 return false;
5704 }
[email protected]0bfd9882010-02-05 23:02:255705 result = GetSharedMemoryAs<SizedResult<GLint>*>(
5706 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
5707 if (!result) {
[email protected]f7b85372010-02-03 01:11:375708 *error = error::kOutOfBounds;
5709 return false;
5710 }
[email protected]0bfd9882010-02-05 23:02:255711 result->size = size;
[email protected]939e7362010-05-13 20:49:105712 *result_type = type;
[email protected]f7b85372010-02-03 01:11:375713 return true;
5714}
5715
[email protected]f7a64ee2010-02-01 22:24:145716error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:195717 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:375718 GLuint program = c.program;
5719 GLint location = c.location;
5720 GLuint service_id;
[email protected]939e7362010-05-13 20:49:105721 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:375722 Error error;
[email protected]0bfd9882010-02-05 23:02:255723 void* result;
[email protected]f7b85372010-02-03 01:11:375724 if (GetUniformSetup(
5725 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:105726 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:255727 glGetUniformiv(
5728 service_id, location,
5729 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:375730 }
5731 return error;
[email protected]96449d2c2009-11-25 00:01:325732}
5733
[email protected]f7a64ee2010-02-01 22:24:145734error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:195735 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:375736 GLuint program = c.program;
5737 GLint location = c.location;
5738 GLuint service_id;
5739 Error error;
[email protected]0bfd9882010-02-05 23:02:255740 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:105741 Result* result;
5742 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:375743 if (GetUniformSetup(
5744 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:105745 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
5746 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
5747 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
5748 GLsizei num_values = result->GetNumResults();
5749 scoped_array<GLint> temp(new GLint[num_values]);
5750 glGetUniformiv(service_id, location, temp.get());
5751 GLfloat* dst = result->GetData();
5752 for (GLsizei ii = 0; ii < num_values; ++ii) {
5753 dst[ii] = (temp[ii] != 0);
5754 }
5755 } else {
5756 glGetUniformfv(service_id, location, result->GetData());
5757 }
[email protected]f7b85372010-02-03 01:11:375758 }
5759 return error;
[email protected]96449d2c2009-11-25 00:01:325760}
5761
[email protected]f7a64ee2010-02-01 22:24:145762error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:195763 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:255764 GLenum shader_type = static_cast<GLenum>(c.shadertype);
5765 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
5766 typedef gles2::GetShaderPrecisionFormat::Result Result;
5767 Result* result = GetSharedMemoryAs<Result*>(
5768 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5769 if (!result) {
5770 return error::kOutOfBounds;
5771 }
[email protected]07d0cc82010-02-17 04:51:405772 // Check that the client initialized the result.
5773 if (result->success != 0) {
5774 return error::kInvalidArguments;
5775 }
[email protected]9438b012010-06-15 22:55:055776 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:295777 SetGLError(GL_INVALID_ENUM,
5778 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
5779 return error::kNoError;
5780 }
[email protected]9438b012010-06-15 22:55:055781 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:295782 SetGLError(GL_INVALID_ENUM,
5783 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
5784 return error::kNoError;
5785 }
5786
5787 result->success = 1; // true
5788 switch (precision_type) {
5789 case GL_LOW_INT:
5790 case GL_MEDIUM_INT:
5791 case GL_HIGH_INT:
5792 result->min_range = -31;
5793 result->max_range = 31;
5794 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:105795 break;
[email protected]8eee29c2010-04-29 03:38:295796 case GL_LOW_FLOAT:
5797 case GL_MEDIUM_FLOAT:
5798 case GL_HIGH_FLOAT:
5799 result->min_range = -62;
5800 result->max_range = 62;
5801 result->precision = -16;
5802 break;
5803 default:
5804 NOTREACHED();
5805 break;
[email protected]0bfd9882010-02-05 23:02:255806 }
[email protected]f7a64ee2010-02-01 22:24:145807 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325808}
5809
[email protected]f7a64ee2010-02-01 22:24:145810error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:195811 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:255812 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:585813 GLuint program = static_cast<GLuint>(c.program);
5814 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5815 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:035816 if (!info) {
[email protected]0bfd9882010-02-05 23:02:255817 return error::kNoError;
5818 }
5819 typedef gles2::GetAttachedShaders::Result Result;
5820 uint32 max_count = Result::ComputeMaxResults(result_size);
5821 Result* result = GetSharedMemoryAs<Result*>(
5822 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
5823 if (!result) {
5824 return error::kOutOfBounds;
5825 }
[email protected]07d0cc82010-02-17 04:51:405826 // Check that the client initialized the result.
5827 if (result->size != 0) {
5828 return error::kInvalidArguments;
5829 }
[email protected]0bfd9882010-02-05 23:02:255830 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:035831 glGetAttachedShaders(
5832 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:255833 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:035834 if (!shader_manager()->GetClientId(result->GetData()[ii],
5835 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:255836 NOTREACHED();
5837 return error::kGenericError;
5838 }
5839 }
5840 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:145841 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325842}
5843
[email protected]f7a64ee2010-02-01 22:24:145844error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:195845 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:255846 GLuint program = c.program;
5847 GLuint index = c.index;
5848 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:255849 typedef gles2::GetActiveUniform::Result Result;
5850 Result* result = GetSharedMemoryAs<Result*>(
5851 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5852 if (!result) {
5853 return error::kOutOfBounds;
5854 }
[email protected]07d0cc82010-02-17 04:51:405855 // Check that the client initialized the result.
5856 if (result->success != 0) {
5857 return error::kInvalidArguments;
5858 }
[email protected]6b8cf1a2010-05-06 16:13:585859 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5860 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:035861 if (!info) {
[email protected]0bfd9882010-02-05 23:02:255862 return error::kNoError;
5863 }
5864 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
5865 info->GetUniformInfo(index);
5866 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:295867 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:255868 return error::kNoError;
5869 }
5870 result->success = 1; // true.
5871 result->size = uniform_info->size;
5872 result->type = uniform_info->type;
5873 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:295874 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:145875 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325876}
5877
[email protected]f7a64ee2010-02-01 22:24:145878error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:195879 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:255880 GLuint program = c.program;
5881 GLuint index = c.index;
5882 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:255883 typedef gles2::GetActiveAttrib::Result Result;
5884 Result* result = GetSharedMemoryAs<Result*>(
5885 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5886 if (!result) {
5887 return error::kOutOfBounds;
5888 }
[email protected]07d0cc82010-02-17 04:51:405889 // Check that the client initialized the result.
5890 if (result->success != 0) {
5891 return error::kInvalidArguments;
5892 }
[email protected]6b8cf1a2010-05-06 16:13:585893 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5894 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:035895 if (!info) {
[email protected]0bfd9882010-02-05 23:02:255896 return error::kNoError;
5897 }
5898 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5899 info->GetAttribInfo(index);
5900 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:295901 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:255902 return error::kNoError;
5903 }
5904 result->success = 1; // true.
5905 result->size = attrib_info->size;
5906 result->type = attrib_info->type;
5907 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:295908 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:145909 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325910}
5911
[email protected]b273e432010-04-12 17:23:585912error::Error GLES2DecoderImpl::HandleShaderBinary(
5913 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
5914#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:295915 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:585916 return error::kNoError;
5917#else
5918 GLsizei n = static_cast<GLsizei>(c.n);
5919 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:295920 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:585921 return error::kNoError;
5922 }
5923 GLsizei length = static_cast<GLsizei>(c.length);
5924 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:295925 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:585926 return error::kNoError;
5927 }
5928 uint32 data_size;
5929 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
5930 return error::kOutOfBounds;
5931 }
5932 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
5933 c.shaders_shm_id, c.shaders_shm_offset, data_size);
5934 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
5935 const void* binary = GetSharedMemoryAs<const void*>(
5936 c.binary_shm_id, c.binary_shm_offset, length);
5937 if (shaders == NULL || binary == NULL) {
5938 return error::kOutOfBounds;
5939 }
5940 scoped_array<GLuint> service_ids(new GLuint[n]);
5941 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:035942 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
5943 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295944 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:585945 return error::kNoError;
5946 }
[email protected]ae51d192010-04-27 00:48:035947 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:585948 }
5949 // TODO(gman): call glShaderBinary
5950 return error::kNoError;
5951#endif
5952}
5953
[email protected]6217d392010-03-25 22:08:355954error::Error GLES2DecoderImpl::HandleSwapBuffers(
5955 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]6217d392010-03-25 22:08:355956 // If offscreen then don't actually SwapBuffers to the display. Just copy
5957 // the rendered frame to another frame buffer.
5958 if (offscreen_target_frame_buffer_.get()) {
5959 ScopedGLErrorSuppressor suppressor(this);
5960
5961 // First check to see if a deferred offscreen render buffer resize is
5962 // pending.
[email protected]d0498742010-09-20 20:27:015963 if (!UpdateOffscreenFrameBufferSize()) {
5964 LOG(ERROR) << "Context lost because reallocation of offscreen FBO "
5965 << "failed.";
[email protected]6217d392010-03-25 22:08:355966 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:015967 }
[email protected]6217d392010-03-25 22:08:355968
[email protected]34ff8b0c2010-10-01 20:06:025969 if (IsOffscreenBufferMultisampled()) {
5970 // For multisampled buffers, bind the resolved frame buffer so that
5971 // callbacks can call ReadPixels or CopyTexImage2D.
5972 ScopedResolvedFrameBufferBinder binder(this);
5973 if (swap_buffers_callback_.get()) {
5974 swap_buffers_callback_->Run();
5975 }
5976 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:485977 } else {
[email protected]0c8c9d22010-06-25 17:36:395978 ScopedFrameBufferBinder binder(this,
5979 offscreen_target_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:405980
[email protected]b86b14982010-10-11 18:45:485981 if (parent_) {
5982 // Copy the target frame buffer to the saved offscreen texture.
5983 offscreen_saved_color_texture_->Copy(
5984 offscreen_saved_color_texture_->size());
5985
[email protected]a3ded6d2010-10-19 06:44:395986 // Ensure the side effects of the copy are visible to the parent
5987 // context. There is no need to do this for ANGLE because it uses a
5988 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:485989 if (!IsAngle())
5990 glFlush();
5991 }
5992
5993 // Run the callback with |binder| in scope, so that the callback can call
5994 // ReadPixels or CopyTexImage2D.
5995 if (swap_buffers_callback_.get()) {
5996 swap_buffers_callback_->Run();
5997 }
5998 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:395999 }
[email protected]6217d392010-03-25 22:08:356000 } else {
[email protected]d0498742010-09-20 20:27:016001 if (!context_->SwapBuffers()) {
6002 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:026003 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016004 }
[email protected]6217d392010-03-25 22:08:356005 }
6006
6007 if (swap_buffers_callback_.get()) {
6008 swap_buffers_callback_->Run();
6009 }
6010
6011 return error::kNoError;
6012}
6013
[email protected]269200b12010-11-18 22:53:066014error::Error GLES2DecoderImpl::HandleCommandBufferEnableCHROMIUM(
6015 uint32 immediate_data_size, const gles2::CommandBufferEnableCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:186016 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]269200b12010-11-18 22:53:066017 typedef gles2::CommandBufferEnableCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:186018 Result* result = GetSharedMemoryAs<Result*>(
6019 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6020 if (!result) {
6021 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:106022 }
[email protected]b1d2dcb2010-05-17 19:24:186023 // Check that the client initialized the result.
6024 if (*result != 0) {
6025 return error::kInvalidArguments;
6026 }
6027 std::string feature_str;
6028 if (!bucket->GetAsString(&feature_str)) {
6029 return error::kInvalidArguments;
6030 }
6031
6032 // TODO(gman): make this some kind of table to function pointer thingy.
6033 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
6034 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]8fbedc02010-11-18 18:43:406035 } else if (feature_str.compare(PEPPER3D_SUPPORT_FIXED_ATTRIBS) == 0) {
6036 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
6037 // TODO(gman): decide how to remove the need for this const_cast.
6038 // I could make validators_ non const but that seems bad as this is the only
6039 // place it is needed. I could make some special friend class of validators
6040 // just to allow this to set them. That seems silly. I could refactor this
6041 // code to use the extension mechanism or the initialization attributes to
6042 // turn this feature on. Given that the only real point of this is to make
6043 // the conformance tests pass and given that there is lots of real work that
6044 // needs to be done it seems like refactoring for one to one of those
6045 // methods is a very low priority.
6046 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]b1d2dcb2010-05-17 19:24:186047 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
6048 use_shader_translator_ = false;
6049 } else {
6050 return error::kNoError;
6051 }
6052
6053 *result = 1; // true.
6054 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:106055}
6056
[email protected]c2f8c8402010-12-06 18:07:246057error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
6058 uint32 immediate_data_size,
6059 const gles2::GetRequestableExtensionsCHROMIUM& c) {
6060 Bucket* bucket = CreateBucket(c.bucket_id);
6061 scoped_ptr<FeatureInfo> info(new FeatureInfo());
6062 info->Initialize(NULL);
6063 bucket->SetFromString(info->extensions().c_str());
6064 return error::kNoError;
6065}
6066
6067error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
6068 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
6069 Bucket* bucket = GetBucket(c.bucket_id);
6070 std::string feature_str;
6071 if (!bucket->GetAsString(&feature_str)) {
6072 return error::kInvalidArguments;
6073 }
6074
6075 bool std_derivatives_enabled =
6076 feature_info_->feature_flags().oes_standard_derivatives;
6077 bool webglsl_enabled =
6078 feature_info_->feature_flags().chromium_webglsl;
6079
6080 feature_info_->AddFeatures(feature_str.c_str());
6081
6082 // If we just enabled a feature which affects the shader translator,
6083 // we may need to re-initialize it.
6084 if (std_derivatives_enabled !=
6085 feature_info_->feature_flags().oes_standard_derivatives ||
6086 webglsl_enabled !=
6087 feature_info_->feature_flags().chromium_webglsl) {
6088 InitializeShaderTranslator();
6089 }
6090
6091 return error::kNoError;
6092}
6093
[email protected]96449d2c2009-11-25 00:01:326094// Include the auto-generated part of this file. We split this because it means
6095// we can easily edit the non-auto generated parts right here in this file
6096// instead of having to edit some template or the code generator.
6097#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
6098
6099} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:256100} // namespace gpu