blob: 033a819bef631efcbff0ed06a30ce2e91e49dd5a [file] [log] [blame]
[email protected]1bee3982009-12-17 23:15:281// Copyright (c) 2009 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]2041cf342010-02-19 03:15:5916#include "base/callback.h"
[email protected]96449d2c2009-11-25 00:01:3217#include "base/scoped_ptr.h"
[email protected]6217d392010-03-25 22:08:3518#include "base/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0219#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3220#define GLES2_GPU_SERVICE 1
21#include "gpu/command_buffer/common/gles2_cmd_format.h"
22#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1023#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5024#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3225#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5026#include "gpu/command_buffer/service/context_group.h"
[email protected]a25fa872010-03-25 02:57:5827#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3228#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4629#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4730#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5831#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4732#include "gpu/command_buffer/service/shader_manager.h"
33#include "gpu/command_buffer/service/texture_manager.h"
[email protected]4e8a5b122010-05-08 22:00:1034#include "gpu/GLES2/gles2_command_buffer.h"
[email protected]2cb1fa92010-05-13 20:30:5135
[email protected]2cb1fa92010-05-13 20:30:5136#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
[email protected]3094c2a2010-04-29 21:50:4537#include "third_party/angle/include/GLSLANG/ShaderLang.h"
[email protected]2cb1fa92010-05-13 20:30:5138#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
[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]6217d392010-03-25 22:08:35117// This class prevents any GL errors that occur when it is in scope from
118// being reported to the client.
119class ScopedGLErrorSuppressor {
120 public:
121 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
122 ~ScopedGLErrorSuppressor();
123 private:
124 GLES2DecoderImpl* decoder_;
125 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
126};
127
128// Temporarily changes a decoder's bound 2D texture and restore it when this
129// object goes out of scope. Also temporarily switches to using active texture
130// unit zero in case the client has changed that to something invalid.
131class ScopedTexture2DBinder {
132 public:
133 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
134 ~ScopedTexture2DBinder();
135
136 private:
137 GLES2DecoderImpl* decoder_;
138 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
139};
140
141// Temporarily changes a decoder's bound render buffer and restore it when this
142// object goes out of scope.
143class ScopedRenderBufferBinder {
144 public:
145 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
146 ~ScopedRenderBufferBinder();
147
148 private:
149 GLES2DecoderImpl* decoder_;
150 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
151};
152
153// Temporarily changes a decoder's bound frame buffer and restore it when this
154// object goes out of scope.
155class ScopedFrameBufferBinder {
156 public:
157 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
158 ~ScopedFrameBufferBinder();
159
160 private:
161 GLES2DecoderImpl* decoder_;
162 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
163};
164
[email protected]2f2d7042010-04-14 21:45:58165// Temporarily switch to a decoder's default GL context, having known default
166// state.
167class ScopedDefaultGLContext {
168 public:
169 explicit ScopedDefaultGLContext(GLES2DecoderImpl* decoder);
170 ~ScopedDefaultGLContext();
171
172 private:
173 GLES2DecoderImpl* decoder_;
174 DISALLOW_COPY_AND_ASSIGN(ScopedDefaultGLContext);
175};
176
[email protected]6217d392010-03-25 22:08:35177// Encapsulates an OpenGL texture.
178class Texture {
179 public:
180 explicit Texture(GLES2DecoderImpl* decoder);
181 ~Texture();
182
183 // Create a new render texture.
184 void Create();
185
186 // Set the initial size and format of a render texture or resize it.
187 bool AllocateStorage(const gfx::Size& size);
188
189 // Copy the contents of the currently bound frame buffer.
190 void Copy(const gfx::Size& size);
191
192 // Destroy the render texture. This must be explicitly called before
193 // destroying this object.
194 void Destroy();
195
196 GLuint id() const {
197 return id_;
198 }
199
[email protected]d37231fa2010-04-09 21:16:02200 gfx::Size size() const {
201 return size_;
202 }
203
[email protected]6217d392010-03-25 22:08:35204 private:
205 GLES2DecoderImpl* decoder_;
206 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02207 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35208 DISALLOW_COPY_AND_ASSIGN(Texture);
209};
210
211// Encapsulates an OpenGL render buffer of any format.
212class RenderBuffer {
213 public:
214 explicit RenderBuffer(GLES2DecoderImpl* decoder);
215 ~RenderBuffer();
216
217 // Create a new render buffer.
218 void Create();
219
220 // Set the initial size and format of a render buffer or resize it.
221 bool AllocateStorage(const gfx::Size& size, GLenum format);
222
223 // Destroy the render buffer. This must be explicitly called before destroying
224 // this object.
225 void Destroy();
226
227 GLuint id() const {
228 return id_;
229 }
230
231 private:
232 GLES2DecoderImpl* decoder_;
233 GLuint id_;
234 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
235};
236
237// Encapsulates an OpenGL frame buffer.
238class FrameBuffer {
239 public:
240 explicit FrameBuffer(GLES2DecoderImpl* decoder);
241 ~FrameBuffer();
242
243 // Create a new frame buffer.
244 void Create();
245
246 // Attach a color render buffer to a frame buffer.
247 void AttachRenderTexture(Texture* texture);
248
249 // Attach a depth stencil render buffer to a frame buffer. Note that
250 // this unbinds any currently bound frame buffer.
251 void AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer);
252
253 // Clear the given attached buffers.
254 void Clear(GLbitfield buffers);
255
256 // Destroy the frame buffer. This must be explicitly called before destroying
257 // this object.
258 void Destroy();
259
260 // See glCheckFramebufferStatusEXT.
261 GLenum CheckStatus();
262
263 GLuint id() const {
264 return id_;
265 }
266
267 private:
268 GLES2DecoderImpl* decoder_;
269 GLuint id_;
270 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
271};
[email protected]43f28f832010-02-03 02:28:48272// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32273
[email protected]3916c97e2010-02-25 03:20:50274GLES2Decoder::GLES2Decoder(ContextGroup* group)
275 : group_(group),
[email protected]3916c97e2010-02-25 03:20:50276 debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32277}
278
[email protected]3916c97e2010-02-25 03:20:50279GLES2Decoder::~GLES2Decoder() {
280}
281
[email protected]f39f4b3f2010-05-12 17:04:08282class VertexAttribManager {
[email protected]96449d2c2009-11-25 00:01:32283 public:
[email protected]07f54fcc2009-12-22 02:46:30284 // Info about Vertex Attributes. This is used to track what the user currently
285 // has bound on each Vertex Attribute so that checking can be done at
286 // glDrawXXX time.
287 class VertexAttribInfo {
288 public:
[email protected]f39f4b3f2010-05-12 17:04:08289 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
[email protected]b1122982010-05-17 23:04:24290 struct Vec4 {
291 float v[4];
292 };
[email protected]f39f4b3f2010-05-12 17:04:08293
[email protected]07f54fcc2009-12-22 02:46:30294 VertexAttribInfo()
[email protected]f39f4b3f2010-05-12 17:04:08295 : index_(0),
296 enabled_(false),
297 size_(4),
298 type_(GL_FLOAT),
[email protected]07f54fcc2009-12-22 02:46:30299 offset_(0),
[email protected]b1122982010-05-17 23:04:24300 normalized_(GL_FALSE),
301 gl_stride_(0),
[email protected]f39f4b3f2010-05-12 17:04:08302 real_stride_(16),
303 list_(NULL) {
[email protected]b1122982010-05-17 23:04:24304 value_.v[0] = 0.0f;
305 value_.v[1] = 0.0f;
306 value_.v[2] = 0.0f;
307 value_.v[3] = 1.0f;
[email protected]07f54fcc2009-12-22 02:46:30308 }
[email protected]3916c97e2010-02-25 03:20:50309
[email protected]07f54fcc2009-12-22 02:46:30310 // Returns true if this VertexAttrib can access index.
[email protected]f39f4b3f2010-05-12 17:04:08311 bool CanAccess(GLuint index) const;
[email protected]07f54fcc2009-12-22 02:46:30312
[email protected]3916c97e2010-02-25 03:20:50313 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30314 return buffer_;
315 }
316
[email protected]8bf5a3e2010-01-29 04:21:36317 GLsizei offset() const {
318 return offset_;
319 }
320
[email protected]f39f4b3f2010-05-12 17:04:08321 GLuint index() const {
322 return index_;
323 }
324
[email protected]b1122982010-05-17 23:04:24325 GLint size() const {
326 return size_;
327 }
328
329 GLenum type() const {
330 return type_;
331 }
332
333 GLboolean normalized() const {
334 return normalized_;
335 }
336
337 GLsizei gl_stride() const {
338 return gl_stride_;
339 }
340
[email protected]07f54fcc2009-12-22 02:46:30341 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50342 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30343 GLint size,
344 GLenum type,
[email protected]b1122982010-05-17 23:04:24345 GLboolean normalized,
346 GLsizei gl_stride,
[email protected]07f54fcc2009-12-22 02:46:30347 GLsizei real_stride,
348 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24349 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30350 buffer_ = buffer;
351 size_ = size;
352 type_ = type;
[email protected]b1122982010-05-17 23:04:24353 normalized_ = normalized;
354 gl_stride_ = gl_stride;
[email protected]07f54fcc2009-12-22 02:46:30355 real_stride_ = real_stride;
356 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50357 }
358
359 void ClearBuffer() {
360 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30361 }
362
[email protected]f39f4b3f2010-05-12 17:04:08363 bool enabled() const {
364 return enabled_;
365 }
366
[email protected]b1122982010-05-17 23:04:24367 void set_value(const Vec4& value) {
368 value_ = value;
369 }
370
371 const Vec4& value() const {
372 return value_;
373 }
374
[email protected]07f54fcc2009-12-22 02:46:30375 private:
[email protected]f39f4b3f2010-05-12 17:04:08376 friend class VertexAttribManager;
377
378 void set_enabled(bool enabled) {
379 enabled_ = enabled;
380 }
381
382 void set_index(GLuint index) {
383 index_ = index;
384 }
385
386 void SetList(VertexAttribInfoList* new_list) {
387 DCHECK(new_list);
388
389 if (list_) {
390 list_->erase(it_);
391 }
392
393 it_ = new_list->insert(new_list->end(), this);
394 list_ = new_list;
395 }
396
397 // The index of this attrib.
398 GLuint index_;
399
[email protected]07f54fcc2009-12-22 02:46:30400 // Whether or not this attribute is enabled.
401 bool enabled_;
402
403 // number of components (1, 2, 3, 4)
404 GLint size_;
405
406 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
407 GLenum type_;
408
409 // The offset into the buffer.
410 GLsizei offset_;
411
[email protected]b1122982010-05-17 23:04:24412 GLboolean normalized_;
413
414 // The stride passed to glVertexAttribPointer.
415 GLsizei gl_stride_;
416
[email protected]07f54fcc2009-12-22 02:46:30417 // The stride that will be used to access the buffer. This is the actual
418 // stide, NOT the GL bogus stride. In other words there is never a stride
419 // of 0.
420 GLsizei real_stride_;
421
[email protected]b1122982010-05-17 23:04:24422 // The current value of the attrib.
423 Vec4 value_;
424
[email protected]3916c97e2010-02-25 03:20:50425 // The buffer bound to this attribute.
426 BufferManager::BufferInfo::Ref buffer_;
[email protected]f39f4b3f2010-05-12 17:04:08427
428 // List this info is on.
429 VertexAttribInfoList* list_;
430
431 // Iterator for list this info is on. Enabled/Disabled
432 VertexAttribInfoList::iterator it_;
[email protected]07f54fcc2009-12-22 02:46:30433 };
434
[email protected]f39f4b3f2010-05-12 17:04:08435 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
436
437 VertexAttribManager()
438 : max_vertex_attribs_(0) {
439 }
440
441 void Initialize(uint32 num_vertex_attribs);
442
443 bool Enable(GLuint index, bool enable);
444
445 const VertexAttribInfoList& GetEnabledVertexAttribInfos() const {
446 return enabled_vertex_attribs_;
447 }
448
449 VertexAttribInfo* GetVertexAttribInfo(GLuint index) {
[email protected]b1122982010-05-17 23:04:24450 if (index < max_vertex_attribs_) {
451 return &vertex_attrib_infos_[index];
452 }
453 return NULL;
[email protected]f39f4b3f2010-05-12 17:04:08454 }
455
456 private:
457 uint32 max_vertex_attribs_;
458
459 // Info for each vertex attribute saved so we can check at glDrawXXX time
460 // if it is safe to draw.
461 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
462
463 // Lists for which vertex attribs are enabled, disabled.
464 VertexAttribInfoList enabled_vertex_attribs_;
465 VertexAttribInfoList disabled_vertex_attribs_;
466};
467
468bool VertexAttribManager::VertexAttribInfo::CanAccess(GLuint index) const {
469 if (!enabled_) {
470 return true;
471 }
472
473 if (!buffer_ || buffer_->IsDeleted()) {
474 return false;
475 }
476
477 // The number of elements that can be accessed.
478 GLsizeiptr buffer_size = buffer_->size();
479 if (offset_ > buffer_size || real_stride_ == 0) {
480 return false;
481 }
482
483 uint32 usable_size = buffer_size - offset_;
484 GLuint num_elements = usable_size / real_stride_ +
485 ((usable_size % real_stride_) >=
486 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
487 return index < num_elements;
488}
489
490
491void VertexAttribManager::Initialize(uint32 max_vertex_attribs) {
492 max_vertex_attribs_ = max_vertex_attribs;
493 vertex_attrib_infos_.reset(
494 new VertexAttribInfo[max_vertex_attribs]);
495 for (uint32 vv = 0; vv < max_vertex_attribs; ++vv) {
496 vertex_attrib_infos_[vv].set_index(vv);
497 vertex_attrib_infos_[vv].SetList(&disabled_vertex_attribs_);
498 }
499}
500
501bool VertexAttribManager::Enable(GLuint index, bool enable) {
502 if (index >= max_vertex_attribs_) {
503 return false;
504 }
505 VertexAttribInfo& info = vertex_attrib_infos_[index];
506 if (info.enabled() != enable) {
507 info.set_enabled(enable);
508 info.SetList(enable ? &enabled_vertex_attribs_ : &disabled_vertex_attribs_);
509 }
510 return true;
511}
512
513// This class implements GLES2Decoder so we don't have to expose all the GLES2
514// cmd stuff to outside this class.
515class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
516 public GLES2Decoder {
517 public:
518 explicit GLES2DecoderImpl(ContextGroup* group);
519
[email protected]96449d2c2009-11-25 00:01:32520 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14521 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50522 unsigned int arg_count,
523 const void* args);
[email protected]96449d2c2009-11-25 00:01:32524
525 // Overridden from AsyncAPIInterface.
526 virtual const char* GetCommandName(unsigned int command_id) const;
527
528 // Overridden from GLES2Decoder.
[email protected]5a6db6c2010-04-22 18:32:06529 virtual bool Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:35530 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:02531 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35532 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32533 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35534 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]eb54a562010-01-20 21:55:18535 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55536 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]5a6db6c2010-04-22 18:32:06537 virtual gfx::GLContext* GetGLContext() { return context_; }
[email protected]43f28f832010-02-03 02:28:48538
539 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
540
[email protected]96449d2c2009-11-25 00:01:32541 private:
[email protected]6217d392010-03-25 22:08:35542 friend class ScopedGLErrorSuppressor;
543 friend class ScopedTexture2DBinder;
544 friend class ScopedFrameBufferBinder;
545 friend class ScopedRenderBufferBinder;
[email protected]2f2d7042010-04-14 21:45:58546 friend class ScopedDefaultGLContext;
[email protected]6217d392010-03-25 22:08:35547 friend class RenderBuffer;
548 friend class FrameBuffer;
549
[email protected]3916c97e2010-02-25 03:20:50550 // State associated with each texture unit.
551 struct TextureUnit {
552 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
553
554 // The last target that was bound to this texture unit.
555 GLenum bind_target;
556
557 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
558 TextureManager::TextureInfo::Ref bound_texture_2d;
559
560 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
561 // glBindTexture
562 TextureManager::TextureInfo::Ref bound_texture_cube_map;
563 };
564
[email protected]ae51d192010-04-27 00:48:03565 // Helpers for the glGen and glDelete functions.
566 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
567 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
568 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
569 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
570 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
571 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
572 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
573 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47574
[email protected]3916c97e2010-02-25 03:20:50575 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50576 BufferManager* buffer_manager() {
577 return group_->buffer_manager();
578 }
579
[email protected]a25fa872010-03-25 02:57:58580 RenderbufferManager* renderbuffer_manager() {
581 return group_->renderbuffer_manager();
582 }
583
584 FramebufferManager* framebuffer_manager() {
585 return group_->framebuffer_manager();
586 }
587
[email protected]3916c97e2010-02-25 03:20:50588 ProgramManager* program_manager() {
589 return group_->program_manager();
590 }
591
592 ShaderManager* shader_manager() {
593 return group_->shader_manager();
594 }
595
596 TextureManager* texture_manager() {
597 return group_->texture_manager();
598 }
599
[email protected]6217d392010-03-25 22:08:35600 bool UpdateOffscreenFrameBufferSize();
601
[email protected]a93bb842010-02-16 23:03:47602 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03603 TextureManager::TextureInfo* CreateTextureInfo(
604 GLuint client_id, GLuint service_id) {
605 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47606 }
607
608 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03609 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50610 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03611 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50612 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47613 }
614
615 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03616 void RemoveTextureInfo(GLuint client_id) {
617 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50618 }
[email protected]a93bb842010-02-16 23:03:47619
[email protected]d37231fa2010-04-09 21:16:02620 // Get the size (in pixels) of the currently bound frame buffer (either FBO
621 // or regular back buffer).
622 gfx::Size GetBoundFrameBufferSize();
623
[email protected]a93bb842010-02-16 23:03:47624 // Wrapper for CompressedTexImage2D commands.
625 error::Error DoCompressedTexImage2D(
626 GLenum target,
627 GLint level,
628 GLenum internal_format,
629 GLsizei width,
630 GLsizei height,
631 GLint border,
632 GLsizei image_size,
633 const void* data);
634
635 // Wrapper for TexImage2D commands.
636 error::Error DoTexImage2D(
637 GLenum target,
638 GLint level,
639 GLenum internal_format,
640 GLsizei width,
641 GLsizei height,
642 GLint border,
643 GLenum format,
644 GLenum type,
645 const void* pixels,
646 uint32 pixels_size);
647
648 // Creates a ProgramInfo for the given program.
[email protected]ae51d192010-04-27 00:48:03649 void CreateProgramInfo(GLuint client_id, GLuint service_id) {
650 program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47651 }
652
[email protected]07f54fcc2009-12-22 02:46:30653 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03654 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50655 ProgramManager::ProgramInfo* info =
[email protected]ae51d192010-04-27 00:48:03656 program_manager()->GetProgramInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50657 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46658 }
[email protected]07f54fcc2009-12-22 02:46:30659
[email protected]6b8cf1a2010-05-06 16:13:58660 // Gets the program info for the given program. If it's not a program
661 // generates a GL error. Returns NULL if not program.
662 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
663 GLuint client_id, const char* function_name) {
664 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
665 if (!info) {
666 if (GetShaderInfo(client_id)) {
667 SetGLError(GL_INVALID_OPERATION,
668 (std::string(function_name) +
669 ": shader passed for program").c_str());
670 } else {
671 SetGLError(GL_INVALID_VALUE,
672 (std::string(function_name) + ": unknown program").c_str());
673 }
674 }
675 return info;
676 }
677
678
[email protected]07f54fcc2009-12-22 02:46:30679 // Deletes the program info for the given program.
[email protected]ae51d192010-04-27 00:48:03680 void RemoveProgramInfo(GLuint client_id) {
681 program_manager()->RemoveProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46682 }
[email protected]07f54fcc2009-12-22 02:46:30683
[email protected]45bf5152010-02-12 00:11:31684 // Creates a ShaderInfo for the given shader.
[email protected]7cea56d92010-04-28 17:21:38685 void CreateShaderInfo(GLuint client_id,
686 GLuint service_id,
687 GLenum shader_type) {
688 shader_manager()->CreateShaderInfo(client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31689 }
690
691 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03692 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
693 ShaderManager::ShaderInfo* info =
694 shader_manager()->GetShaderInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50695 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]45bf5152010-02-12 00:11:31696 }
697
[email protected]6b8cf1a2010-05-06 16:13:58698 // Gets the shader info for the given shader. If it's not a shader generates a
699 // GL error. Returns NULL if not shader.
700 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
701 GLuint client_id, const char* function_name) {
702 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
703 if (!info) {
704 if (GetProgramInfo(client_id)) {
705 SetGLError(
706 GL_INVALID_OPERATION,
707 (std::string(function_name) +
708 ": program passed for shader").c_str());
709 } else {
710 SetGLError(GL_INVALID_VALUE,
711 (std::string(function_name) + ": unknown shader").c_str());
712 }
713 }
714 return info;
715 }
716
[email protected]45bf5152010-02-12 00:11:31717 // Deletes the shader info for the given shader.
[email protected]ae51d192010-04-27 00:48:03718 void RemoveShaderInfo(GLuint client_id) {
719 shader_manager()->RemoveShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31720 }
721
[email protected]a93bb842010-02-16 23:03:47722 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03723 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
724 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47725 }
726
[email protected]07f54fcc2009-12-22 02:46:30727 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03728 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
729 BufferManager::BufferInfo* info =
730 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50731 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46732 }
[email protected]07f54fcc2009-12-22 02:46:30733
[email protected]a93bb842010-02-16 23:03:47734 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
735 // on glDeleteBuffers so we can make sure the user does not try to render
736 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03737 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47738
[email protected]a25fa872010-03-25 02:57:58739 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03740 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
741 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58742 }
743
744 // Gets the framebuffer info for the given framebuffer.
745 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03746 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58747 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03748 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58749 return (info && !info->IsDeleted()) ? info : NULL;
750 }
751
752 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03753 void RemoveFramebufferInfo(GLuint client_id) {
754 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58755 }
756
757 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03758 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
759 return renderbuffer_manager()->CreateRenderbufferInfo(
760 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58761 }
762
763 // Gets the renderbuffer info for the given renderbuffer.
764 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03765 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58766 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03767 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58768 return (info && !info->IsDeleted()) ? info : NULL;
769 }
770
771 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03772 void RemoveRenderbufferInfo(GLuint client_id) {
773 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58774 }
775
[email protected]558847a2010-03-24 07:02:54776 error::Error GetAttribLocationHelper(
777 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
778 const std::string& name_str);
779
780 error::Error GetUniformLocationHelper(
781 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
782 const std::string& name_str);
783
[email protected]3916c97e2010-02-25 03:20:50784 // Helper for glShaderSource.
785 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03786 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30787
[email protected]939e7362010-05-13 20:49:10788 // Checks if the current program exists and is valid. If not generates the
789 // appropriate GL error. Returns true if the current program is in a usable
790 // state.
791 bool CheckCurrentProgram(const char* function_name);
792
793 // Checks if the current program exists and is valid and that location is not
794 // -1. If the current program is not valid generates the appropriate GL
795 // error. Returns true if the current program is in a usable state and
796 // location is not -1.
797 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
798
799 // Gets the type of a uniform for a location in the current program. Sets GL
800 // errors if the current program is not valid. Returns true if the current
801 // program is valid and the location exists.
802 bool GetUniformTypeByLocation(
803 GLint location, const char* function_name, GLenum* type);
804
[email protected]b273e432010-04-12 17:23:58805 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
806 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
807
[email protected]96449d2c2009-11-25 00:01:32808 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03809 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32810
811 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03812 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32813
[email protected]3916c97e2010-02-25 03:20:50814 // Wrapper for glActiveTexture
815 void DoActiveTexture(GLenum texture_unit);
816
[email protected]ae51d192010-04-27 00:48:03817 // Wrapper for glAttachShader
818 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
819
[email protected]96449d2c2009-11-25 00:01:32820 // Wrapper for glBindBuffer since we need to track the current targets.
821 void DoBindBuffer(GLenum target, GLuint buffer);
822
[email protected]86093972010-03-11 00:13:56823 // Wrapper for glBindFramebuffer since we need to track the current targets.
824 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
825
826 // Wrapper for glBindRenderbuffer since we need to track the current targets.
827 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
828
[email protected]a93bb842010-02-16 23:03:47829 // Wrapper for glBindTexture since we need to track the current targets.
830 void DoBindTexture(GLenum target, GLuint texture);
831
[email protected]36cef8ce2010-03-16 07:34:45832 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11833 void DoBufferData(
834 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
835
[email protected]36cef8ce2010-03-16 07:34:45836 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11837 void DoBufferSubData(
838 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
839
[email protected]36cef8ce2010-03-16 07:34:45840 // Wrapper for glCheckFramebufferStatus
841 GLenum DoCheckFramebufferStatus(GLenum target);
842
[email protected]45bf5152010-02-12 00:11:31843 // Wrapper for glCompileShader.
844 void DoCompileShader(GLuint shader);
845
[email protected]066849e32010-05-03 19:14:10846 // Helper for DeleteSharedIds commands.
847 void DoDeleteSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
848
[email protected]ae51d192010-04-27 00:48:03849 // Wrapper for glDetachShader
850 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
851
[email protected]07f54fcc2009-12-22 02:46:30852 // Wrapper for glDrawArrays.
853 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
854
855 // Wrapper for glDisableVertexAttribArray.
856 void DoDisableVertexAttribArray(GLuint index);
857
858 // Wrapper for glEnableVertexAttribArray.
859 void DoEnableVertexAttribArray(GLuint index);
860
[email protected]36cef8ce2010-03-16 07:34:45861 // Wrapper for glFramebufferRenderbufffer.
862 void DoFramebufferRenderbuffer(
863 GLenum target, GLenum attachment, GLenum renderbuffertarget,
864 GLuint renderbuffer);
865
866 // Wrapper for glFramebufferTexture2D.
867 void DoFramebufferTexture2D(
868 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
869 GLint level);
870
[email protected]a93bb842010-02-16 23:03:47871 // Wrapper for glGenerateMipmap
872 void DoGenerateMipmap(GLenum target);
873
[email protected]066849e32010-05-03 19:14:10874 // Helper for GenSharedIds commands.
875 void DoGenSharedIds(
876 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
877
[email protected]b273e432010-04-12 17:23:58878 // Wrapper for DoGetBooleanv.
879 void DoGetBooleanv(GLenum pname, GLboolean* params);
880
881 // Wrapper for DoGetFloatv.
882 void DoGetFloatv(GLenum pname, GLfloat* params);
883
[email protected]36cef8ce2010-03-16 07:34:45884 // Wrapper for glGetFramebufferAttachmentParameteriv.
885 void DoGetFramebufferAttachmentParameteriv(
886 GLenum target, GLenum attachment, GLenum pname, GLint* params);
887
[email protected]a0c3e972010-04-21 00:49:13888 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:58889 void DoGetIntegerv(GLenum pname, GLint* params);
890
[email protected]29a9eb52010-04-13 09:04:23891 // Gets the max value in a range in a buffer.
892 GLuint DoGetMaxValueInBuffer(
893 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
894
[email protected]a0c3e972010-04-21 00:49:13895 // Wrapper for glGetProgramiv.
896 void DoGetProgramiv(
897 GLuint program_id, GLenum pname, GLint* params);
898
[email protected]36cef8ce2010-03-16 07:34:45899 // Wrapper for glRenderbufferParameteriv.
900 void DoGetRenderbufferParameteriv(
901 GLenum target, GLenum pname, GLint* params);
902
[email protected]ddd968b82010-03-02 00:44:29903 // Wrapper for glGetShaderiv
904 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
905
[email protected]b1122982010-05-17 23:04:24906 // Wrappers for glGetVertexAttrib.
907 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
908 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
909
[email protected]1958e0e2010-04-22 05:17:15910 // Wrappers for glIsXXX functions.
911 bool DoIsBuffer(GLuint client_id);
912 bool DoIsFramebuffer(GLuint client_id);
913 bool DoIsProgram(GLuint client_id);
914 bool DoIsRenderbuffer(GLuint client_id);
915 bool DoIsShader(GLuint client_id);
916 bool DoIsTexture(GLuint client_id);
917
[email protected]07f54fcc2009-12-22 02:46:30918 // Wrapper for glLinkProgram
919 void DoLinkProgram(GLuint program);
920
[email protected]066849e32010-05-03 19:14:10921 // Helper for RegisterSharedIds.
922 void DoRegisterSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids);
923
[email protected]36cef8ce2010-03-16 07:34:45924 // Wrapper for glRenderbufferStorage.
925 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:03926 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:45927
[email protected]b273e432010-04-12 17:23:58928 // Wrapper for glReleaseShaderCompiler.
929 void DoReleaseShaderCompiler() { }
930
[email protected]3916c97e2010-02-25 03:20:50931 // Wrappers for glTexParameter functions.
932 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
933 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
934 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
935 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
936
937 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
938 // spec only these 2 functions can be used to set sampler uniforms.
939 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:10940 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
941
942 // Wrappers for glUniformfv because some drivers don't correctly accept
943 // bool uniforms.
944 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
945 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
946 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
947 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:50948
[email protected]b1122982010-05-17 23:04:24949 // Wrappers for glVertexAttrib??
950 void DoVertexAttrib1f(GLuint index, GLfloat v0);
951 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
952 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
953 void DoVertexAttrib4f(
954 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
955 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
956 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
957 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
958 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
959
[email protected]07f54fcc2009-12-22 02:46:30960 // Wrapper for glUseProgram
961 void DoUseProgram(GLuint program);
962
[email protected]ae51d192010-04-27 00:48:03963 // Wrapper for glValidateProgram.
964 void DoValidateProgram(GLuint program_client_id);
965
[email protected]4e8a5b122010-05-08 22:00:10966 // Gets the number of values that will be returned by glGetXXX. Returns
967 // false if pname is unknown.
968 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
969
[email protected]96449d2c2009-11-25 00:01:32970 // Gets the GLError through our wrapper.
971 GLenum GetGLError();
972
973 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:29974 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:32975
[email protected]07f54fcc2009-12-22 02:46:30976 // Copies the real GL errors to the wrapper. This is so we can
977 // make sure there are no native GL errors before calling some GL function
978 // so that on return we know any error generated was for that specific
979 // command.
980 void CopyRealGLErrorsToWrapper();
981
[email protected]6217d392010-03-25 22:08:35982 // Clear all real GL errors. This is to prevent the client from seeing any
983 // errors caused by GL calls that it was not responsible for issuing.
984 void ClearRealGLErrors();
985
[email protected]07f54fcc2009-12-22 02:46:30986 // Checks if the current program and vertex attributes are valid for drawing.
987 bool IsDrawValid(GLuint max_vertex_accessed);
988
[email protected]b1122982010-05-17 23:04:24989 // Returns true if attrib0 was simulated.
990 bool SimulateAttrib0(GLuint max_vertex_accessed);
991 void RestoreStateForSimulatedAttrib0();
992
[email protected]3916c97e2010-02-25 03:20:50993 void SetBlackTextureForNonRenderableTextures(
994 bool* has_non_renderable_textures);
995 void RestoreStateForNonRenderableTextures();
996
[email protected]07f54fcc2009-12-22 02:46:30997 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:50998 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:30999 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501000 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1001 bound_array_buffer_ : bound_element_array_buffer_;
1002 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301003 }
1004
[email protected]a93bb842010-02-16 23:03:471005 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501006 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1007 TextureUnit& unit = texture_units_[active_texture_unit_];
1008 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471009 switch (target) {
1010 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501011 info = unit.bound_texture_2d;
1012 break;
[email protected]a93bb842010-02-16 23:03:471013 case GL_TEXTURE_CUBE_MAP:
1014 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1015 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1016 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1017 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1018 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1019 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501020 info = unit.bound_texture_cube_map;
1021 break;
[email protected]1aef98132010-02-23 18:00:071022 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1023 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1024 // because |texture_| is used by the FBO rendering mechanism for readback
1025 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471026 default:
1027 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501028 return NULL;
[email protected]a93bb842010-02-16 23:03:471029 }
[email protected]3916c97e2010-02-25 03:20:501030 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471031 }
1032
[email protected]f7b85372010-02-03 01:11:371033 // Validates the program and location for a glGetUniform call and returns
1034 // a SizeResult setup to receive the result. Returns true if glGetUniform
1035 // should be called.
1036 bool GetUniformSetup(
1037 GLuint program, GLint location,
1038 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101039 error::Error* error, GLuint* service_id, void** result,
1040 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371041
[email protected]86093972010-03-11 00:13:561042 bool ValidateGLenumCompressedTextureInternalFormat(GLenum format);
1043
[email protected]96449d2c2009-11-25 00:01:321044 // Generate a member function prototype for each command in an automated and
1045 // typesafe way.
1046 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141047 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191048 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321049 const gles2::name& args); \
1050
1051 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1052
1053 #undef GLES2_CMD_OP
1054
[email protected]2f2d7042010-04-14 21:45:581055 // The GL context this decoder renders to on behalf of the client.
[email protected]5a6db6c2010-04-22 18:32:061056 gfx::GLContext* context_;
[email protected]d37231fa2010-04-09 21:16:021057
[email protected]2f2d7042010-04-14 21:45:581058 // A GLContext that is kept in its default state. It is used to perform
1059 // operations that should not be dependent on client set GLContext state, like
1060 // clearing a render buffer when it is created.
1061 // TODO(apatrick): Decoders in the same ContextGroup could potentially share
1062 // the same default GL context.
[email protected]5a6db6c2010-04-22 18:32:061063 scoped_ptr<gfx::GLContext> default_context_;
[email protected]2f2d7042010-04-14 21:45:581064
[email protected]6217d392010-03-25 22:08:351065 // A parent decoder can access this decoders saved offscreen frame buffer.
1066 // The parent pointer is reset if the parent is destroyed.
1067 base::WeakPtr<GLES2DecoderImpl> parent_;
1068
1069 // Width and height to which an offscreen frame buffer should be resized on
1070 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021071 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351072
[email protected]96449d2c2009-11-25 00:01:321073 // Current GL error bits.
1074 uint32 error_bits_;
1075
[email protected]96449d2c2009-11-25 00:01:321076 // Util to help with GL.
1077 GLES2Util util_;
1078
1079 // pack alignment as last set by glPixelStorei
1080 GLint pack_alignment_;
1081
1082 // unpack alignment as last set by glPixelStorei
1083 GLint unpack_alignment_;
1084
1085 // The currently bound array buffer. If this is 0 it is illegal to call
1086 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501087 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321088
1089 // The currently bound element array buffer. If this is 0 it is illegal
1090 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501091 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301092
[email protected]f39f4b3f2010-05-12 17:04:081093 // Class that manages vertex attribs.
1094 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301095
[email protected]b1122982010-05-17 23:04:241096 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1097 GLuint attrib_0_buffer_id_;
1098
1099 // The value currently in attrib_0.
1100 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1101
1102 // The size of attrib 0.
1103 GLsizei attrib_0_size_;
1104
[email protected]3916c97e2010-02-25 03:20:501105 // Current active texture by 0 - n index.
1106 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1107 // be 2.
1108 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301109
[email protected]3916c97e2010-02-25 03:20:501110 // Which textures are bound to texture units through glActiveTexture.
1111 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471112
[email protected]cd6cd4762010-06-01 23:07:211113 // Black (0,0,0,1) textures for when non-renderable textures are used.
[email protected]3916c97e2010-02-25 03:20:501114 // NOTE: There is no corresponding TextureInfo for these textures.
1115 // TextureInfos are only for textures the client side can access.
1116 GLuint black_2d_texture_id_;
1117 GLuint black_cube_texture_id_;
[email protected]45bf5152010-02-12 00:11:311118
[email protected]1d32bc82010-01-13 22:06:461119 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501120 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301121
[email protected]86093972010-03-11 00:13:561122 // The currently bound framebuffer
[email protected]051b1372010-04-12 02:42:081123 FramebufferManager::FramebufferInfo::Ref bound_framebuffer_;
[email protected]86093972010-03-11 00:13:561124
1125 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081126 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561127
[email protected]96449d2c2009-11-25 00:01:321128 bool anti_aliased_;
1129
[email protected]6217d392010-03-25 22:08:351130 // The offscreen frame buffer that the client renders to.
1131 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1132 scoped_ptr<Texture> offscreen_target_color_texture_;
1133 scoped_ptr<RenderBuffer> offscreen_target_depth_stencil_render_buffer_;
1134
1135 // The copy that is saved when SwapBuffers is called.
1136 scoped_ptr<Texture> offscreen_saved_color_texture_;
1137
[email protected]43f28f832010-02-03 02:28:481138 scoped_ptr<Callback0::Type> swap_buffers_callback_;
1139
[email protected]8eee29c2010-04-29 03:38:291140 // The last error message set.
1141 std::string last_error_;
1142
[email protected]b1d2dcb2010-05-17 19:24:181143 bool use_shader_translator_;
1144
[email protected]96449d2c2009-11-25 00:01:321145 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1146};
1147
[email protected]6217d392010-03-25 22:08:351148ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1149 : decoder_(decoder) {
1150 decoder_->CopyRealGLErrorsToWrapper();
1151}
1152
1153ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1154 decoder_->ClearRealGLErrors();
1155}
1156
1157ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1158 GLuint id)
1159 : decoder_(decoder) {
1160 ScopedGLErrorSuppressor suppressor(decoder_);
1161
1162 // TODO(apatrick): Check if there are any other states that need to be reset
1163 // before binding a new texture.
1164 glActiveTexture(GL_TEXTURE0);
1165 glBindTexture(GL_TEXTURE_2D, id);
1166}
1167
1168ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1169 ScopedGLErrorSuppressor suppressor(decoder_);
1170 GLES2DecoderImpl::TextureUnit& info = decoder_->texture_units_[0];
1171 GLuint last_id;
1172 if (info.bound_texture_2d)
[email protected]ae51d192010-04-27 00:48:031173 last_id = info.bound_texture_2d->service_id();
[email protected]6217d392010-03-25 22:08:351174 else
1175 last_id = 0;
1176
1177 glBindTexture(GL_TEXTURE_2D, last_id);
1178 glActiveTexture(GL_TEXTURE0 + decoder_->active_texture_unit_);
1179}
1180
1181ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1182 GLuint id)
1183 : decoder_(decoder) {
1184 ScopedGLErrorSuppressor suppressor(decoder_);
1185 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1186}
1187
1188ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1189 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:081190 glBindRenderbufferEXT(
1191 GL_RENDERBUFFER,
1192 decoder_->bound_renderbuffer_ ?
[email protected]ae51d192010-04-27 00:48:031193 decoder_->bound_renderbuffer_->service_id() : 0);
[email protected]6217d392010-03-25 22:08:351194}
1195
1196ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1197 GLuint id)
1198 : decoder_(decoder) {
1199 ScopedGLErrorSuppressor suppressor(decoder_);
1200 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1201}
1202
1203ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1204 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:081205 FramebufferManager::FramebufferInfo* info =
1206 decoder_->bound_framebuffer_.get();
[email protected]ae51d192010-04-27 00:48:031207 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]051b1372010-04-12 02:42:081208 if (framebuffer_id == 0 &&
[email protected]6217d392010-03-25 22:08:351209 decoder_->offscreen_target_frame_buffer_.get()) {
1210 glBindFramebufferEXT(GL_FRAMEBUFFER,
1211 decoder_->offscreen_target_frame_buffer_->id());
1212 } else {
[email protected]051b1372010-04-12 02:42:081213 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_id);
[email protected]6217d392010-03-25 22:08:351214 }
1215}
1216
[email protected]2f2d7042010-04-14 21:45:581217ScopedDefaultGLContext::ScopedDefaultGLContext(GLES2DecoderImpl* decoder)
1218 : decoder_(decoder) {
1219 decoder_->default_context_->MakeCurrent();
1220}
1221
1222ScopedDefaultGLContext::~ScopedDefaultGLContext() {
1223 decoder_->context_->MakeCurrent();
1224}
1225
[email protected]6217d392010-03-25 22:08:351226Texture::Texture(GLES2DecoderImpl* decoder)
1227 : decoder_(decoder),
1228 id_(0) {
1229}
1230
1231Texture::~Texture() {
1232 // This does not destroy the render texture because that would require that
1233 // the associated GL context was current. Just check that it was explicitly
1234 // destroyed.
1235 DCHECK_EQ(id_, 0u);
1236}
1237
1238void Texture::Create() {
1239 ScopedGLErrorSuppressor suppressor(decoder_);
1240 Destroy();
1241 glGenTextures(1, &id_);
1242}
1243
1244bool Texture::AllocateStorage(const gfx::Size& size) {
1245 DCHECK_NE(id_, 0u);
1246 ScopedGLErrorSuppressor suppressor(decoder_);
1247 ScopedTexture2DBinder binder(decoder_, id_);
1248 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1249 glTexParameteri(
1250 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1251 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1253 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
1254
1255 glTexImage2D(GL_TEXTURE_2D,
1256 0, // mip level
1257 GL_RGBA,
1258 size.width(),
1259 size.height(),
1260 0, // border
1261 GL_RGBA,
1262 GL_UNSIGNED_BYTE,
1263 NULL);
1264
[email protected]d37231fa2010-04-09 21:16:021265 size_ = size;
1266
[email protected]6217d392010-03-25 22:08:351267 return glGetError() == GL_NO_ERROR;
1268}
1269
1270void Texture::Copy(const gfx::Size& size) {
1271 DCHECK_NE(id_, 0u);
1272 ScopedGLErrorSuppressor suppressor(decoder_);
1273 ScopedTexture2DBinder binder(decoder_, id_);
1274 glCopyTexImage2D(GL_TEXTURE_2D,
1275 0, // level
1276 GL_RGBA,
1277 0, 0,
1278 size.width(),
1279 size.height(),
1280 0); // border
1281}
1282
1283void Texture::Destroy() {
1284 if (id_ != 0) {
1285 ScopedGLErrorSuppressor suppressor(decoder_);
1286 glDeleteTextures(1, &id_);
1287 id_ = 0;
1288 }
1289}
1290
1291RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1292 : decoder_(decoder),
1293 id_(0) {
1294}
1295
1296RenderBuffer::~RenderBuffer() {
1297 // This does not destroy the render buffer because that would require that
1298 // the associated GL context was current. Just check that it was explicitly
1299 // destroyed.
1300 DCHECK_EQ(id_, 0u);
1301}
1302
1303void RenderBuffer::Create() {
1304 ScopedGLErrorSuppressor suppressor(decoder_);
1305 Destroy();
1306 glGenRenderbuffersEXT(1, &id_);
1307}
1308
1309bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format) {
1310 ScopedGLErrorSuppressor suppressor(decoder_);
1311 ScopedRenderBufferBinder binder(decoder_, id_);
1312 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1313 format,
1314 size.width(),
1315 size.height());
1316 return glGetError() == GL_NO_ERROR;
1317}
1318
1319void RenderBuffer::Destroy() {
1320 if (id_ != 0) {
1321 ScopedGLErrorSuppressor suppressor(decoder_);
1322 glDeleteRenderbuffersEXT(1, &id_);
1323 id_ = 0;
1324 }
1325}
1326
1327FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1328 : decoder_(decoder),
1329 id_(0) {
1330}
1331
1332FrameBuffer::~FrameBuffer() {
1333 // This does not destroy the frame buffer because that would require that
1334 // the associated GL context was current. Just check that it was explicitly
1335 // destroyed.
1336 DCHECK_EQ(id_, 0u);
1337}
1338
1339void FrameBuffer::Create() {
1340 ScopedGLErrorSuppressor suppressor(decoder_);
1341 Destroy();
1342 glGenFramebuffersEXT(1, &id_);
1343}
1344
1345void FrameBuffer::AttachRenderTexture(Texture* texture) {
1346 DCHECK_NE(id_, 0u);
1347 ScopedGLErrorSuppressor suppressor(decoder_);
1348 ScopedFrameBufferBinder binder(decoder_, id_);
1349 GLuint attach_id = texture ? texture->id() : 0;
1350 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1351 GL_COLOR_ATTACHMENT0,
1352 GL_TEXTURE_2D,
1353 attach_id,
1354 0);
1355}
1356
1357void FrameBuffer::AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer) {
1358 DCHECK_NE(id_, 0u);
1359 ScopedGLErrorSuppressor suppressor(decoder_);
1360 ScopedFrameBufferBinder binder(decoder_, id_);
1361 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1362 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
1363 GL_DEPTH_ATTACHMENT,
1364 GL_RENDERBUFFER,
1365 attach_id);
1366 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
1367 GL_STENCIL_ATTACHMENT,
1368 GL_RENDERBUFFER,
1369 attach_id);
1370}
1371
1372void FrameBuffer::Clear(GLbitfield buffers) {
1373 ScopedGLErrorSuppressor suppressor(decoder_);
1374 ScopedFrameBufferBinder binder(decoder_, id_);
1375 glClear(buffers);
1376}
1377
1378void FrameBuffer::Destroy() {
1379 if (id_ != 0) {
1380 ScopedGLErrorSuppressor suppressor(decoder_);
1381 glDeleteFramebuffersEXT(1, &id_);
1382 id_ = 0;
1383 }
1384}
1385
1386GLenum FrameBuffer::CheckStatus() {
1387 DCHECK_NE(id_, 0u);
1388 ScopedGLErrorSuppressor suppressor(decoder_);
1389 ScopedFrameBufferBinder binder(decoder_, id_);
1390 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1391}
1392
[email protected]3916c97e2010-02-25 03:20:501393GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1394 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321395}
1396
[email protected]3916c97e2010-02-25 03:20:501397GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
1398 : GLES2Decoder(group),
[email protected]d37231fa2010-04-09 21:16:021399 context_(NULL),
[email protected]96449d2c2009-11-25 00:01:321400 error_bits_(0),
1401 util_(0), // TODO(gman): Set to actual num compress texture formats.
1402 pack_alignment_(4),
1403 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241404 attrib_0_buffer_id_(0),
1405 attrib_0_size_(0),
[email protected]3916c97e2010-02-25 03:20:501406 active_texture_unit_(0),
1407 black_2d_texture_id_(0),
1408 black_cube_texture_id_(0),
[email protected]b1d2dcb2010-05-17 19:24:181409 anti_aliased_(false),
1410 use_shader_translator_(true) {
[email protected]b1122982010-05-17 23:04:241411 attrib_0_value_.v[0] = 0.0f;
1412 attrib_0_value_.v[1] = 0.0f;
1413 attrib_0_value_.v[2] = 0.0f;
1414 attrib_0_value_.v[3] = 1.0f;
[email protected]96449d2c2009-11-25 00:01:321415}
1416
[email protected]5a6db6c2010-04-22 18:32:061417bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:351418 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:021419 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:351420 uint32 parent_client_texture_id) {
[email protected]4bedba72010-04-20 22:08:541421 DCHECK(context);
[email protected]d37231fa2010-04-09 21:16:021422 DCHECK(!context_);
1423 context_ = context;
1424
[email protected]2f2d7042010-04-14 21:45:581425 // Create a GL context that is kept in a default state and shares a namespace
1426 // with the main GL context.
[email protected]5a6db6c2010-04-22 18:32:061427 default_context_.reset(gfx::GLContext::CreateOffscreenGLContext(
[email protected]4bedba72010-04-20 22:08:541428 context_->GetHandle()));
1429 if (!default_context_.get()) {
[email protected]2f2d7042010-04-14 21:45:581430 Destroy();
1431 return false;
1432 }
1433
[email protected]6217d392010-03-25 22:08:351434 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021435 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351436 if (parent)
1437 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1438
[email protected]246a70452010-03-05 21:53:501439 if (!MakeCurrent()) {
1440 Destroy();
1441 return false;
[email protected]eb54a562010-01-20 21:55:181442 }
1443
[email protected]246a70452010-03-05 21:53:501444 CHECK_GL_ERROR();
1445
1446 if (!group_->Initialize()) {
1447 Destroy();
1448 return false;
1449 }
1450
[email protected]f39f4b3f2010-05-12 17:04:081451 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]b1122982010-05-17 23:04:241452 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1453 // OpenGL ES 2.0 does not have this issue.
1454 glEnableVertexAttribArray(0);
1455 glGenBuffersARB(1, &attrib_0_buffer_id_);
1456 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1457 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1458 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]f39f4b3f2010-05-12 17:04:081459
[email protected]246a70452010-03-05 21:53:501460 texture_units_.reset(
1461 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151462 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
1463 texture_units_[tt].bound_texture_2d =
1464 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1465 texture_units_[tt].bound_texture_cube_map =
1466 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
1467 }
[email protected]4e8a5b122010-05-08 22:00:101468
[email protected]246a70452010-03-05 21:53:501469 GLuint ids[2];
1470 glGenTextures(2, ids);
1471 // Make black textures for replacing non-renderable textures.
1472 black_2d_texture_id_ = ids[0];
1473 black_cube_texture_id_ = ids[1];
[email protected]cd6cd4762010-06-01 23:07:211474 static uint8 black[] = {0, 0, 0, 255};
[email protected]246a70452010-03-05 21:53:501475 glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
1476 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
1477 GL_UNSIGNED_BYTE, black);
1478 glBindTexture(GL_TEXTURE_2D, 0);
1479 glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
[email protected]1958e0e2010-04-22 05:17:151480 for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
1481 glTexImage2D(GLES2Util::IndexToGLFaceTarget(ii), 0, GL_RGBA, 1, 1, 0,
1482 GL_RGBA, GL_UNSIGNED_BYTE, black);
[email protected]246a70452010-03-05 21:53:501483 }
1484 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
1485 CHECK_GL_ERROR();
1486
[email protected]d37231fa2010-04-09 21:16:021487#if !defined(UNIT_TEST)
1488 if (context_->IsOffscreen()) {
[email protected]6217d392010-03-25 22:08:351489 // Create the target frame buffer. This is the one that the client renders
1490 // directly to.
1491 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1492 offscreen_target_frame_buffer_->Create();
1493 offscreen_target_color_texture_.reset(new Texture(this));
1494 offscreen_target_color_texture_->Create();
1495 offscreen_target_depth_stencil_render_buffer_.reset(
1496 new RenderBuffer(this));
1497 offscreen_target_depth_stencil_render_buffer_->Create();
1498
1499 // Create the saved offscreen texture. The target frame buffer is copied
1500 // here when SwapBuffers is called.
1501 offscreen_saved_color_texture_.reset(new Texture(this));
1502 offscreen_saved_color_texture_->Create();
1503
[email protected]6217d392010-03-25 22:08:351504 // Map the ID of the saved offscreen texture into the parent so that
1505 // it can reference it.
1506 if (parent_) {
1507 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]6217d392010-03-25 22:08:351508 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:031509 parent_->CreateTextureInfo(parent_client_texture_id, service_id);
[email protected]6217d392010-03-25 22:08:351510 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
1511 }
1512
1513 // Allocate the render buffers at their initial size and check the status
1514 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021515 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351516 if (!UpdateOffscreenFrameBufferSize()) {
1517 DLOG(ERROR) << "Could not allocate offscreen buffer storage.";
1518 Destroy();
1519 return false;
1520 }
1521
1522 // Bind to the new default frame buffer (the offscreen target frame buffer).
1523 // This should now be associated with ID zero.
1524 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
1525 }
[email protected]d37231fa2010-04-09 21:16:021526#endif // UNIT_TEST
[email protected]6217d392010-03-25 22:08:351527
[email protected]76a0ee102010-04-07 21:03:041528#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1529 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1530 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1531 // isn't well documented; it was discovered in the Khronos OpenGL ES
1532 // mailing list archives.
1533 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]de17df392010-04-23 21:09:411534
[email protected]bc10076c2010-05-14 19:14:061535#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER) && !defined(UNIT_TEST)
[email protected]de17df392010-04-23 21:09:411536 // Initialize GLSL ES to GLSL translator.
1537 if (!ShInitialize()) {
1538 DLOG(ERROR) << "Could not initialize GLSL translator.";
1539 Destroy();
1540 return false;
1541 }
1542#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
1543#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
[email protected]76a0ee102010-04-07 21:03:041544
[email protected]246a70452010-03-05 21:53:501545 return true;
[email protected]96449d2c2009-11-25 00:01:321546}
1547
[email protected]ae51d192010-04-27 00:48:031548bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471549 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031550 if (GetBufferInfo(client_ids[ii])) {
1551 return false;
1552 }
1553 }
1554 scoped_array<GLuint> service_ids(new GLuint[n]);
1555 glGenBuffersARB(n, service_ids.get());
1556 for (GLsizei ii = 0; ii < n; ++ii) {
1557 CreateBufferInfo(client_ids[ii], service_ids[ii]);
1558 }
1559 return true;
1560}
1561
1562bool GLES2DecoderImpl::GenFramebuffersHelper(
1563 GLsizei n, const GLuint* client_ids) {
1564 for (GLsizei ii = 0; ii < n; ++ii) {
1565 if (GetFramebufferInfo(client_ids[ii])) {
1566 return false;
1567 }
1568 }
1569 scoped_array<GLuint> service_ids(new GLuint[n]);
1570 glGenFramebuffersEXT(n, service_ids.get());
1571 for (GLsizei ii = 0; ii < n; ++ii) {
1572 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
1573 }
1574 return true;
1575}
1576
1577bool GLES2DecoderImpl::GenRenderbuffersHelper(
1578 GLsizei n, const GLuint* client_ids) {
1579 for (GLsizei ii = 0; ii < n; ++ii) {
1580 if (GetRenderbufferInfo(client_ids[ii])) {
1581 return false;
1582 }
1583 }
1584 scoped_array<GLuint> service_ids(new GLuint[n]);
1585 glGenRenderbuffersEXT(n, service_ids.get());
1586 for (GLsizei ii = 0; ii < n; ++ii) {
1587 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
1588 }
1589 return true;
1590}
1591
1592bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
1593 for (GLsizei ii = 0; ii < n; ++ii) {
1594 if (GetTextureInfo(client_ids[ii])) {
1595 return false;
1596 }
1597 }
1598 scoped_array<GLuint> service_ids(new GLuint[n]);
1599 glGenTextures(n, service_ids.get());
1600 for (GLsizei ii = 0; ii < n; ++ii) {
1601 CreateTextureInfo(client_ids[ii], service_ids[ii]);
1602 }
1603 return true;
1604}
1605
1606void GLES2DecoderImpl::DeleteBuffersHelper(
1607 GLsizei n, const GLuint* client_ids) {
1608 for (GLsizei ii = 0; ii < n; ++ii) {
1609 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
1610 if (info) {
1611 GLuint service_id = info->service_id();
1612 glDeleteBuffersARB(1, &service_id);
1613 RemoveBufferInfo(client_ids[ii]);
1614 }
[email protected]a93bb842010-02-16 23:03:471615 }
[email protected]07f54fcc2009-12-22 02:46:301616}
1617
[email protected]ae51d192010-04-27 00:48:031618void GLES2DecoderImpl::DeleteFramebuffersHelper(
1619 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:581620 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031621 FramebufferManager::FramebufferInfo* info =
1622 GetFramebufferInfo(client_ids[ii]);
1623 if (info) {
1624 GLuint service_id = info->service_id();
1625 glDeleteFramebuffersEXT(1, &service_id);
1626 RemoveFramebufferInfo(client_ids[ii]);
1627 }
[email protected]a25fa872010-03-25 02:57:581628 }
[email protected]07f54fcc2009-12-22 02:46:301629}
1630
[email protected]ae51d192010-04-27 00:48:031631void GLES2DecoderImpl::DeleteRenderbuffersHelper(
1632 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:581633 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031634 RenderbufferManager::RenderbufferInfo* info =
1635 GetRenderbufferInfo(client_ids[ii]);
1636 if (info) {
1637 GLuint service_id = info->service_id();
1638 glDeleteRenderbuffersEXT(1, &service_id);
1639 RemoveRenderbufferInfo(client_ids[ii]);
1640 }
[email protected]a25fa872010-03-25 02:57:581641 }
[email protected]07f54fcc2009-12-22 02:46:301642}
1643
[email protected]ae51d192010-04-27 00:48:031644void GLES2DecoderImpl::DeleteTexturesHelper(
1645 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471646 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031647 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
1648 if (info) {
1649 GLuint service_id = info->service_id();
1650 glDeleteTextures(1, &service_id);
1651 RemoveTextureInfo(client_ids[ii]);
1652 }
[email protected]a93bb842010-02-16 23:03:471653 }
[email protected]07f54fcc2009-12-22 02:46:301654}
1655
[email protected]43f28f832010-02-03 02:28:481656// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:321657
[email protected]eb54a562010-01-20 21:55:181658bool GLES2DecoderImpl::MakeCurrent() {
1659#if defined(UNIT_TEST)
1660 return true;
[email protected]eb54a562010-01-20 21:55:181661#else
[email protected]d37231fa2010-04-09 21:16:021662 return context_->MakeCurrent();
[email protected]eb54a562010-01-20 21:55:181663#endif
1664}
1665
[email protected]d37231fa2010-04-09 21:16:021666gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() {
1667 if (bound_framebuffer_ != 0) {
1668 int width = 0;
1669 int height = 0;
[email protected]246a70452010-03-05 21:53:501670
[email protected]d37231fa2010-04-09 21:16:021671 // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
1672 // stencil.
1673 GLint fb_type = 0;
1674 glGetFramebufferAttachmentParameterivEXT(
1675 GL_FRAMEBUFFER,
1676 GL_COLOR_ATTACHMENT0,
1677 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
1678 &fb_type);
1679 switch (fb_type) {
1680 case GL_RENDERBUFFER:
1681 {
1682 GLint renderbuffer_id = 0;
1683 glGetFramebufferAttachmentParameterivEXT(
1684 GL_FRAMEBUFFER,
1685 GL_COLOR_ATTACHMENT0,
1686 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1687 &renderbuffer_id);
1688 if (renderbuffer_id != 0) {
1689 glGetRenderbufferParameterivEXT(
1690 GL_RENDERBUFFER,
1691 GL_RENDERBUFFER_WIDTH,
1692 &width);
1693 glGetRenderbufferParameterivEXT(
1694 GL_RENDERBUFFER,
1695 GL_RENDERBUFFER_HEIGHT,
1696 &height);
1697 }
1698 break;
1699 }
1700 case GL_TEXTURE:
1701 {
1702 GLint texture_id = 0;
1703 glGetFramebufferAttachmentParameterivEXT(
1704 GL_FRAMEBUFFER,
1705 GL_COLOR_ATTACHMENT0,
1706 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1707 &texture_id);
1708 if (texture_id != 0) {
[email protected]ae51d192010-04-27 00:48:031709 GLuint client_id = 0;
1710 if (texture_manager()->GetClientId(texture_id, &client_id)) {
1711 TextureManager::TextureInfo* texture_info =
1712 GetTextureInfo(client_id);
1713 if (texture_info) {
1714 GLint level = 0;
1715 GLint face = 0;
1716 glGetFramebufferAttachmentParameterivEXT(
1717 GL_FRAMEBUFFER,
1718 GL_COLOR_ATTACHMENT0,
1719 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
1720 &level);
1721 glGetFramebufferAttachmentParameterivEXT(
1722 GL_FRAMEBUFFER,
1723 GL_COLOR_ATTACHMENT0,
1724 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
1725 &face);
1726 texture_info->GetLevelSize(
1727 face ? face : GL_TEXTURE_2D, level, &width, &height);
1728 }
[email protected]d37231fa2010-04-09 21:16:021729 }
1730 }
1731 break;
1732 }
1733 default:
1734 // unknown so assume width and height are zero.
1735 break;
[email protected]246a70452010-03-05 21:53:501736 }
1737
[email protected]d37231fa2010-04-09 21:16:021738 return gfx::Size(width, height);
1739 } else if (offscreen_target_color_texture_.get()) {
1740 return offscreen_target_color_texture_->size();
[email protected]6217d392010-03-25 22:08:351741 } else {
[email protected]246a70452010-03-05 21:53:501742#if defined(UNIT_TEST)
[email protected]d37231fa2010-04-09 21:16:021743 return gfx::Size(INT_MAX, INT_MAX);
1744#else
1745 return context_->GetSize();
[email protected]246a70452010-03-05 21:53:501746#endif
[email protected]d37231fa2010-04-09 21:16:021747 }
[email protected]246a70452010-03-05 21:53:501748}
1749
[email protected]6217d392010-03-25 22:08:351750bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]d37231fa2010-04-09 21:16:021751 if (offscreen_target_color_texture_->size() == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:351752 return true;
1753
[email protected]2f2d7042010-04-14 21:45:581754 if (parent_) {
1755 // Create the saved offscreen color texture (only accessible to parent).
1756 offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
1757
1758 // Attach the saved offscreen color texture to a frame buffer so we can
1759 // clear it with glClear.
1760 offscreen_target_frame_buffer_->AttachRenderTexture(
1761 offscreen_saved_color_texture_.get());
1762 if (offscreen_target_frame_buffer_->CheckStatus() !=
1763 GL_FRAMEBUFFER_COMPLETE) {
1764 return false;
1765 }
1766
1767#if !defined(UNIT_TEST)
1768 // Clear the saved offscreen color texture. Use default GL context
1769 // to ensure clear is not affected by client set state.
[email protected]1958e0e2010-04-22 05:17:151770 { // NOLINT
[email protected]2f2d7042010-04-14 21:45:581771 ScopedDefaultGLContext scoped_context(this);
1772 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
1773 offscreen_target_frame_buffer_->id());
1774 glClear(GL_COLOR_BUFFER_BIT);
1775 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1776
1777 if (glGetError() != GL_NO_ERROR)
1778 return false;
1779 }
1780#endif
1781 }
1782
[email protected]6217d392010-03-25 22:08:351783 // Reallocate the offscreen target buffers.
[email protected]d37231fa2010-04-09 21:16:021784 if (!offscreen_target_color_texture_->AllocateStorage(
1785 pending_offscreen_size_)) {
[email protected]6217d392010-03-25 22:08:351786 return false;
1787 }
1788
1789 if (!offscreen_target_depth_stencil_render_buffer_->AllocateStorage(
[email protected]d37231fa2010-04-09 21:16:021790 pending_offscreen_size_, GL_DEPTH24_STENCIL8)) {
[email protected]6217d392010-03-25 22:08:351791 return false;
1792 }
1793
[email protected]2f2d7042010-04-14 21:45:581794 // Attach the offscreen target buffers to the target frame buffer.
[email protected]6217d392010-03-25 22:08:351795 offscreen_target_frame_buffer_->AttachRenderTexture(
1796 offscreen_target_color_texture_.get());
1797 offscreen_target_frame_buffer_->AttachDepthStencilRenderBuffer(
1798 offscreen_target_depth_stencil_render_buffer_.get());
1799 if (offscreen_target_frame_buffer_->CheckStatus() !=
1800 GL_FRAMEBUFFER_COMPLETE) {
1801 return false;
1802 }
1803
[email protected]2f2d7042010-04-14 21:45:581804#if !defined(UNIT_TEST)
1805 // Clear offscreen frame buffer to its initial state. Use default GL context
1806 // to ensure clear is not affected by client set state.
[email protected]1958e0e2010-04-22 05:17:151807 { // NOLINT
[email protected]2f2d7042010-04-14 21:45:581808 ScopedDefaultGLContext scoped_context(this);
1809 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
1810 offscreen_target_frame_buffer_->id());
1811 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1812 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1813
1814 if (glGetError() != GL_NO_ERROR)
1815 return false;
1816 }
1817#endif
1818
[email protected]6217d392010-03-25 22:08:351819 if (parent_) {
[email protected]d37231fa2010-04-09 21:16:021820 // Create the saved offscreen color texture (only accessible to parent).
1821 offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
1822
[email protected]2f2d7042010-04-14 21:45:581823 // Update the info about the offscreen saved color texture in the parent.
1824 // The reference to the parent is a weak pointer and will become null if the
1825 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:351826 GLuint service_id = offscreen_saved_color_texture_->id();
1827
1828 TextureManager::TextureInfo* info =
1829 parent_->texture_manager()->GetTextureInfo(service_id);
1830 DCHECK(info);
1831
1832 info->SetLevelInfo(GL_TEXTURE_2D,
1833 0, // level
1834 GL_RGBA,
[email protected]d37231fa2010-04-09 21:16:021835 pending_offscreen_size_.width(),
1836 pending_offscreen_size_.height(),
[email protected]6217d392010-03-25 22:08:351837 1, // depth
1838 0, // border
1839 GL_RGBA,
1840 GL_UNSIGNED_BYTE);
1841 }
1842
[email protected]6217d392010-03-25 22:08:351843 return true;
1844}
1845
[email protected]43f28f832010-02-03 02:28:481846void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
1847 swap_buffers_callback_.reset(callback);
1848}
1849
[email protected]96449d2c2009-11-25 00:01:321850void GLES2DecoderImpl::Destroy() {
[email protected]4bedba72010-04-20 22:08:541851 if (context_) {
1852 MakeCurrent();
[email protected]6217d392010-03-25 22:08:351853
[email protected]b1122982010-05-17 23:04:241854 if (black_2d_texture_id_) {
1855 glDeleteTextures(1, &black_2d_texture_id_);
1856 }
1857 if (black_cube_texture_id_) {
1858 glDeleteTextures(1, &black_cube_texture_id_);
1859 }
1860 if (attrib_0_buffer_id_) {
1861 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
1862 }
1863
[email protected]4bedba72010-04-20 22:08:541864 // Remove the saved frame buffer mapping from the parent decoder. The
1865 // parent pointer is a weak pointer so it will be null if the parent has
1866 // already been destroyed.
1867 if (parent_) {
1868 // First check the texture has been mapped into the parent. This might not
1869 // be the case if initialization failed midway through.
1870 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]ae51d192010-04-27 00:48:031871 GLuint client_id = 0;
1872 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
1873 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]4bedba72010-04-20 22:08:541874 }
[email protected]6217d392010-03-25 22:08:351875 }
[email protected]6217d392010-03-25 22:08:351876
[email protected]4bedba72010-04-20 22:08:541877 if (offscreen_target_frame_buffer_.get()) {
1878 offscreen_target_frame_buffer_->Destroy();
1879 offscreen_target_frame_buffer_.reset();
1880 }
[email protected]6217d392010-03-25 22:08:351881
[email protected]4bedba72010-04-20 22:08:541882 if (offscreen_target_color_texture_.get()) {
1883 offscreen_target_color_texture_->Destroy();
1884 offscreen_target_color_texture_.reset();
1885 }
[email protected]6217d392010-03-25 22:08:351886
[email protected]4bedba72010-04-20 22:08:541887 if (offscreen_target_depth_stencil_render_buffer_.get()) {
1888 offscreen_target_depth_stencil_render_buffer_->Destroy();
1889 offscreen_target_depth_stencil_render_buffer_.reset();
1890 }
[email protected]6217d392010-03-25 22:08:351891
[email protected]4bedba72010-04-20 22:08:541892 if (offscreen_saved_color_texture_.get()) {
1893 offscreen_saved_color_texture_->Destroy();
1894 offscreen_saved_color_texture_.reset();
1895 }
[email protected]d37231fa2010-04-09 21:16:021896 }
[email protected]2f2d7042010-04-14 21:45:581897
1898 if (default_context_.get()) {
1899 default_context_->Destroy();
1900 default_context_.reset();
1901 }
[email protected]de17df392010-04-23 21:09:411902
[email protected]bc10076c2010-05-14 19:14:061903#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) && !defined(UNIT_TEST)
[email protected]de17df392010-04-23 21:09:411904#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
1905 // Terminate GLSL translator.
1906 ShFinalize();
1907#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
1908#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
[email protected]96449d2c2009-11-25 00:01:321909}
1910
[email protected]6217d392010-03-25 22:08:351911void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
1912 // We can't resize the render buffers immediately because there might be a
1913 // partial frame rendered into them and we don't want the tail end of that
1914 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021915 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351916}
1917
[email protected]96449d2c2009-11-25 00:01:321918const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
1919 if (command_id > kStartPoint && command_id < kNumCommands) {
1920 return gles2::GetCommandName(static_cast<CommandId>(command_id));
1921 }
1922 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
1923}
1924
1925// Decode command with its arguments, and call the corresponding GL function.
1926// Note: args is a pointer to the command buffer. As such, it could be changed
1927// by a (malicious) client at any time, so if validation has to happen, it
1928// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:141929error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:321930 unsigned int command,
1931 unsigned int arg_count,
1932 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:141933 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191934 if (debug()) {
1935 // TODO(gman): Change output to something useful for NaCl.
[email protected]f39f4b3f2010-05-12 17:04:081936 DLOG(INFO) << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:191937 }
[email protected]96449d2c2009-11-25 00:01:321938 unsigned int command_index = command - kStartPoint - 1;
1939 if (command_index < arraysize(g_command_info)) {
1940 const CommandInfo& info = g_command_info[command_index];
1941 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
1942 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
1943 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:191944 uint32 immediate_data_size =
1945 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:321946 switch (command) {
1947 #define GLES2_CMD_OP(name) \
1948 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:191949 result = Handle ## name( \
1950 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321951 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:191952 break; \
[email protected]96449d2c2009-11-25 00:01:321953
1954 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:321955 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:381956 }
1957 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:301958 GLenum error;
1959 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:381960 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:291961 SetGLError(error, NULL);
[email protected]f39f4b3f2010-05-12 17:04:081962 DLOG(INFO) << "GL ERROR: " << error
1963 << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:191964 }
[email protected]96449d2c2009-11-25 00:01:321965 }
1966 } else {
[email protected]f7a64ee2010-02-01 22:24:141967 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:321968 }
[email protected]b9849abf2009-11-25 19:13:191969 } else {
1970 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:321971 }
[email protected]b9849abf2009-11-25 19:13:191972 return result;
[email protected]96449d2c2009-11-25 00:01:321973}
1974
[email protected]ae51d192010-04-27 00:48:031975void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
1976 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:501977}
1978
[email protected]ae51d192010-04-27 00:48:031979bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
1980 if (GetProgramInfo(client_id)) {
1981 return false;
1982 }
[email protected]96449d2c2009-11-25 00:01:321983 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:031984 if (service_id != 0) {
1985 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:321986 }
[email protected]ae51d192010-04-27 00:48:031987 return true;
[email protected]96449d2c2009-11-25 00:01:321988}
1989
[email protected]ae51d192010-04-27 00:48:031990bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
1991 if (GetShaderInfo(client_id)) {
1992 return false;
[email protected]96449d2c2009-11-25 00:01:321993 }
[email protected]ae51d192010-04-27 00:48:031994 GLuint service_id = glCreateShader(type);
1995 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:381996 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:031997 }
1998 return true;
[email protected]96449d2c2009-11-25 00:01:321999}
2000
[email protected]86093972010-03-11 00:13:562001bool GLES2DecoderImpl::ValidateGLenumCompressedTextureInternalFormat(GLenum) {
2002 // TODO(gman): Add support for compressed texture formats.
2003 return false;
2004}
2005
[email protected]3916c97e2010-02-25 03:20:502006void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452007 GLuint texture_index = texture_unit - GL_TEXTURE0;
2008 if (texture_index > group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292009 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502010 return;
2011 }
[email protected]36cef8ce2010-03-16 07:34:452012 active_texture_unit_ = texture_index;
2013 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502014}
2015
[email protected]051b1372010-04-12 02:42:082016void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502017 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082018 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032019 if (client_id != 0) {
2020 info = GetBufferInfo(client_id);
2021 if (!info) {
2022 // It's a new id so make a buffer info for it.
2023 glGenBuffersARB(1, &service_id);
2024 CreateBufferInfo(client_id, service_id);
2025 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102026 IdAllocator* id_allocator =
2027 group_->GetIdAllocator(id_namespaces::kBuffers);
2028 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032029 }
[email protected]051b1372010-04-12 02:42:082030 }
[email protected]ae51d192010-04-27 00:48:032031 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102032 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292033 SetGLError(GL_INVALID_OPERATION,
2034 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472035 return;
2036 }
[email protected]ae51d192010-04-27 00:48:032037 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472038 }
[email protected]96449d2c2009-11-25 00:01:322039 switch (target) {
2040 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502041 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322042 break;
2043 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502044 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322045 break;
2046 default:
[email protected]a93bb842010-02-16 23:03:472047 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322048 break;
2049 }
[email protected]051b1372010-04-12 02:42:082050 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322051}
2052
[email protected]051b1372010-04-12 02:42:082053void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2054 FramebufferManager::FramebufferInfo* info = NULL;
2055 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032056 if (client_id != 0) {
2057 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082058 if (!info) {
[email protected]ae51d192010-04-27 00:48:032059 // It's a new id so make a framebuffer info for it.
2060 glGenFramebuffersEXT(1, &service_id);
2061 CreateFramebufferInfo(client_id, service_id);
2062 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102063 IdAllocator* id_allocator =
2064 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2065 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032066 } else {
2067 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082068 }
2069 }
2070 bound_framebuffer_ = info;
[email protected]6217d392010-03-25 22:08:352071
2072 // When rendering to an offscreen frame buffer, instead of unbinding from
2073 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:082074 if (info == NULL && offscreen_target_frame_buffer_.get())
2075 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:352076
[email protected]051b1372010-04-12 02:42:082077 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562078}
2079
[email protected]051b1372010-04-12 02:42:082080void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2081 RenderbufferManager::RenderbufferInfo* info = NULL;
2082 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032083 if (client_id != 0) {
2084 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082085 if (!info) {
[email protected]ae51d192010-04-27 00:48:032086 // It's a new id so make a renderbuffer info for it.
2087 glGenRenderbuffersEXT(1, &service_id);
2088 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102089 info = GetRenderbufferInfo(client_id);
2090 IdAllocator* id_allocator =
2091 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2092 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032093 } else {
2094 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082095 }
2096 }
2097 bound_renderbuffer_ = info;
2098 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562099}
2100
[email protected]051b1372010-04-12 02:42:082101void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032102 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082103 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032104 if (client_id != 0) {
2105 info = GetTextureInfo(client_id);
2106 if (!info) {
2107 // It's a new id so make a texture info for it.
2108 glGenTextures(1, &service_id);
2109 CreateTextureInfo(client_id, service_id);
2110 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:102111 IdAllocator* id_allocator =
2112 group_->GetIdAllocator(id_namespaces::kTextures);
2113 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032114 }
2115 } else {
2116 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082117 }
[email protected]ae51d192010-04-27 00:48:032118
[email protected]1958e0e2010-04-22 05:17:152119 // Check the texture exists
2120 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032121 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292122 SetGLError(GL_INVALID_OPERATION,
2123 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152124 return;
2125 }
2126 if (info->target() == 0) {
2127 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472128 }
[email protected]ae51d192010-04-27 00:48:032129 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502130 TextureUnit& unit = texture_units_[active_texture_unit_];
2131 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472132 switch (target) {
2133 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502134 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472135 break;
2136 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502137 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472138 break;
2139 default:
2140 NOTREACHED(); // Validation should prevent us getting here.
2141 break;
2142 }
2143}
2144
[email protected]07f54fcc2009-12-22 02:46:302145void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082146 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]b1122982010-05-17 23:04:242147 if (index != 0) {
2148 glDisableVertexAttribArray(index);
2149 }
[email protected]07f54fcc2009-12-22 02:46:302150 } else {
[email protected]8eee29c2010-04-29 03:38:292151 SetGLError(GL_INVALID_VALUE,
2152 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302153 }
2154}
2155
2156void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082157 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302158 glEnableVertexAttribArray(index);
2159 } else {
[email protected]8eee29c2010-04-29 03:38:292160 SetGLError(GL_INVALID_VALUE,
2161 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302162 }
2163}
2164
[email protected]a93bb842010-02-16 23:03:472165void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502166 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2167 if (!info || !info->MarkMipmapsGenerated()) {
[email protected]8eee29c2010-04-29 03:38:292168 SetGLError(GL_INVALID_OPERATION,
2169 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472170 return;
2171 }
2172 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:472173}
2174
[email protected]b273e432010-04-12 17:23:582175bool GLES2DecoderImpl::GetHelper(
2176 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582177 DCHECK(num_written);
2178 switch (pname) {
[email protected]58ae32f2010-04-14 01:26:042179#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]b273e432010-04-12 17:23:582180 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2181 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102182 if (params) {
2183 *params = GL_RGBA; // TODO(gman): get correct format.
2184 }
[email protected]b273e432010-04-12 17:23:582185 return true;
2186 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2187 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102188 if (params) {
2189 *params = GL_UNSIGNED_BYTE; // TODO(gman): get correct type.
2190 }
[email protected]b273e432010-04-12 17:23:582191 return true;
2192 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2193 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102194 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482195 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102196 }
[email protected]b273e432010-04-12 17:23:582197 return true;
2198 case GL_MAX_VARYING_VECTORS:
2199 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102200 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482201 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102202 }
[email protected]b273e432010-04-12 17:23:582203 return true;
2204 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2205 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102206 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482207 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102208 }
[email protected]b273e432010-04-12 17:23:582209 return true;
[email protected]58ae32f2010-04-14 01:26:042210#endif
[email protected]656dcaad2010-05-07 17:18:372211 case GL_COMPRESSED_TEXTURE_FORMATS:
2212 *num_written = 0;
2213 // We don't support compressed textures.
2214 return true;
[email protected]b273e432010-04-12 17:23:582215 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
2216 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102217 if (params) {
2218 *params = 0; // We don't support compressed textures.
2219 }
[email protected]b273e432010-04-12 17:23:582220 return true;
2221 case GL_NUM_SHADER_BINARY_FORMATS:
2222 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102223 if (params) {
2224 *params = 0; // We don't support binary shader formats.
2225 }
[email protected]b273e432010-04-12 17:23:582226 return true;
2227 case GL_SHADER_BINARY_FORMATS:
2228 *num_written = 0;
2229 return true; // We don't support binary shader format.s
2230 case GL_SHADER_COMPILER:
2231 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102232 if (params) {
2233 *params = GL_TRUE;
2234 }
[email protected]b273e432010-04-12 17:23:582235 return true;
[email protected]6b8cf1a2010-05-06 16:13:582236 case GL_ARRAY_BUFFER_BINDING:
2237 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102238 if (params) {
2239 if (bound_array_buffer_) {
2240 GLuint client_id = 0;
2241 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
2242 &client_id);
2243 *params = client_id;
2244 } else {
2245 *params = 0;
2246 }
[email protected]6b8cf1a2010-05-06 16:13:582247 }
2248 return true;
2249 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
2250 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102251 if (params) {
2252 if (bound_element_array_buffer_) {
2253 GLuint client_id = 0;
2254 buffer_manager()->GetClientId(
2255 bound_element_array_buffer_->service_id(),
2256 &client_id);
2257 *params = client_id;
2258 } else {
2259 *params = 0;
2260 }
[email protected]6b8cf1a2010-05-06 16:13:582261 }
2262 return true;
2263 case GL_FRAMEBUFFER_BINDING:
2264 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102265 if (params) {
2266 if (bound_framebuffer_) {
2267 GLuint client_id = 0;
2268 framebuffer_manager()->GetClientId(
2269 bound_framebuffer_->service_id(), &client_id);
2270 *params = client_id;
2271 } else {
2272 *params = 0;
2273 }
[email protected]6b8cf1a2010-05-06 16:13:582274 }
2275 return true;
2276 case GL_RENDERBUFFER_BINDING:
2277 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102278 if (params) {
2279 if (bound_renderbuffer_) {
2280 GLuint client_id = 0;
2281 renderbuffer_manager()->GetClientId(
2282 bound_renderbuffer_->service_id(), &client_id);
2283 *params = client_id;
2284 } else {
2285 *params = 0;
2286 }
[email protected]6b8cf1a2010-05-06 16:13:582287 }
2288 return true;
2289 case GL_CURRENT_PROGRAM:
2290 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102291 if (params) {
2292 if (current_program_) {
2293 GLuint client_id = 0;
2294 program_manager()->GetClientId(
2295 current_program_->service_id(), &client_id);
2296 *params = client_id;
2297 } else {
2298 *params = 0;
2299 }
[email protected]6b8cf1a2010-05-06 16:13:582300 }
2301 return true;
[email protected]4e8a5b122010-05-08 22:00:102302 case GL_TEXTURE_BINDING_2D:
2303 *num_written = 1;
2304 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582305 TextureUnit& unit = texture_units_[active_texture_unit_];
2306 if (unit.bound_texture_2d) {
2307 GLuint client_id = 0;
2308 texture_manager()->GetClientId(
2309 unit.bound_texture_2d->service_id(), &client_id);
2310 *params = client_id;
2311 } else {
2312 *params = 0;
2313 }
[email protected]6b8cf1a2010-05-06 16:13:582314 }
[email protected]4e8a5b122010-05-08 22:00:102315 return true;
2316 case GL_TEXTURE_BINDING_CUBE_MAP:
2317 *num_written = 1;
2318 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582319 TextureUnit& unit = texture_units_[active_texture_unit_];
2320 if (unit.bound_texture_cube_map) {
2321 GLuint client_id = 0;
2322 texture_manager()->GetClientId(
2323 unit.bound_texture_cube_map->service_id(), &client_id);
2324 *params = client_id;
2325 } else {
2326 *params = 0;
2327 }
[email protected]6b8cf1a2010-05-06 16:13:582328 }
[email protected]4e8a5b122010-05-08 22:00:102329 return true;
[email protected]b273e432010-04-12 17:23:582330 default:
[email protected]4e8a5b122010-05-08 22:00:102331 *num_written = util_.GLGetNumValuesReturned(pname);
2332 if (params) {
2333 glGetIntegerv(pname, params);
2334 }
2335 return true;
[email protected]b273e432010-04-12 17:23:582336 }
2337}
2338
[email protected]4e8a5b122010-05-08 22:00:102339bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
2340 GLenum pname, GLsizei* num_values) {
2341 return GetHelper(pname, NULL, num_values);
2342}
2343
[email protected]b273e432010-04-12 17:23:582344void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
2345 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:102346 GLsizei num_written = 0;
2347 if (GetHelper(pname, NULL, &num_written)) {
2348 scoped_array<GLint> values(new GLint[num_written]);
2349 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:582350 for (GLsizei ii = 0; ii < num_written; ++ii) {
2351 params[ii] = static_cast<GLboolean>(values[ii]);
2352 }
2353 } else {
2354 glGetBooleanv(pname, params);
2355 }
2356}
2357
2358void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
2359 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:102360 GLsizei num_written = 0;
2361 if (GetHelper(pname, NULL, &num_written)) {
2362 scoped_array<GLint> values(new GLint[num_written]);
2363 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:582364 for (GLsizei ii = 0; ii < num_written; ++ii) {
2365 params[ii] = static_cast<GLfloat>(values[ii]);
2366 }
2367 } else {
2368 glGetFloatv(pname, params);
2369 }
2370}
2371
2372void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
2373 DCHECK(params);
2374 GLsizei num_written;
2375 if (!GetHelper(pname, params, &num_written)) {
2376 glGetIntegerv(pname, params);
2377 }
2378}
2379
[email protected]a0c3e972010-04-21 00:49:132380void GLES2DecoderImpl::DoGetProgramiv(
2381 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:582382 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2383 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:132384 if (!info) {
[email protected]a0c3e972010-04-21 00:49:132385 return;
2386 }
2387 info->GetProgramiv(pname, params);
2388}
2389
[email protected]558847a2010-03-24 07:02:542390error::Error GLES2DecoderImpl::HandleBindAttribLocation(
2391 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:582392 GLuint program = static_cast<GLuint>(c.program);
2393 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2394 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032395 if (!info) {
[email protected]558847a2010-03-24 07:02:542396 return error::kNoError;
2397 }
2398 GLuint index = static_cast<GLuint>(c.index);
2399 uint32 name_size = c.data_size;
2400 const char* name = GetSharedMemoryAs<const char*>(
2401 c.name_shm_id, c.name_shm_offset, name_size);
2402 if (name == NULL) {
2403 return error::kOutOfBounds;
2404 }
2405 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:032406 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542407 return error::kNoError;
2408}
2409
2410error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
2411 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:582412 GLuint program = static_cast<GLuint>(c.program);
2413 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2414 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032415 if (!info) {
[email protected]558847a2010-03-24 07:02:542416 return error::kNoError;
2417 }
2418 GLuint index = static_cast<GLuint>(c.index);
2419 uint32 name_size = c.data_size;
2420 const char* name = GetImmediateDataAs<const char*>(
2421 c, name_size, immediate_data_size);
2422 if (name == NULL) {
2423 return error::kOutOfBounds;
2424 }
2425 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:032426 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542427 return error::kNoError;
2428}
2429
2430error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
2431 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:582432 GLuint program = static_cast<GLuint>(c.program);
2433 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2434 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032435 if (!info) {
[email protected]558847a2010-03-24 07:02:542436 return error::kNoError;
2437 }
2438 GLuint index = static_cast<GLuint>(c.index);
2439 Bucket* bucket = GetBucket(c.name_bucket_id);
2440 if (!bucket || bucket->size() == 0) {
2441 return error::kInvalidArguments;
2442 }
2443 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:182444 if (!bucket->GetAsString(&name_str)) {
2445 return error::kInvalidArguments;
2446 }
[email protected]ae51d192010-04-27 00:48:032447 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542448 return error::kNoError;
2449}
2450
[email protected]f7a64ee2010-02-01 22:24:142451error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:462452 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:032453 GLuint client_id = c.shader;
2454 if (client_id) {
2455 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
2456 if (info) {
2457 glDeleteShader(info->service_id());
2458 RemoveShaderInfo(client_id);
2459 } else {
[email protected]8eee29c2010-04-29 03:38:292460 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:032461 }
[email protected]96449d2c2009-11-25 00:01:322462 }
[email protected]f7a64ee2010-02-01 22:24:142463 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322464}
2465
[email protected]f7a64ee2010-02-01 22:24:142466error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:462467 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:032468 GLuint client_id = c.program;
2469 if (client_id) {
2470 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
2471 if (info) {
2472 glDeleteProgram(info->service_id());
2473 RemoveProgramInfo(client_id);
2474 } else {
[email protected]8eee29c2010-04-29 03:38:292475 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:032476 }
[email protected]96449d2c2009-11-25 00:01:322477 }
[email protected]f7a64ee2010-02-01 22:24:142478 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322479}
2480
[email protected]066849e32010-05-03 19:14:102481void GLES2DecoderImpl::DoDeleteSharedIds(
2482 GLuint namespace_id, GLsizei n, const GLuint* ids) {
2483 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2484 for (GLsizei ii = 0; ii < n; ++ii) {
2485 id_allocator->FreeID(ids[ii]);
2486 }
2487}
2488
2489error::Error GLES2DecoderImpl::HandleDeleteSharedIds(
2490 uint32 immediate_data_size, const gles2::DeleteSharedIds& c) {
2491 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2492 GLsizei n = static_cast<GLsizei>(c.n);
2493 uint32 data_size;
2494 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2495 return error::kOutOfBounds;
2496 }
2497 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
2498 c.ids_shm_id, c.ids_shm_offset, data_size);
2499 if (n < 0) {
2500 SetGLError(GL_INVALID_VALUE, "DeleteSharedIds: n < 0");
2501 return error::kNoError;
2502 }
2503 if (ids == NULL) {
2504 return error::kOutOfBounds;
2505 }
2506 DoDeleteSharedIds(namespace_id, n, ids);
2507 return error::kNoError;
2508}
2509
2510void GLES2DecoderImpl::DoGenSharedIds(
2511 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
2512 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2513 if (id_offset == 0) {
2514 for (GLsizei ii = 0; ii < n; ++ii) {
2515 ids[ii] = id_allocator->AllocateID();
2516 }
2517 } else {
2518 for (GLsizei ii = 0; ii < n; ++ii) {
2519 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
2520 id_offset = ids[ii] + 1;
2521 }
2522 }
2523}
2524
2525error::Error GLES2DecoderImpl::HandleGenSharedIds(
2526 uint32 immediate_data_size, const gles2::GenSharedIds& c) {
2527 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2528 GLuint id_offset = static_cast<GLuint>(c.id_offset);
2529 GLsizei n = static_cast<GLsizei>(c.n);
2530 uint32 data_size;
2531 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2532 return error::kOutOfBounds;
2533 }
2534 GLuint* ids = GetSharedMemoryAs<GLuint*>(
2535 c.ids_shm_id, c.ids_shm_offset, data_size);
2536 if (n < 0) {
2537 SetGLError(GL_INVALID_VALUE, "GenSharedIds: n < 0");
2538 return error::kNoError;
2539 }
2540 if (ids == NULL) {
2541 return error::kOutOfBounds;
2542 }
2543 DoGenSharedIds(namespace_id, id_offset, n, ids);
2544 return error::kNoError;
2545}
2546
2547void GLES2DecoderImpl::DoRegisterSharedIds(
2548 GLuint namespace_id, GLsizei n, const GLuint* ids) {
2549 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2550 for (GLsizei ii = 0; ii < n; ++ii) {
2551 if (!id_allocator->MarkAsUsed(ids[ii])) {
2552 for (GLsizei jj = 0; jj < ii; ++jj) {
2553 id_allocator->FreeID(ids[jj]);
2554 }
2555 SetGLError(
2556 GL_INVALID_VALUE,
2557 "RegisterSharedIds: attempt to register id that already exists");
2558 return;
2559 }
2560 }
2561}
2562
2563error::Error GLES2DecoderImpl::HandleRegisterSharedIds(
2564 uint32 immediate_data_size, const gles2::RegisterSharedIds& c) {
2565 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2566 GLsizei n = static_cast<GLsizei>(c.n);
2567 uint32 data_size;
2568 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2569 return error::kOutOfBounds;
2570 }
2571 GLuint* ids = GetSharedMemoryAs<GLuint*>(
2572 c.ids_shm_id, c.ids_shm_offset, data_size);
2573 if (n < 0) {
2574 SetGLError(GL_INVALID_VALUE, "RegisterSharedIds: n < 0");
2575 return error::kNoError;
2576 }
2577 if (ids == NULL) {
2578 return error::kOutOfBounds;
2579 }
2580 DoRegisterSharedIds(namespace_id, n, ids);
2581 return error::kNoError;
2582}
2583
[email protected]07f54fcc2009-12-22 02:46:302584void GLES2DecoderImpl::DoDrawArrays(
2585 GLenum mode, GLint first, GLsizei count) {
2586 if (IsDrawValid(first + count - 1)) {
[email protected]3916c97e2010-02-25 03:20:502587 bool has_non_renderable_textures;
[email protected]b1122982010-05-17 23:04:242588 bool simulated_attrib_0 = SimulateAttrib0(first + count - 1);
[email protected]3916c97e2010-02-25 03:20:502589 SetBlackTextureForNonRenderableTextures(&has_non_renderable_textures);
[email protected]07f54fcc2009-12-22 02:46:302590 glDrawArrays(mode, first, count);
[email protected]3916c97e2010-02-25 03:20:502591 if (has_non_renderable_textures) {
2592 RestoreStateForNonRenderableTextures();
2593 }
[email protected]b1122982010-05-17 23:04:242594 if (simulated_attrib_0) {
2595 RestoreStateForSimulatedAttrib0();
2596 }
[email protected]07f54fcc2009-12-22 02:46:302597 }
2598}
2599
[email protected]36cef8ce2010-03-16 07:34:452600void GLES2DecoderImpl::DoFramebufferRenderbuffer(
2601 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:032602 GLuint client_renderbuffer_id) {
[email protected]051b1372010-04-12 02:42:082603 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292604 SetGLError(GL_INVALID_OPERATION,
2605 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452606 return;
2607 }
[email protected]ae51d192010-04-27 00:48:032608 GLuint service_id = 0;
2609 if (client_renderbuffer_id) {
2610 RenderbufferManager::RenderbufferInfo* info =
2611 GetRenderbufferInfo(client_renderbuffer_id);
2612 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292613 SetGLError(GL_INVALID_OPERATION,
2614 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:032615 return;
2616 }
2617 service_id = info->service_id();
2618 }
2619 glFramebufferRenderbufferEXT(
2620 target, attachment, renderbuffertarget, service_id);
[email protected]36cef8ce2010-03-16 07:34:452621}
2622
2623GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]051b1372010-04-12 02:42:082624 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452625 return GL_FRAMEBUFFER_COMPLETE;
2626 }
2627 return glCheckFramebufferStatusEXT(target);
2628}
2629
2630void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:032631 GLenum target, GLenum attachment, GLenum textarget,
2632 GLuint client_texture_id, GLint level) {
[email protected]051b1372010-04-12 02:42:082633 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292634 SetGLError(GL_INVALID_OPERATION,
2635 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:452636 return;
2637 }
[email protected]ae51d192010-04-27 00:48:032638 GLuint service_id = 0;
2639 if (client_texture_id) {
2640 TextureManager::TextureInfo* info = GetTextureInfo(client_texture_id);
2641 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292642 SetGLError(GL_INVALID_OPERATION,
2643 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:032644 return;
2645 }
2646 service_id = info->service_id();
2647 }
2648 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]36cef8ce2010-03-16 07:34:452649}
2650
2651void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
2652 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082653 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292654 SetGLError(GL_INVALID_OPERATION,
2655 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452656 return;
2657 }
2658 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
2659}
2660
2661void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
2662 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082663 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:292664 SetGLError(GL_INVALID_OPERATION,
2665 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452666 return;
2667 }
2668 glGetRenderbufferParameterivEXT(target, pname, params);
2669}
2670
2671void GLES2DecoderImpl::DoRenderbufferStorage(
2672 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:082673 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:292674 SetGLError(GL_INVALID_OPERATION,
2675 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452676 return;
2677 }
2678 glRenderbufferStorageEXT(target, internalformat, width, height);
2679}
2680
[email protected]07f54fcc2009-12-22 02:46:302681void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]6b8cf1a2010-05-06 16:13:582682 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2683 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:472684 if (!info) {
[email protected]a93bb842010-02-16 23:03:472685 return;
2686 }
[email protected]ae51d192010-04-27 00:48:032687 glLinkProgram(info->service_id());
[email protected]6b8cf1a2010-05-06 16:13:582688 GLint success = 0;
2689 glGetProgramiv(info->service_id(), GL_LINK_STATUS, &success);
2690 if (success) {
[email protected]a93bb842010-02-16 23:03:472691 info->Update();
[email protected]6b8cf1a2010-05-06 16:13:582692 } else {
2693 info->Reset();
[email protected]07f54fcc2009-12-22 02:46:302694 }
2695};
2696
[email protected]3916c97e2010-02-25 03:20:502697void GLES2DecoderImpl::DoTexParameterf(
2698 GLenum target, GLenum pname, GLfloat param) {
2699 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:302700 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292701 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]07f54fcc2009-12-22 02:46:302702 } else {
[email protected]3916c97e2010-02-25 03:20:502703 info->SetParameter(pname, static_cast<GLint>(param));
2704 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:302705 }
2706}
2707
[email protected]3916c97e2010-02-25 03:20:502708void GLES2DecoderImpl::DoTexParameteri(
2709 GLenum target, GLenum pname, GLint param) {
2710 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2711 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292712 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502713 } else {
2714 info->SetParameter(pname, param);
2715 glTexParameteri(target, pname, param);
2716 }
2717}
2718
2719void GLES2DecoderImpl::DoTexParameterfv(
2720 GLenum target, GLenum pname, const GLfloat* params) {
2721 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2722 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292723 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502724 } else {
2725 info->SetParameter(pname, *reinterpret_cast<const GLint*>(params));
2726 glTexParameterfv(target, pname, params);
2727 }
2728}
2729
2730void GLES2DecoderImpl::DoTexParameteriv(
2731 GLenum target, GLenum pname, const GLint* params) {
2732 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2733 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292734 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502735 } else {
2736 info->SetParameter(pname, *params);
2737 glTexParameteriv(target, pname, params);
2738 }
2739}
2740
[email protected]939e7362010-05-13 20:49:102741bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]3916c97e2010-02-25 03:20:502742 if (!current_program_ || current_program_->IsDeleted()) {
[email protected]939e7362010-05-13 20:49:102743 // The program does not exist.
2744 SetGLError(GL_INVALID_OPERATION,
2745 (std::string(function_name) + ": no program in use").c_str());
2746 return false;
2747 }
2748 if (!current_program_->IsValid()) {
2749 SetGLError(GL_INVALID_OPERATION,
2750 (std::string(function_name) + ": program not linked").c_str());
2751 return false;
2752 }
2753 return true;
2754}
2755
2756bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
2757 GLint location, const char* function_name) {
2758 if (!CheckCurrentProgram(function_name)) {
2759 return false;
2760 }
2761 return location != -1;
2762}
2763
2764bool GLES2DecoderImpl::GetUniformTypeByLocation(
2765 GLint location, const char* function_name, GLenum* type) {
2766 if (!CheckCurrentProgramForUniform(location, function_name)) {
2767 return false;
2768 }
2769 if (!current_program_->GetUniformTypeByLocation(location, type)) {
2770 SetGLError(GL_INVALID_OPERATION,
2771 (std::string(function_name) + ": program not linked").c_str());
2772 return false;
2773 }
2774 return true;
2775}
2776
2777
2778void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
2779 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:502780 return;
2781 }
2782 current_program_->SetSamplers(location, 1, &v0);
2783 glUniform1i(location, v0);
2784}
2785
2786void GLES2DecoderImpl::DoUniform1iv(
2787 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:102788 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:502789 return;
2790 }
2791 current_program_->SetSamplers(location, count, value);
2792 glUniform1iv(location, count, value);
2793}
2794
[email protected]939e7362010-05-13 20:49:102795void GLES2DecoderImpl::DoUniform1fv(
2796 GLint location, GLsizei count, const GLfloat* value) {
2797 GLenum type;
2798 if (!GetUniformTypeByLocation(location, "glUniform1fv", &type)) {
2799 return;
2800 }
2801 if (type == GL_BOOL) {
2802 scoped_array<GLint> temp(new GLint[count]);
2803 for (GLsizei ii = 0; ii < count; ++ii) {
2804 temp[ii] = static_cast<GLint>(value[ii]);
2805 }
2806 DoUniform1iv(location, count, temp.get());
2807 } else {
2808 glUniform1fv(location, count, value);
2809 }
2810}
2811
2812void GLES2DecoderImpl::DoUniform2fv(
2813 GLint location, GLsizei count, const GLfloat* value) {
2814 GLenum type;
2815 if (!GetUniformTypeByLocation(location, "glUniform2fv", &type)) {
2816 return;
2817 }
2818 if (type == GL_BOOL_VEC2) {
2819 GLsizei num_values = count * 2;
2820 scoped_array<GLint> temp(new GLint[num_values]);
2821 for (GLsizei ii = 0; ii < num_values; ++ii) {
2822 temp[ii] = static_cast<GLint>(value[ii]);
2823 }
2824 glUniform2iv(location, count, temp.get());
2825 } else {
2826 glUniform2fv(location, count, value);
2827 }
2828}
2829
2830void GLES2DecoderImpl::DoUniform3fv(
2831 GLint location, GLsizei count, const GLfloat* value) {
2832 GLenum type;
2833 if (!GetUniformTypeByLocation(location, "glUniform3fv", &type)) {
2834 return;
2835 }
2836 if (type == GL_BOOL_VEC3) {
2837 GLsizei num_values = count * 3;
2838 scoped_array<GLint> temp(new GLint[num_values]);
2839 for (GLsizei ii = 0; ii < num_values; ++ii) {
2840 temp[ii] = static_cast<GLint>(value[ii]);
2841 }
2842 glUniform3iv(location, count, temp.get());
2843 } else {
2844 glUniform3fv(location, count, value);
2845 }
2846}
2847
2848void GLES2DecoderImpl::DoUniform4fv(
2849 GLint location, GLsizei count, const GLfloat* value) {
2850 GLenum type;
2851 if (!GetUniformTypeByLocation(location, "glUniform4fv", &type)) {
2852 return;
2853 }
2854 if (type == GL_BOOL_VEC4) {
2855 GLsizei num_values = count * 4;
2856 scoped_array<GLint> temp(new GLint[num_values]);
2857 for (GLsizei ii = 0; ii < num_values; ++ii) {
2858 temp[ii] = static_cast<GLint>(value[ii]);
2859 }
2860 glUniform4iv(location, count, temp.get());
2861 } else {
2862 glUniform4fv(location, count, value);
2863 }
2864}
2865
[email protected]3916c97e2010-02-25 03:20:502866void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:032867 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:502868 ProgramManager::ProgramInfo* info = NULL;
2869 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:582870 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:502871 if (!info) {
[email protected]ae51d192010-04-27 00:48:032872 return;
2873 }
2874 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:502875 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:292876 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:502877 return;
2878 }
[email protected]ae51d192010-04-27 00:48:032879 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:502880 }
2881 current_program_ = info;
[email protected]ae51d192010-04-27 00:48:032882 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:502883}
2884
[email protected]96449d2c2009-11-25 00:01:322885GLenum GLES2DecoderImpl::GetGLError() {
2886 // Check the GL error first, then our wrapped error.
2887 GLenum error = glGetError();
2888 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:372889 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:322890 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:292891 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:322892 break;
2893 }
2894 }
2895 }
2896
2897 if (error != GL_NO_ERROR) {
2898 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:292899 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322900 }
2901 return error;
2902}
2903
[email protected]8eee29c2010-04-29 03:38:292904void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
2905 if (msg) {
2906 last_error_ = msg;
2907 DLOG(ERROR) << last_error_;
2908 }
[email protected]ddd968b82010-03-02 00:44:292909 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322910}
2911
[email protected]07f54fcc2009-12-22 02:46:302912void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
2913 GLenum error;
2914 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:292915 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:302916 }
2917}
2918
[email protected]6217d392010-03-25 22:08:352919void GLES2DecoderImpl::ClearRealGLErrors() {
2920 GLenum error;
2921 while ((error = glGetError()) != GL_NO_ERROR) {
2922 NOTREACHED() << "GL error " << error << " was unhandled.";
2923 }
2924}
2925
[email protected]3916c97e2010-02-25 03:20:502926void GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures(
2927 bool* has_non_renderable_textures) {
2928 DCHECK(has_non_renderable_textures);
2929 DCHECK(current_program_);
2930 DCHECK(!current_program_->IsDeleted());
2931 *has_non_renderable_textures = false;
2932 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
2933 current_program_->sampler_indices();
2934 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
2935 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2936 current_program_->GetUniformInfo(sampler_indices[ii]);
2937 DCHECK(uniform_info);
2938 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
2939 GLuint texture_unit_index = uniform_info->texture_units[jj];
2940 if (texture_unit_index < group_->max_texture_units()) {
2941 TextureUnit& texture_unit = texture_units_[texture_unit_index];
2942 TextureManager::TextureInfo* texture_info =
2943 uniform_info->type == GL_SAMPLER_2D ?
2944 texture_unit.bound_texture_2d :
2945 texture_unit.bound_texture_cube_map;
2946 if (!texture_info || !texture_info->CanRender()) {
2947 *has_non_renderable_textures = true;
2948 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
2949 glBindTexture(
2950 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
2951 GL_TEXTURE_CUBE_MAP,
2952 uniform_info->type == GL_SAMPLER_2D ? black_2d_texture_id_ :
2953 black_cube_texture_id_);
2954 }
2955 }
2956 // else: should this be an error?
2957 }
2958 }
2959}
2960
2961void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
2962 DCHECK(current_program_);
2963 DCHECK(!current_program_->IsDeleted());
2964 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
2965 current_program_->sampler_indices();
2966 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
2967 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2968 current_program_->GetUniformInfo(sampler_indices[ii]);
2969 DCHECK(uniform_info);
2970 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
2971 GLuint texture_unit_index = uniform_info->texture_units[jj];
2972 if (texture_unit_index < group_->max_texture_units()) {
2973 TextureUnit& texture_unit = texture_units_[texture_unit_index];
2974 TextureManager::TextureInfo* texture_info =
2975 uniform_info->type == GL_SAMPLER_2D ?
2976 texture_unit.bound_texture_2d :
2977 texture_unit.bound_texture_cube_map;
2978 if (!texture_info || !texture_info->CanRender()) {
2979 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
2980 // Get the texture info that was previously bound here.
2981 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
2982 texture_unit.bound_texture_2d :
2983 texture_unit.bound_texture_cube_map;
2984 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:032985 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:502986 }
2987 }
2988 }
2989 }
2990 // Set the active texture back to whatever the user had it as.
2991 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:302992}
2993
2994bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]939e7362010-05-13 20:49:102995 if (!current_program_ || current_program_->IsDeleted() ||
2996 !current_program_->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:502997 // The program does not exist.
2998 // But GL says no ERROR.
2999 return false;
3000 }
[email protected]f39f4b3f2010-05-12 17:04:083001 // Validate all attribs currently enabled. If they are used by the current
3002 // program then check that they have enough elements to handle the draw call.
3003 // If they are not used by the current program check that they have a buffer
3004 // assigned.
3005 const VertexAttribManager::VertexAttribInfoList& infos =
3006 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
3007 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
3008 infos.begin(); it != infos.end(); ++it) {
3009 const VertexAttribManager::VertexAttribInfo* info = *it;
3010 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
3011 current_program_->GetAttribInfoByLocation(info->index());
3012 if (attrib_info) {
3013 // This attrib is used in the current program.
3014 if (!info->CanAccess(max_vertex_accessed)) {
3015 SetGLError(GL_INVALID_OPERATION,
3016 "glDrawXXX: attempt to access out of range vertices");
3017 return false;
3018 }
3019 } else {
3020 // This attrib is not used in the current program.
3021 if (!info->buffer() || info->buffer()->IsDeleted()) {
3022 SetGLError(
3023 GL_INVALID_OPERATION,
3024 "glDrawXXX: attempt to render with no buffer attached to enabled "
3025 "attrib");
3026 return false;
3027 }
[email protected]1d32bc82010-01-13 22:06:463028 }
[email protected]07f54fcc2009-12-22 02:46:303029 }
[email protected]3916c97e2010-02-25 03:20:503030 return true;
[email protected]b1122982010-05-17 23:04:243031}
3032
3033bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
3034#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
3035 const VertexAttribManager::VertexAttribInfo* info =
3036 vertex_attrib_manager_.GetVertexAttribInfo(0);
3037 // If it's enabled or it's not used then we don't need to do anything.
3038 if (info->enabled() || !current_program_->GetAttribInfoByLocation(0)) {
3039 return false;
3040 }
3041
3042 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
3043
3044 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
3045
3046 // Make a buffer with a single repeated vec4 value enough to
3047 // simulate the constant value that is supposed to be here.
3048 // This is required to emulate GLES2 on GL.
3049 GLsizei num_vertices = max_vertex_accessed + 1;
3050 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
3051 if (size_needed > attrib_0_size_ ||
3052 info->value().v[0] != attrib_0_value_.v[0] ||
3053 info->value().v[1] != attrib_0_value_.v[1] ||
3054 info->value().v[2] != attrib_0_value_.v[2] ||
3055 info->value().v[3] != attrib_0_value_.v[3]) {
3056 scoped_array<Vec4> temp(new Vec4[num_vertices]);
3057 for (GLsizei ii = 0; ii < num_vertices; ++ii) {
3058 temp[ii] = info->value();
3059 }
3060 glBufferData(
3061 GL_ARRAY_BUFFER,
3062 size_needed,
3063 &temp[0].v[0],
3064 GL_DYNAMIC_DRAW);
3065 attrib_0_value_ = info->value();
3066 attrib_0_size_ = size_needed;
3067 }
3068
3069 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
3070
3071 return true;
3072#else // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
3073 return false;
3074#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
3075}
3076
3077void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
3078 const VertexAttribManager::VertexAttribInfo* info =
3079 vertex_attrib_manager_.GetVertexAttribInfo(0);
3080 const void* ptr = reinterpret_cast<const void*>(info->offset());
3081 BufferManager::BufferInfo* buffer_info = info->buffer();
3082 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
3083 glVertexAttribPointer(
3084 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
3085 ptr);
3086 glBindBuffer(GL_ARRAY_BUFFER,
3087 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
3088}
[email protected]07f54fcc2009-12-22 02:46:303089
[email protected]f7a64ee2010-02-01 22:24:143090error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:193091 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:503092 if (!bound_element_array_buffer_ ||
3093 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:293094 SetGLError(GL_INVALID_OPERATION,
3095 "glDrawElements: No element array buffer bound");
3096 return error::kNoError;
3097 }
3098
3099 GLenum mode = c.mode;
3100 GLsizei count = c.count;
3101 GLenum type = c.type;
3102 int32 offset = c.index_offset;
3103 if (count < 0) {
3104 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
3105 return error::kNoError;
3106 }
3107 if (offset < 0) {
3108 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
3109 return error::kNoError;
3110 }
3111 if (!ValidateGLenumDrawMode(mode)) {
3112 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
3113 return error::kNoError;
3114 }
3115 if (!ValidateGLenumIndexType(type)) {
3116 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
3117 return error::kNoError;
3118 }
3119
3120 GLuint max_vertex_accessed;
3121 if (!bound_element_array_buffer_->GetMaxValueForRange(
3122 offset, count, type, &max_vertex_accessed)) {
3123 SetGLError(GL_INVALID_OPERATION,
3124 "glDrawElements: range out of bounds for buffer");
3125 return error::kNoError;
3126 }
3127
3128 if (IsDrawValid(max_vertex_accessed)) {
3129 bool has_non_renderable_textures;
[email protected]b1122982010-05-17 23:04:243130 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]8eee29c2010-04-29 03:38:293131 SetBlackTextureForNonRenderableTextures(
3132 &has_non_renderable_textures);
3133 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
3134 glDrawElements(mode, count, type, indices);
3135 if (has_non_renderable_textures) {
3136 RestoreStateForNonRenderableTextures();
[email protected]ba3176a2009-12-16 18:19:463137 }
[email protected]b1122982010-05-17 23:04:243138 if (simulated_attrib_0) {
3139 RestoreStateForSimulatedAttrib0();
3140 }
[email protected]96449d2c2009-11-25 00:01:323141 }
[email protected]f7a64ee2010-02-01 22:24:143142 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323143}
3144
[email protected]29a9eb52010-04-13 09:04:233145GLuint GLES2DecoderImpl::DoGetMaxValueInBuffer(
3146 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
3147 GLuint max_vertex_accessed = 0;
3148 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:293149 if (!info) {
[email protected]ae51d192010-04-27 00:48:033150 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:293151 SetGLError(GL_INVALID_VALUE,
3152 "GetMaxValueInBuffer: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:233153 } else {
3154 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:033155 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:293156 SetGLError(GL_INVALID_OPERATION,
3157 "GetMaxValueInBuffer: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:233158 }
3159 }
3160 return max_vertex_accessed;
3161}
3162
[email protected]96449d2c2009-11-25 00:01:323163// Calls glShaderSource for the various versions of the ShaderSource command.
3164// Assumes that data / data_size points to a piece of memory that is in range
3165// of whatever context it came from (shared memory, immediate memory, bucket
3166// memory.)
[email protected]45bf5152010-02-12 00:11:313167error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:033168 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:583169 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3170 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:313171 if (!info) {
[email protected]45bf5152010-02-12 00:11:313172 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323173 }
[email protected]45bf5152010-02-12 00:11:313174 // Note: We don't actually call glShaderSource here. We wait until
3175 // the call to glCompileShader.
3176 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:143177 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323178}
3179
[email protected]f7a64ee2010-02-01 22:24:143180error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:193181 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:323182 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:313183 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:323184 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:463185 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143186 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:323187 }
[email protected]ae51d192010-04-27 00:48:033188 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:323189}
3190
[email protected]f7a64ee2010-02-01 22:24:143191error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:193192 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:323193 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:313194 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:303195 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:463196 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143197 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:323198 }
[email protected]ae51d192010-04-27 00:48:033199 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:313200}
3201
[email protected]558847a2010-03-24 07:02:543202error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
3203 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:543204 Bucket* bucket = GetBucket(c.data_bucket_id);
3205 if (!bucket || bucket->size() == 0) {
3206 return error::kInvalidArguments;
3207 }
3208 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:033209 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:543210 bucket->size() - 1);
3211}
3212
[email protected]ae51d192010-04-27 00:48:033213void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583214 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3215 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:313216 if (!info) {
[email protected]45bf5152010-02-12 00:11:313217 return;
3218 }
[email protected]de17df392010-04-23 21:09:413219 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
3220 // glShaderSource and then glCompileShader.
3221 const char* shader_src = info->source().c_str();
[email protected]bc10076c2010-05-14 19:14:063222#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) && !defined(UNIT_TEST)
[email protected]de17df392010-04-23 21:09:413223#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
[email protected]8f1ccdac2010-05-19 21:01:483224 ShHandle compiler = 0;
[email protected]b1d2dcb2010-05-17 19:24:183225 if (use_shader_translator_) {
3226 int dbg_options = 0;
3227 EShLanguage language = info->shader_type() == GL_VERTEX_SHADER ?
3228 EShLangVertex : EShLangFragment;
3229 TBuiltInResource resources;
[email protected]b1d2dcb2010-05-17 19:24:183230 resources.maxVertexAttribs = group_->max_vertex_attribs();
[email protected]8f1ccdac2010-05-19 21:01:483231 resources.maxVertexUniformVectors =
3232 group_->max_vertex_uniform_vectors();
3233 resources.maxVaryingVectors = group_->max_varying_vectors();
3234 resources.maxVertexTextureImageUnits =
3235 group_->max_vertex_texture_image_units();
[email protected]b1d2dcb2010-05-17 19:24:183236 resources.maxCombinedTextureImageUnits = group_->max_texture_units();
[email protected]8f1ccdac2010-05-19 21:01:483237 resources.maxTextureImageUnits = group_->max_texture_image_units();
3238 resources.maxFragmentUniformVectors =
3239 group_->max_fragment_uniform_vectors();
[email protected]b1d2dcb2010-05-17 19:24:183240 resources.maxDrawBuffers = 1;
3241 compiler = ShConstructCompiler(language, dbg_options);
3242 if (!ShCompile(compiler, &shader_src, 1, EShOptNone, &resources,
3243 dbg_options)) {
[email protected]8f1ccdac2010-05-19 21:01:483244 info->SetTranslationStatus(false, ShGetInfoLog(compiler));
[email protected]b1d2dcb2010-05-17 19:24:183245 ShDestruct(compiler);
3246 return;
3247 }
[email protected]8f1ccdac2010-05-19 21:01:483248 info->SetTranslationStatus(true, "");
[email protected]b1d2dcb2010-05-17 19:24:183249 shader_src = ShGetObjectCode(compiler);
[email protected]de17df392010-04-23 21:09:413250 }
[email protected]de17df392010-04-23 21:09:413251#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
3252#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
3253
[email protected]ae51d192010-04-27 00:48:033254 glShaderSource(info->service_id(), 1, &shader_src, NULL);
3255 glCompileShader(info->service_id());
[email protected]bc10076c2010-05-14 19:14:063256#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) && !defined(UNIT_TEST)
[email protected]de17df392010-04-23 21:09:413257#ifdef GLES2_GPU_SERVICE_TRANSLATE_SHADER
[email protected]b1d2dcb2010-05-17 19:24:183258 if (use_shader_translator_) {
3259 ShDestruct(compiler);
3260 }
[email protected]de17df392010-04-23 21:09:413261#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
3262#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
[email protected]45bf5152010-02-12 00:11:313263};
3264
[email protected]ddd968b82010-03-02 00:44:293265void GLES2DecoderImpl::DoGetShaderiv(
3266 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583267 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3268 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:293269 if (!info) {
[email protected]ddd968b82010-03-02 00:44:293270 return;
3271 }
[email protected]8f1ccdac2010-05-19 21:01:483272 switch (pname) {
3273 case GL_SHADER_SOURCE_LENGTH:
3274 *params = info->source().size();
3275 return;
3276 case GL_COMPILE_STATUS:
3277 if (!info->translation_valid()) {
3278 *params = GL_FALSE;
3279 return;
3280 }
3281 break;
3282 case GL_INFO_LOG_LENGTH:
3283 if (!info->translation_valid()) {
3284 *params = info->translation_log().size() + 1;
3285 return;
3286 }
3287 break;
3288 default:
3289 break;
[email protected]ddd968b82010-03-02 00:44:293290 }
[email protected]8f1ccdac2010-05-19 21:01:483291 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:293292}
3293
[email protected]ae51d192010-04-27 00:48:033294error::Error GLES2DecoderImpl::HandleGetShaderSource(
3295 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
3296 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:033297 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3298 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:583299 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3300 shader, "glGetShaderSource");
[email protected]8eee29c2010-04-29 03:38:293301 if (!info) {
3302 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:293303 return error::kNoError;
3304 }
[email protected]ae51d192010-04-27 00:48:033305 bucket->SetFromString(info->source());
3306 return error::kNoError;
3307}
3308
3309error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
3310 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
3311 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:583312 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3313 Bucket* bucket = CreateBucket(bucket_id);
3314 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3315 program, "glGetProgramInfoLog");
[email protected]ae51d192010-04-27 00:48:033316 if (!info) {
[email protected]ae51d192010-04-27 00:48:033317 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:313318 }
[email protected]ae51d192010-04-27 00:48:033319 GLint len = 0;
3320 glGetProgramiv(info->service_id(), GL_INFO_LOG_LENGTH, &len);
[email protected]8f1ccdac2010-05-19 21:01:483321 bucket->SetSize(len);
[email protected]ae51d192010-04-27 00:48:033322 glGetProgramInfoLog(
3323 info->service_id(),
[email protected]8f1ccdac2010-05-19 21:01:483324 len, &len, bucket->GetDataAs<GLchar*>(0, len));
[email protected]ae51d192010-04-27 00:48:033325 return error::kNoError;
3326}
3327
3328error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
3329 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
3330 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:583331 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3332 Bucket* bucket = CreateBucket(bucket_id);
3333 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3334 shader, "glGetShaderInfoLog");
[email protected]ae51d192010-04-27 00:48:033335 if (!info) {
[email protected]6b8cf1a2010-05-06 16:13:583336 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:033337 return error::kNoError;
3338 }
[email protected]8f1ccdac2010-05-19 21:01:483339 if (!info->translation_valid()) {
3340 bucket->SetFromString(info->translation_log());
3341 } else {
3342 GLint len = 0;
3343 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &len);
3344 bucket->SetSize(len);
3345 glGetShaderInfoLog(
3346 info->service_id(),
3347 len, &len, bucket->GetDataAs<GLchar*>(0, len));
3348 }
[email protected]ae51d192010-04-27 00:48:033349 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323350}
3351
[email protected]1958e0e2010-04-22 05:17:153352bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033353 return GetBufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153354}
3355
3356bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033357 return GetFramebufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153358}
3359
3360bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033361 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153362}
3363
3364bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033365 return GetRenderbufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153366}
3367
3368bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033369 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153370}
3371
3372bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033373 return GetTextureInfo(client_id) != NULL;
3374}
3375
3376void GLES2DecoderImpl::DoAttachShader(
3377 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583378 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
3379 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:033380 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:033381 return;
[email protected]1958e0e2010-04-22 05:17:153382 }
[email protected]6b8cf1a2010-05-06 16:13:583383 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
3384 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:033385 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:033386 return;
3387 }
3388 glAttachShader(program_info->service_id(), shader_info->service_id());
3389}
3390
3391void GLES2DecoderImpl::DoDetachShader(
3392 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583393 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
3394 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:033395 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:033396 return;
3397 }
[email protected]6b8cf1a2010-05-06 16:13:583398 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
3399 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:033400 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:033401 return;
3402 }
3403 glDetachShader(program_info->service_id(), shader_info->service_id());
3404}
3405
3406void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583407 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3408 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:033409 if (!info) {
[email protected]ae51d192010-04-27 00:48:033410 return;
3411 }
3412 glValidateProgram(info->service_id());
[email protected]1958e0e2010-04-22 05:17:153413}
3414
[email protected]b1122982010-05-17 23:04:243415void GLES2DecoderImpl::DoGetVertexAttribfv(
3416 GLuint index, GLenum pname, GLfloat* params) {
3417 VertexAttribManager::VertexAttribInfo* info =
3418 vertex_attrib_manager_.GetVertexAttribInfo(index);
3419 if (!info) {
3420 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
3421 return;
3422 }
3423 switch (pname) {
3424 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
3425 BufferManager::BufferInfo* buffer = info->buffer();
3426 if (buffer && !buffer->IsDeleted()) {
3427 GLuint client_id;
3428 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
3429 *params = static_cast<GLfloat>(client_id);
3430 }
3431 break;
3432 }
3433 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3434 *params = static_cast<GLfloat>(info->enabled());
3435 break;
3436 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3437 *params = static_cast<GLfloat>(info->size());
3438 break;
3439 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3440 *params = static_cast<GLfloat>(info->gl_stride());
3441 break;
3442 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3443 *params = static_cast<GLfloat>(info->type());
3444 break;
3445 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3446 *params = static_cast<GLfloat>(info->normalized());
3447 break;
3448 case GL_CURRENT_VERTEX_ATTRIB:
3449 params[0] = info->value().v[0];
3450 params[1] = info->value().v[1];
3451 params[2] = info->value().v[2];
3452 params[3] = info->value().v[3];
3453 break;
3454 default:
3455 NOTREACHED();
3456 break;
3457 }
3458}
3459
3460void GLES2DecoderImpl::DoGetVertexAttribiv(
3461 GLuint index, GLenum pname, GLint* params) {
3462 VertexAttribManager::VertexAttribInfo* info =
3463 vertex_attrib_manager_.GetVertexAttribInfo(index);
3464 if (!info) {
3465 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
3466 return;
3467 }
3468 switch (pname) {
3469 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
3470 BufferManager::BufferInfo* buffer = info->buffer();
3471 if (buffer && !buffer->IsDeleted()) {
3472 GLuint client_id;
3473 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
3474 *params = client_id;
3475 }
3476 break;
3477 }
3478 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3479 *params = info->enabled();
3480 break;
3481 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3482 *params = info->size();
3483 break;
3484 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3485 *params = info->gl_stride();
3486 break;
3487 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3488 *params = info->type();
3489 break;
3490 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3491 *params = static_cast<GLint>(info->normalized());
3492 break;
3493 case GL_CURRENT_VERTEX_ATTRIB:
3494 params[0] = static_cast<GLint>(info->value().v[0]);
3495 params[1] = static_cast<GLint>(info->value().v[1]);
3496 params[2] = static_cast<GLint>(info->value().v[2]);
3497 params[3] = static_cast<GLint>(info->value().v[3]);
3498 break;
3499 default:
3500 NOTREACHED();
3501 break;
3502 }
3503}
3504
3505void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
3506 VertexAttribManager::VertexAttribInfo* info =
3507 vertex_attrib_manager_.GetVertexAttribInfo(index);
3508 if (!info) {
3509 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
3510 return;
3511 }
3512 VertexAttribManager::VertexAttribInfo::Vec4 value;
3513 value.v[0] = v0;
3514 value.v[1] = 0.0f;
3515 value.v[2] = 0.0f;
3516 value.v[3] = 1.0f;
3517 info->set_value(value);
3518 glVertexAttrib1f(index, v0);
3519}
3520
3521void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
3522 VertexAttribManager::VertexAttribInfo* info =
3523 vertex_attrib_manager_.GetVertexAttribInfo(index);
3524 if (!info) {
3525 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
3526 return;
3527 }
3528 VertexAttribManager::VertexAttribInfo::Vec4 value;
3529 value.v[0] = v0;
3530 value.v[1] = v1;
3531 value.v[2] = 0.0f;
3532 value.v[3] = 1.0f;
3533 info->set_value(value);
3534 glVertexAttrib2f(index, v0, v1);
3535}
3536
3537void GLES2DecoderImpl::DoVertexAttrib3f(
3538 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
3539 VertexAttribManager::VertexAttribInfo* info =
3540 vertex_attrib_manager_.GetVertexAttribInfo(index);
3541 if (!info) {
3542 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
3543 return;
3544 }
3545 VertexAttribManager::VertexAttribInfo::Vec4 value;
3546 value.v[0] = v0;
3547 value.v[1] = v1;
3548 value.v[2] = v2;
3549 value.v[3] = 1.0f;
3550 info->set_value(value);
3551 glVertexAttrib3f(index, v0, v1, v2);
3552}
3553
3554void GLES2DecoderImpl::DoVertexAttrib4f(
3555 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
3556 VertexAttribManager::VertexAttribInfo* info =
3557 vertex_attrib_manager_.GetVertexAttribInfo(index);
3558 if (!info) {
3559 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
3560 return;
3561 }
3562 VertexAttribManager::VertexAttribInfo::Vec4 value;
3563 value.v[0] = v0;
3564 value.v[1] = v1;
3565 value.v[2] = v2;
3566 value.v[3] = v3;
3567 info->set_value(value);
3568 glVertexAttrib4f(index, v0, v1, v2, v3);
3569}
3570
3571void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
3572 VertexAttribManager::VertexAttribInfo* info =
3573 vertex_attrib_manager_.GetVertexAttribInfo(index);
3574 if (!info) {
3575 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
3576 return;
3577 }
3578 VertexAttribManager::VertexAttribInfo::Vec4 value;
3579 value.v[0] = v[0];
3580 value.v[1] = 0.0f;
3581 value.v[2] = 0.0f;
3582 value.v[3] = 1.0f;
3583 info->set_value(value);
3584 glVertexAttrib1fv(index, v);
3585}
3586
3587void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
3588 VertexAttribManager::VertexAttribInfo* info =
3589 vertex_attrib_manager_.GetVertexAttribInfo(index);
3590 if (!info) {
3591 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
3592 return;
3593 }
3594 VertexAttribManager::VertexAttribInfo::Vec4 value;
3595 value.v[0] = v[0];
3596 value.v[1] = v[1];
3597 value.v[2] = 0.0f;
3598 value.v[3] = 1.0f;
3599 info->set_value(value);
3600 glVertexAttrib2fv(index, v);
3601}
3602
3603void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
3604 VertexAttribManager::VertexAttribInfo* info =
3605 vertex_attrib_manager_.GetVertexAttribInfo(index);
3606 if (!info) {
3607 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
3608 return;
3609 }
3610 VertexAttribManager::VertexAttribInfo::Vec4 value;
3611 value.v[0] = v[0];
3612 value.v[1] = v[1];
3613 value.v[2] = v[2];
3614 value.v[3] = 1.0f;
3615 info->set_value(value);
3616 glVertexAttrib3fv(index, v);
3617}
3618
3619void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
3620 VertexAttribManager::VertexAttribInfo* info =
3621 vertex_attrib_manager_.GetVertexAttribInfo(index);
3622 if (!info) {
3623 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
3624 return;
3625 }
3626 VertexAttribManager::VertexAttribInfo::Vec4 value;
3627 value.v[0] = v[0];
3628 value.v[1] = v[1];
3629 value.v[2] = v[2];
3630 value.v[3] = v[3];
3631 info->set_value(value);
3632 glVertexAttrib4fv(index, v);
3633}
3634
[email protected]f7a64ee2010-02-01 22:24:143635error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:193636 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:293637 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
3638 SetGLError(GL_INVALID_VALUE,
3639 "glVertexAttribPointer: no array buffer bound");
3640 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323641 }
[email protected]8eee29c2010-04-29 03:38:293642
3643 GLuint indx = c.indx;
3644 GLint size = c.size;
3645 GLenum type = c.type;
3646 GLboolean normalized = c.normalized;
3647 GLsizei stride = c.stride;
3648 GLsizei offset = c.offset;
3649 const void* ptr = reinterpret_cast<const void*>(offset);
3650 if (!ValidateGLenumVertexAttribType(type)) {
3651 SetGLError(GL_INVALID_ENUM,
3652 "glVertexAttribPointer: type GL_INVALID_ENUM");
3653 return error::kNoError;
3654 }
3655 if (!ValidateGLintVertexAttribSize(size)) {
3656 SetGLError(GL_INVALID_ENUM,
3657 "glVertexAttribPointer: size GL_INVALID_VALUE");
3658 return error::kNoError;
3659 }
3660 if (indx >= group_->max_vertex_attribs()) {
3661 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
3662 return error::kNoError;
3663 }
3664 if (stride < 0) {
3665 SetGLError(GL_INVALID_VALUE,
3666 "glVertexAttribPointer: stride < 0");
3667 return error::kNoError;
3668 }
3669 if (stride > 255) {
3670 SetGLError(GL_INVALID_VALUE,
3671 "glVertexAttribPointer: stride > 255");
3672 return error::kNoError;
3673 }
3674 if (offset < 0) {
3675 SetGLError(GL_INVALID_VALUE,
3676 "glVertexAttribPointer: offset < 0");
3677 return error::kNoError;
3678 }
3679 GLsizei component_size =
3680 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:293681 if (offset % component_size > 0) {
3682 SetGLError(GL_INVALID_VALUE,
3683 "glVertexAttribPointer: stride not valid for type");
3684 return error::kNoError;
3685 }
[email protected]f39f4b3f2010-05-12 17:04:083686 vertex_attrib_manager_.GetVertexAttribInfo(indx)->SetInfo(
[email protected]8eee29c2010-04-29 03:38:293687 bound_array_buffer_,
3688 size,
3689 type,
[email protected]b1122982010-05-17 23:04:243690 normalized,
3691 stride,
3692 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:293693 offset);
3694 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
[email protected]f7a64ee2010-02-01 22:24:143695 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323696}
3697
[email protected]f7a64ee2010-02-01 22:24:143698error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:193699 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:313700 GLint x = c.x;
3701 GLint y = c.y;
3702 GLsizei width = c.width;
3703 GLsizei height = c.height;
3704 GLenum format = c.format;
3705 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:563706 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:293707 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:563708 return error::kNoError;
3709 }
[email protected]a51788e2010-02-24 21:54:253710 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:183711 uint32 pixels_size;
3712 if (!GLES2Util::ComputeImageDataSize(
3713 width, height, format, type, pack_alignment_, &pixels_size)) {
3714 return error::kOutOfBounds;
3715 }
[email protected]612d2f82009-12-08 20:49:313716 void* pixels = GetSharedMemoryAs<void*>(
3717 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:253718 Result* result = GetSharedMemoryAs<Result*>(
3719 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3720 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:143721 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:463722 }
[email protected]a51788e2010-02-24 21:54:253723
[email protected]8eee29c2010-04-29 03:38:293724 if (!ValidateGLenumReadPixelFormat(format)) {
3725 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
3726 return error::kNoError;
3727 }
3728 if (!ValidateGLenumPixelType(type)) {
3729 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:123730 return error::kNoError;
3731 }
[email protected]57f223832010-03-19 01:57:563732 if (width == 0 || height == 0) {
3733 return error::kNoError;
3734 }
3735
3736 CopyRealGLErrorsToWrapper();
3737
3738 // Get the size of the current fbo or backbuffer.
[email protected]d37231fa2010-04-09 21:16:023739 gfx::Size max_size = GetBoundFrameBufferSize();
[email protected]57f223832010-03-19 01:57:563740
3741 GLint max_x;
3742 GLint max_y;
3743 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:293744 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:143745 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:313746 }
[email protected]57f223832010-03-19 01:57:563747
[email protected]d37231fa2010-04-09 21:16:023748 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:563749 // The user requested an out of range area. Get the results 1 line
3750 // at a time.
3751 uint32 temp_size;
3752 if (!GLES2Util::ComputeImageDataSize(
3753 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:293754 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563755 return error::kNoError;
3756 }
3757 GLsizei unpadded_row_size = temp_size;
3758 if (!GLES2Util::ComputeImageDataSize(
3759 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:293760 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563761 return error::kNoError;
3762 }
3763 GLsizei padded_row_size = temp_size - unpadded_row_size;
3764 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:293765 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563766 return error::kNoError;
3767 }
3768
3769 GLint dest_x_offset = std::max(-x, 0);
3770 uint32 dest_row_offset;
3771 if (!GLES2Util::ComputeImageDataSize(
3772 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:293773 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563774 return error::kNoError;
3775 }
3776
3777 // Copy each row into the larger dest rect.
3778 int8* dst = static_cast<int8*>(pixels);
3779 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:023780 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:563781 GLint read_width = read_end_x - read_x;
3782 for (GLint yy = 0; yy < height; ++yy) {
3783 GLint ry = y + yy;
3784
3785 // Clear the row.
3786 memset(dst, 0, unpadded_row_size);
3787
3788 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:023789 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:563790 glReadPixels(
3791 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
3792 }
3793 dst += padded_row_size;
3794 }
3795 } else {
3796 glReadPixels(x, y, width, height, format, type, pixels);
3797 }
[email protected]a51788e2010-02-24 21:54:253798 GLenum error = glGetError();
3799 if (error == GL_NO_ERROR) {
3800 *result = true;
3801 } else {
[email protected]8eee29c2010-04-29 03:38:293802 SetGLError(error, NULL);
[email protected]a51788e2010-02-24 21:54:253803 }
[email protected]f7a64ee2010-02-01 22:24:143804 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323805}
3806
[email protected]f7a64ee2010-02-01 22:24:143807error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:193808 uint32 immediate_data_size, const gles2::PixelStorei& c) {
3809 GLenum pname = c.pname;
3810 GLenum param = c.param;
[email protected]d2cf0a2d2010-02-25 21:36:123811 if (!ValidateGLenumPixelStore(pname)) {
[email protected]8eee29c2010-04-29 03:38:293812 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:123813 return error::kNoError;
3814 }
3815 if (!ValidateGLintPixelStoreAlignment(param)) {
[email protected]8eee29c2010-04-29 03:38:293816 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:143817 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193818 }
3819 glPixelStorei(pname, param);
3820 switch (pname) {
3821 case GL_PACK_ALIGNMENT:
3822 pack_alignment_ = param;
3823 break;
3824 case GL_UNPACK_ALIGNMENT:
3825 unpack_alignment_ = param;
3826 break;
3827 default:
3828 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:373829 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:193830 break;
3831 }
[email protected]f7a64ee2010-02-01 22:24:143832 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193833}
3834
[email protected]558847a2010-03-24 07:02:543835error::Error GLES2DecoderImpl::GetAttribLocationHelper(
3836 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
3837 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:583838 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3839 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:033840 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:143841 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193842 }
[email protected]ae51d192010-04-27 00:48:033843 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:293844 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:253845 return error::kNoError;
3846 }
[email protected]b9849abf2009-11-25 19:13:193847 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:543848 location_shm_id, location_shm_offset, sizeof(GLint));
3849 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:143850 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193851 }
[email protected]558847a2010-03-24 07:02:543852 // Require the client to init this incase the context is lost and we are no
3853 // longer executing commands.
3854 if (*location != -1) {
3855 return error::kGenericError;
3856 }
[email protected]0bfd9882010-02-05 23:02:253857 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:143858 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193859}
3860
[email protected]558847a2010-03-24 07:02:543861error::Error GLES2DecoderImpl::HandleGetAttribLocation(
3862 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
3863 uint32 name_size = c.data_size;
3864 const char* name = GetSharedMemoryAs<const char*>(
3865 c.name_shm_id, c.name_shm_offset, name_size);
3866 if (!name) {
3867 return error::kOutOfBounds;
3868 }
3869 String name_str(name, name_size);
3870 return GetAttribLocationHelper(
3871 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3872}
3873
[email protected]f7a64ee2010-02-01 22:24:143874error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:193875 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:543876 uint32 name_size = c.data_size;
3877 const char* name = GetImmediateDataAs<const char*>(
3878 c, name_size, immediate_data_size);
3879 if (!name) {
3880 return error::kOutOfBounds;
3881 }
3882 String name_str(name, name_size);
3883 return GetAttribLocationHelper(
3884 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3885}
3886
3887error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
3888 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
3889 Bucket* bucket = GetBucket(c.name_bucket_id);
3890 if (!bucket) {
3891 return error::kInvalidArguments;
3892 }
3893 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183894 if (!bucket->GetAsString(&name_str)) {
3895 return error::kInvalidArguments;
3896 }
[email protected]558847a2010-03-24 07:02:543897 return GetAttribLocationHelper(
3898 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3899}
3900
3901error::Error GLES2DecoderImpl::GetUniformLocationHelper(
3902 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
3903 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:583904 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3905 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:033906 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:143907 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193908 }
[email protected]ae51d192010-04-27 00:48:033909 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:293910 SetGLError(GL_INVALID_OPERATION,
3911 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:253912 return error::kNoError;
3913 }
[email protected]b9849abf2009-11-25 19:13:193914 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:543915 location_shm_id, location_shm_offset, sizeof(GLint));
3916 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:143917 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193918 }
[email protected]558847a2010-03-24 07:02:543919 // Require the client to init this incase the context is lost an we are no
3920 // longer executing commands.
3921 if (*location != -1) {
3922 return error::kGenericError;
3923 }
3924 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:143925 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193926}
3927
[email protected]f7a64ee2010-02-01 22:24:143928error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:193929 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:193930 uint32 name_size = c.data_size;
3931 const char* name = GetSharedMemoryAs<const char*>(
3932 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:543933 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:143934 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193935 }
3936 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:543937 return GetUniformLocationHelper(
3938 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:193939}
3940
[email protected]f7a64ee2010-02-01 22:24:143941error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:193942 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:193943 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:303944 const char* name = GetImmediateDataAs<const char*>(
3945 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:543946 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:143947 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193948 }
3949 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:543950 return GetUniformLocationHelper(
3951 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3952}
3953
3954error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
3955 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
3956 Bucket* bucket = GetBucket(c.name_bucket_id);
3957 if (!bucket) {
3958 return error::kInvalidArguments;
3959 }
3960 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183961 if (!bucket->GetAsString(&name_str)) {
3962 return error::kInvalidArguments;
3963 }
[email protected]558847a2010-03-24 07:02:543964 return GetUniformLocationHelper(
3965 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:193966}
3967
[email protected]ddd968b82010-03-02 00:44:293968error::Error GLES2DecoderImpl::HandleGetString(
3969 uint32 immediate_data_size, const gles2::GetString& c) {
3970 GLenum name = static_cast<GLenum>(c.name);
3971 if (!ValidateGLenumStringType(name)) {
[email protected]8eee29c2010-04-29 03:38:293972 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:293973 return error::kNoError;
3974 }
[email protected]1958e0e2010-04-22 05:17:153975 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
3976 const char* str = NULL;
3977 switch (name) {
3978 case GL_VERSION:
3979 str = "OpenGL ES 2.0 Chromium";
3980 break;
3981 case GL_SHADING_LANGUAGE_VERSION:
3982 str = "OpenGL ES GLSL ES 1.0 Chromium";
3983 break;
3984 case GL_EXTENSIONS:
3985 str = "";
3986 break;
3987 default:
3988 str = gl_str;
3989 break;
3990 }
[email protected]ddd968b82010-03-02 00:44:293991 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:153992 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:293993 return error::kNoError;
3994}
3995
[email protected]0c86dbf2010-03-05 08:14:113996void GLES2DecoderImpl::DoBufferData(
3997 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]8eee29c2010-04-29 03:38:293998 if (!ValidateGLenumBufferTarget(target)) {
3999 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
4000 return;
4001 }
4002 if (!ValidateGLenumBufferUsage(usage)) {
4003 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:114004 return;
[email protected]3b6ec202010-03-05 05:16:234005 }
4006 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:294007 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:284008 return;
[email protected]3b6ec202010-03-05 05:16:234009 }
4010 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
4011 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294012 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:284013 return;
[email protected]3b6ec202010-03-05 05:16:234014 }
4015 // Clear the buffer to 0 if no initial data was passed in.
4016 scoped_array<int8> zero;
4017 if (!data) {
4018 zero.reset(new int8[size]);
4019 memset(zero.get(), 0, size);
4020 data = zero.get();
4021 }
4022 CopyRealGLErrorsToWrapper();
4023 glBufferData(target, size, data, usage);
4024 GLenum error = glGetError();
4025 if (error != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294026 SetGLError(error, NULL);
[email protected]3b6ec202010-03-05 05:16:234027 } else {
[email protected]4e8a5b122010-05-08 22:00:104028 buffer_manager()->SetSize(info, size);
[email protected]0c86dbf2010-03-05 08:14:114029 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:234030 }
[email protected]0c86dbf2010-03-05 08:14:114031}
4032
4033error::Error GLES2DecoderImpl::HandleBufferData(
4034 uint32 immediate_data_size, const gles2::BufferData& c) {
4035 GLenum target = static_cast<GLenum>(c.target);
4036 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
4037 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
4038 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
4039 GLenum usage = static_cast<GLenum>(c.usage);
4040 const void* data = NULL;
4041 if (data_shm_id != 0 || data_shm_offset != 0) {
4042 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
4043 if (!data) {
4044 return error::kOutOfBounds;
4045 }
4046 }
4047 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:144048 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194049}
4050
[email protected]f7a64ee2010-02-01 22:24:144051error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:194052 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
4053 GLenum target = static_cast<GLenum>(c.target);
4054 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:304055 const void* data = GetImmediateDataAs<const void*>(
4056 c, size, immediate_data_size);
4057 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144058 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:304059 }
[email protected]b9849abf2009-11-25 19:13:194060 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:114061 DoBufferData(target, size, data, usage);
4062 return error::kNoError;
4063}
4064
4065void GLES2DecoderImpl::DoBufferSubData(
4066 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:504067 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474068 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294069 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:284070 return;
[email protected]a93bb842010-02-16 23:03:474071 }
[email protected]0c86dbf2010-03-05 08:14:114072 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:294073 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]07f54fcc2009-12-22 02:46:304074 } else {
[email protected]0c86dbf2010-03-05 08:14:114075 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:304076 }
[email protected]b9849abf2009-11-25 19:13:194077}
4078
[email protected]a93bb842010-02-16 23:03:474079error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
4080 GLenum target,
4081 GLint level,
4082 GLenum internal_format,
4083 GLsizei width,
4084 GLsizei height,
4085 GLint border,
4086 GLsizei image_size,
4087 const void* data) {
[email protected]a93bb842010-02-16 23:03:474088 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]8eee29c2010-04-29 03:38:294089 if (!ValidateGLenumTextureTarget(target)) {
4090 SetGLError(GL_INVALID_ENUM,
4091 "glCompressedTexImage2D: target GL_INVALID_ENUM");
4092 return error::kNoError;
4093 }
4094 if (!ValidateGLenumCompressedTextureInternalFormat(internal_format)) {
4095 SetGLError(GL_INVALID_ENUM,
4096 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:474097 return error::kNoError;
4098 }
[email protected]3916c97e2010-02-25 03:20:504099 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:474100 border != 0) {
[email protected]8eee29c2010-04-29 03:38:294101 SetGLError(GL_INVALID_VALUE,
4102 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:474103 return error::kNoError;
4104 }
[email protected]3916c97e2010-02-25 03:20:504105 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474106 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294107 SetGLError(GL_INVALID_VALUE,
4108 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:474109 return error::kNoError;
4110 }
4111 scoped_array<int8> zero;
4112 if (!data) {
4113 zero.reset(new int8[image_size]);
4114 memset(zero.get(), 0, image_size);
4115 data = zero.get();
4116 }
4117 info->SetLevelInfo(
4118 target, level, internal_format, width, height, 1, border, 0, 0);
4119 glCompressedTexImage2D(
4120 target, level, internal_format, width, height, border, image_size, data);
4121 return error::kNoError;
4122}
4123
[email protected]f7a64ee2010-02-01 22:24:144124error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194125 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
4126 GLenum target = static_cast<GLenum>(c.target);
4127 GLint level = static_cast<GLint>(c.level);
4128 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4129 GLsizei width = static_cast<GLsizei>(c.width);
4130 GLsizei height = static_cast<GLsizei>(c.height);
4131 GLint border = static_cast<GLint>(c.border);
4132 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
4133 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
4134 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
4135 const void* data = NULL;
4136 if (data_shm_id != 0 || data_shm_offset != 0) {
4137 data = GetSharedMemoryAs<const void*>(
4138 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:464139 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144140 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194141 }
4142 }
[email protected]a93bb842010-02-16 23:03:474143 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194144 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:194145}
4146
[email protected]f7a64ee2010-02-01 22:24:144147error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:194148 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
4149 GLenum target = static_cast<GLenum>(c.target);
4150 GLint level = static_cast<GLint>(c.level);
4151 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4152 GLsizei width = static_cast<GLsizei>(c.width);
4153 GLsizei height = static_cast<GLsizei>(c.height);
4154 GLint border = static_cast<GLint>(c.border);
4155 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:304156 const void* data = GetImmediateDataAs<const void*>(
4157 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464158 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144159 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464160 }
[email protected]a93bb842010-02-16 23:03:474161 return DoCompressedTexImage2D(
4162 target, level, internal_format, width, height, border, image_size, data);
4163}
4164
[email protected]b6140d02010-05-17 14:47:164165error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
4166 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
4167 GLenum target = static_cast<GLenum>(c.target);
4168 GLint level = static_cast<GLint>(c.level);
4169 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4170 GLsizei width = static_cast<GLsizei>(c.width);
4171 GLsizei height = static_cast<GLsizei>(c.height);
4172 GLint border = static_cast<GLint>(c.border);
4173 Bucket* bucket = GetBucket(c.bucket_id);
4174 return DoCompressedTexImage2D(
4175 target, level, internal_format, width, height, border,
4176 bucket->size(), bucket->GetData(0, bucket->size()));
4177}
4178
4179error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
4180 uint32 immediate_data_size,
4181 const gles2::CompressedTexSubImage2DBucket& c) {
4182 GLenum target = static_cast<GLenum>(c.target);
4183 GLint level = static_cast<GLint>(c.level);
4184 GLint xoffset = static_cast<GLint>(c.xoffset);
4185 GLint yoffset = static_cast<GLint>(c.yoffset);
4186 GLsizei width = static_cast<GLsizei>(c.width);
4187 GLsizei height = static_cast<GLsizei>(c.height);
4188 GLenum format = static_cast<GLenum>(c.format);
4189 Bucket* bucket = GetBucket(c.bucket_id);
4190 uint32 data_size = bucket->size();
4191 GLsizei imageSize = data_size;
4192 const void* data = bucket->GetData(0, data_size);
4193 if (!ValidateGLenumTextureTarget(target)) {
4194 SetGLError(
4195 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
4196 return error::kNoError;
4197 }
4198 if (width < 0) {
4199 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
4200 return error::kNoError;
4201 }
4202 if (height < 0) {
4203 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
4204 return error::kNoError;
4205 }
4206 if (imageSize < 0) {
4207 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
4208 return error::kNoError;
4209 }
4210 glCompressedTexSubImage2D(
4211 target, level, xoffset, yoffset, width, height, format, imageSize, data);
4212 return error::kNoError;
4213}
4214
[email protected]a93bb842010-02-16 23:03:474215error::Error GLES2DecoderImpl::DoTexImage2D(
4216 GLenum target,
4217 GLint level,
4218 GLenum internal_format,
4219 GLsizei width,
4220 GLsizei height,
4221 GLint border,
4222 GLenum format,
4223 GLenum type,
4224 const void* pixels,
4225 uint32 pixels_size) {
[email protected]8eee29c2010-04-29 03:38:294226 if (!ValidateGLenumTextureTarget(target)) {
4227 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
4228 return error::kNoError;
4229 }
4230 if (!ValidateGLenumTextureFormat(internal_format)) {
4231 SetGLError(GL_INVALID_ENUM,
4232 "glTexImage2D: internal_format GL_INVALID_ENUM");
4233 return error::kNoError;
4234 }
4235 if (!ValidateGLenumTextureFormat(format)) {
4236 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
4237 return error::kNoError;
4238 }
4239 if (!ValidateGLenumPixelType(type)) {
4240 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:144241 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194242 }
[email protected]3916c97e2010-02-25 03:20:504243 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:474244 border != 0) {
[email protected]8eee29c2010-04-29 03:38:294245 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:474246 return error::kNoError;
4247 }
[email protected]3916c97e2010-02-25 03:20:504248 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474249 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294250 SetGLError(GL_INVALID_OPERATION,
4251 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:474252 return error::kNoError;
4253 }
4254 scoped_array<int8> zero;
4255 if (!pixels) {
4256 zero.reset(new int8[pixels_size]);
4257 memset(zero.get(), 0, pixels_size);
4258 pixels = zero.get();
4259 }
4260 info->SetLevelInfo(
4261 target, level, internal_format, width, height, 1, border, format, type);
4262 glTexImage2D(
4263 target, level, internal_format, width, height, border, format, type,
4264 pixels);
[email protected]f7a64ee2010-02-01 22:24:144265 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194266}
4267
[email protected]f7a64ee2010-02-01 22:24:144268error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194269 uint32 immediate_data_size, const gles2::TexImage2D& c) {
4270 GLenum target = static_cast<GLenum>(c.target);
4271 GLint level = static_cast<GLint>(c.level);
4272 GLint internal_format = static_cast<GLint>(c.internalformat);
4273 GLsizei width = static_cast<GLsizei>(c.width);
4274 GLsizei height = static_cast<GLsizei>(c.height);
4275 GLint border = static_cast<GLint>(c.border);
4276 GLenum format = static_cast<GLenum>(c.format);
4277 GLenum type = static_cast<GLenum>(c.type);
4278 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
4279 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:184280 uint32 pixels_size;
4281 if (!GLES2Util::ComputeImageDataSize(
4282 width, height, format, type, unpack_alignment_, &pixels_size)) {
4283 return error::kOutOfBounds;
4284 }
[email protected]b9849abf2009-11-25 19:13:194285 const void* pixels = NULL;
4286 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
4287 pixels = GetSharedMemoryAs<const void*>(
4288 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:464289 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:144290 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194291 }
4292 }
[email protected]a93bb842010-02-16 23:03:474293 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194294 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:474295 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:194296}
4297
[email protected]f7a64ee2010-02-01 22:24:144298error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:194299 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
4300 GLenum target = static_cast<GLenum>(c.target);
4301 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:464302 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:194303 GLsizei width = static_cast<GLsizei>(c.width);
4304 GLsizei height = static_cast<GLsizei>(c.height);
4305 GLint border = static_cast<GLint>(c.border);
4306 GLenum format = static_cast<GLenum>(c.format);
4307 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:184308 uint32 size;
4309 if (!GLES2Util::ComputeImageDataSize(
4310 width, height, format, type, unpack_alignment_, &size)) {
4311 return error::kOutOfBounds;
4312 }
[email protected]07f54fcc2009-12-22 02:46:304313 const void* pixels = GetImmediateDataAs<const void*>(
4314 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464315 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:144316 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464317 }
[email protected]a93bb842010-02-16 23:03:474318 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:464319 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:474320 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:144321 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324322}
4323
[email protected]f7a64ee2010-02-01 22:24:144324error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:194325 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:364326 GLuint index = static_cast<GLuint>(c.index);
4327 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:254328 typedef gles2::GetVertexAttribPointerv::Result Result;
4329 Result* result = GetSharedMemoryAs<Result*>(
4330 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:364331 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:144332 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:364333 }
[email protected]07d0cc82010-02-17 04:51:404334 // Check that the client initialized the result.
4335 if (result->size != 0) {
4336 return error::kInvalidArguments;
4337 }
[email protected]8bf5a3e2010-01-29 04:21:364338 if (!ValidateGLenumVertexPointer(pname)) {
[email protected]8eee29c2010-04-29 03:38:294339 SetGLError(GL_INVALID_ENUM,
4340 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:144341 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:364342 }
[email protected]3916c97e2010-02-25 03:20:504343 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:294344 SetGLError(GL_INVALID_VALUE,
4345 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:144346 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:364347 }
[email protected]0bfd9882010-02-05 23:02:254348 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:084349 *result->GetData() =
4350 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:144351 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324352}
4353
[email protected]f7b85372010-02-03 01:11:374354bool GLES2DecoderImpl::GetUniformSetup(
4355 GLuint program, GLint location,
4356 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:104357 error::Error* error, GLuint* service_id, void** result_pointer,
4358 GLenum* result_type) {
4359 DCHECK(error);
4360 DCHECK(service_id);
4361 DCHECK(result_pointer);
4362 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:374363 *error = error::kNoError;
4364 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:254365 SizedResult<GLint>* result;
4366 result = GetSharedMemoryAs<SizedResult<GLint>*>(
4367 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
4368 if (!result) {
[email protected]f7b85372010-02-03 01:11:374369 *error = error::kOutOfBounds;
4370 return false;
4371 }
[email protected]0bfd9882010-02-05 23:02:254372 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:374373 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:254374 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:584375 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4376 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:374377 if (!info) {
[email protected]ae51d192010-04-27 00:48:034378 return false;
4379 }
4380 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:374381 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294382 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:374383 return false;
4384 }
[email protected]ae51d192010-04-27 00:48:034385 *service_id = info->service_id();
[email protected]0bfd9882010-02-05 23:02:254386 GLenum type;
4387 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:374388 // No such location.
[email protected]8eee29c2010-04-29 03:38:294389 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:374390 return false;
4391 }
[email protected]3916c97e2010-02-25 03:20:504392 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:374393 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:294394 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:374395 return false;
4396 }
[email protected]0bfd9882010-02-05 23:02:254397 result = GetSharedMemoryAs<SizedResult<GLint>*>(
4398 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
4399 if (!result) {
[email protected]f7b85372010-02-03 01:11:374400 *error = error::kOutOfBounds;
4401 return false;
4402 }
[email protected]0bfd9882010-02-05 23:02:254403 result->size = size;
[email protected]939e7362010-05-13 20:49:104404 *result_type = type;
[email protected]f7b85372010-02-03 01:11:374405 return true;
4406}
4407
[email protected]f7a64ee2010-02-01 22:24:144408error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:194409 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:374410 GLuint program = c.program;
4411 GLint location = c.location;
4412 GLuint service_id;
[email protected]939e7362010-05-13 20:49:104413 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:374414 Error error;
[email protected]0bfd9882010-02-05 23:02:254415 void* result;
[email protected]f7b85372010-02-03 01:11:374416 if (GetUniformSetup(
4417 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:104418 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:254419 glGetUniformiv(
4420 service_id, location,
4421 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:374422 }
4423 return error;
[email protected]96449d2c2009-11-25 00:01:324424}
4425
[email protected]f7a64ee2010-02-01 22:24:144426error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:194427 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:374428 GLuint program = c.program;
4429 GLint location = c.location;
4430 GLuint service_id;
4431 Error error;
[email protected]0bfd9882010-02-05 23:02:254432 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:104433 Result* result;
4434 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:374435 if (GetUniformSetup(
4436 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:104437 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
4438 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
4439 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
4440 GLsizei num_values = result->GetNumResults();
4441 scoped_array<GLint> temp(new GLint[num_values]);
4442 glGetUniformiv(service_id, location, temp.get());
4443 GLfloat* dst = result->GetData();
4444 for (GLsizei ii = 0; ii < num_values; ++ii) {
4445 dst[ii] = (temp[ii] != 0);
4446 }
4447 } else {
4448 glGetUniformfv(service_id, location, result->GetData());
4449 }
[email protected]f7b85372010-02-03 01:11:374450 }
4451 return error;
[email protected]96449d2c2009-11-25 00:01:324452}
4453
[email protected]f7a64ee2010-02-01 22:24:144454error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:194455 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:254456 GLenum shader_type = static_cast<GLenum>(c.shadertype);
4457 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
4458 typedef gles2::GetShaderPrecisionFormat::Result Result;
4459 Result* result = GetSharedMemoryAs<Result*>(
4460 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4461 if (!result) {
4462 return error::kOutOfBounds;
4463 }
[email protected]07d0cc82010-02-17 04:51:404464 // Check that the client initialized the result.
4465 if (result->success != 0) {
4466 return error::kInvalidArguments;
4467 }
[email protected]8eee29c2010-04-29 03:38:294468 if (!ValidateGLenumShaderType(shader_type)) {
4469 SetGLError(GL_INVALID_ENUM,
4470 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
4471 return error::kNoError;
4472 }
4473 if (!ValidateGLenumShaderPrecision(precision_type)) {
4474 SetGLError(GL_INVALID_ENUM,
4475 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
4476 return error::kNoError;
4477 }
4478
4479 result->success = 1; // true
4480 switch (precision_type) {
4481 case GL_LOW_INT:
4482 case GL_MEDIUM_INT:
4483 case GL_HIGH_INT:
4484 result->min_range = -31;
4485 result->max_range = 31;
4486 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:104487 break;
[email protected]8eee29c2010-04-29 03:38:294488 case GL_LOW_FLOAT:
4489 case GL_MEDIUM_FLOAT:
4490 case GL_HIGH_FLOAT:
4491 result->min_range = -62;
4492 result->max_range = 62;
4493 result->precision = -16;
4494 break;
4495 default:
4496 NOTREACHED();
4497 break;
[email protected]0bfd9882010-02-05 23:02:254498 }
[email protected]f7a64ee2010-02-01 22:24:144499 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324500}
4501
[email protected]f7a64ee2010-02-01 22:24:144502error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:194503 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:254504 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:584505 GLuint program = static_cast<GLuint>(c.program);
4506 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4507 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:034508 if (!info) {
[email protected]0bfd9882010-02-05 23:02:254509 return error::kNoError;
4510 }
4511 typedef gles2::GetAttachedShaders::Result Result;
4512 uint32 max_count = Result::ComputeMaxResults(result_size);
4513 Result* result = GetSharedMemoryAs<Result*>(
4514 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
4515 if (!result) {
4516 return error::kOutOfBounds;
4517 }
[email protected]07d0cc82010-02-17 04:51:404518 // Check that the client initialized the result.
4519 if (result->size != 0) {
4520 return error::kInvalidArguments;
4521 }
[email protected]0bfd9882010-02-05 23:02:254522 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:034523 glGetAttachedShaders(
4524 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:254525 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:034526 if (!shader_manager()->GetClientId(result->GetData()[ii],
4527 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:254528 NOTREACHED();
4529 return error::kGenericError;
4530 }
4531 }
4532 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:144533 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324534}
4535
[email protected]f7a64ee2010-02-01 22:24:144536error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:194537 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:254538 GLuint program = c.program;
4539 GLuint index = c.index;
4540 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:254541 typedef gles2::GetActiveUniform::Result Result;
4542 Result* result = GetSharedMemoryAs<Result*>(
4543 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4544 if (!result) {
4545 return error::kOutOfBounds;
4546 }
[email protected]07d0cc82010-02-17 04:51:404547 // Check that the client initialized the result.
4548 if (result->success != 0) {
4549 return error::kInvalidArguments;
4550 }
[email protected]6b8cf1a2010-05-06 16:13:584551 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4552 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:034553 if (!info) {
[email protected]0bfd9882010-02-05 23:02:254554 return error::kNoError;
4555 }
4556 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4557 info->GetUniformInfo(index);
4558 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:294559 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:254560 return error::kNoError;
4561 }
4562 result->success = 1; // true.
4563 result->size = uniform_info->size;
4564 result->type = uniform_info->type;
4565 Bucket* bucket = CreateBucket(name_bucket_id);
4566 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:144567 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324568}
4569
[email protected]f7a64ee2010-02-01 22:24:144570error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:194571 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:254572 GLuint program = c.program;
4573 GLuint index = c.index;
4574 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:254575 typedef gles2::GetActiveAttrib::Result Result;
4576 Result* result = GetSharedMemoryAs<Result*>(
4577 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4578 if (!result) {
4579 return error::kOutOfBounds;
4580 }
[email protected]07d0cc82010-02-17 04:51:404581 // Check that the client initialized the result.
4582 if (result->success != 0) {
4583 return error::kInvalidArguments;
4584 }
[email protected]6b8cf1a2010-05-06 16:13:584585 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4586 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:034587 if (!info) {
[email protected]0bfd9882010-02-05 23:02:254588 return error::kNoError;
4589 }
4590 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4591 info->GetAttribInfo(index);
4592 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:294593 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:254594 return error::kNoError;
4595 }
4596 result->success = 1; // true.
4597 result->size = attrib_info->size;
4598 result->type = attrib_info->type;
4599 Bucket* bucket = CreateBucket(name_bucket_id);
4600 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:144601 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324602}
4603
[email protected]b273e432010-04-12 17:23:584604error::Error GLES2DecoderImpl::HandleShaderBinary(
4605 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
4606#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:294607 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:584608 return error::kNoError;
4609#else
4610 GLsizei n = static_cast<GLsizei>(c.n);
4611 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:294612 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:584613 return error::kNoError;
4614 }
4615 GLsizei length = static_cast<GLsizei>(c.length);
4616 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:294617 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:584618 return error::kNoError;
4619 }
4620 uint32 data_size;
4621 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4622 return error::kOutOfBounds;
4623 }
4624 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
4625 c.shaders_shm_id, c.shaders_shm_offset, data_size);
4626 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
4627 const void* binary = GetSharedMemoryAs<const void*>(
4628 c.binary_shm_id, c.binary_shm_offset, length);
4629 if (shaders == NULL || binary == NULL) {
4630 return error::kOutOfBounds;
4631 }
4632 scoped_array<GLuint> service_ids(new GLuint[n]);
4633 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:034634 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
4635 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294636 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:584637 return error::kNoError;
4638 }
[email protected]ae51d192010-04-27 00:48:034639 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:584640 }
4641 // TODO(gman): call glShaderBinary
4642 return error::kNoError;
4643#endif
4644}
4645
[email protected]6217d392010-03-25 22:08:354646error::Error GLES2DecoderImpl::HandleSwapBuffers(
4647 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]6217d392010-03-25 22:08:354648 // If offscreen then don't actually SwapBuffers to the display. Just copy
4649 // the rendered frame to another frame buffer.
4650 if (offscreen_target_frame_buffer_.get()) {
4651 ScopedGLErrorSuppressor suppressor(this);
4652
4653 // First check to see if a deferred offscreen render buffer resize is
4654 // pending.
4655 if (!UpdateOffscreenFrameBufferSize())
4656 return error::kLostContext;
4657
4658 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]d37231fa2010-04-09 21:16:024659 offscreen_saved_color_texture_->Copy(
4660 offscreen_saved_color_texture_->size());
[email protected]6217d392010-03-25 22:08:354661 } else {
[email protected]d37231fa2010-04-09 21:16:024662#if !defined(UNIT_TEST)
4663 context_->SwapBuffers();
[email protected]6217d392010-03-25 22:08:354664#endif
4665 }
4666
[email protected]7d9ce4f2010-04-14 18:39:404667 // TODO(kbr): when the back buffer is multisampled, then at least on Mac
4668 // OS X (and probably on all platforms, for best semantics), we will need
4669 // to perform the resolve step and bind the offscreen_saved_color_texture_
4670 // as the color attachment before calling the swap buffers callback, which
4671 // expects a normal (non-multisampled) frame buffer for glCopyTexImage2D /
4672 // glReadPixels. After the callback runs, the multisampled frame buffer
4673 // needs to be bound again.
4674
[email protected]6217d392010-03-25 22:08:354675 if (swap_buffers_callback_.get()) {
4676 swap_buffers_callback_->Run();
4677 }
4678
4679 return error::kNoError;
4680}
4681
[email protected]b1d2dcb2010-05-17 19:24:184682error::Error GLES2DecoderImpl::HandleCommandBufferEnable(
4683 uint32 immediate_data_size, const gles2::CommandBufferEnable& c) {
4684 Bucket* bucket = GetBucket(c.bucket_id);
4685 typedef gles2::CommandBufferEnable::Result Result;
4686 Result* result = GetSharedMemoryAs<Result*>(
4687 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4688 if (!result) {
4689 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:104690 }
[email protected]b1d2dcb2010-05-17 19:24:184691 // Check that the client initialized the result.
4692 if (*result != 0) {
4693 return error::kInvalidArguments;
4694 }
4695 std::string feature_str;
4696 if (!bucket->GetAsString(&feature_str)) {
4697 return error::kInvalidArguments;
4698 }
4699
4700 // TODO(gman): make this some kind of table to function pointer thingy.
4701 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
4702 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
4703 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
4704 use_shader_translator_ = false;
4705 } else {
4706 return error::kNoError;
4707 }
4708
4709 *result = 1; // true.
4710 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:104711}
4712
[email protected]96449d2c2009-11-25 00:01:324713// Include the auto-generated part of this file. We split this because it means
4714// we can easily edit the non-auto generated parts right here in this file
4715// instead of having to edit some template or the code generator.
4716#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
4717
4718} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:254719} // namespace gpu