blob: ceabfa794315433e9cd1281d19b099be9565df26 [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]b9363b22010-06-09 22:06:1516#include "app/gfx/gl/gl_implementation.h"
[email protected]2041cf342010-02-19 03:15:5917#include "base/callback.h"
[email protected]96449d2c2009-11-25 00:01:3218#include "base/scoped_ptr.h"
[email protected]6217d392010-03-25 22:08:3519#include "base/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0220#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3221#define GLES2_GPU_SERVICE 1
22#include "gpu/command_buffer/common/gles2_cmd_format.h"
23#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1024#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5025#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3226#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5027#include "gpu/command_buffer/service/context_group.h"
[email protected]a25fa872010-03-25 02:57:5828#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3229#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4630#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4731#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5832#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4733#include "gpu/command_buffer/service/shader_manager.h"
34#include "gpu/command_buffer/service/texture_manager.h"
[email protected]4e8a5b122010-05-08 22:00:1035#include "gpu/GLES2/gles2_command_buffer.h"
[email protected]2cb1fa92010-05-13 20:30:5136
[email protected]2cb1fa92010-05-13 20:30:5137#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
[email protected]3094c2a2010-04-29 21:50:4538#include "third_party/angle/include/GLSLANG/ShaderLang.h"
[email protected]2cb1fa92010-05-13 20:30:5139#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
[email protected]de17df392010-04-23 21:09:4140
[email protected]6217d392010-03-25 22:08:3541#if !defined(GL_DEPTH24_STENCIL8)
42#define GL_DEPTH24_STENCIL8 0x88F0
43#endif
44
[email protected]a7a27ace2009-12-12 00:11:2545namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3246namespace gles2 {
47
[email protected]6217d392010-03-25 22:08:3548class GLES2DecoderImpl;
49
[email protected]07f54fcc2009-12-22 02:46:3050// Check that certain assumptions the code makes are true. There are places in
51// the code where shared memory is passed direclty to GL. Example, glUniformiv,
52// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
53// a few others) are 32bits. If they are not 32bits the code will have to change
54// to call those GL functions with service side memory and then copy the results
55// to shared memory, converting the sizes.
56COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
57 GLint_not_same_size_as_uint32);
58COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
59 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3760COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
61 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3062
[email protected]43f28f832010-02-03 02:28:4863// TODO(kbr): the use of this anonymous namespace core dumps the
64// linker on Mac OS X 10.6 when the symbol ordering file is used
65// namespace {
[email protected]96449d2c2009-11-25 00:01:3266
67// Returns the address of the first byte after a struct.
68template <typename T>
69const void* AddressAfterStruct(const T& pod) {
70 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
71}
72
[email protected]07f54fcc2009-12-22 02:46:3073// Returns the address of the frst byte after the struct or NULL if size >
74// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3275template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3076RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
77 uint32 size,
78 uint32 immediate_data_size) {
79 return (size <= immediate_data_size) ?
80 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
81 NULL;
[email protected]96449d2c2009-11-25 00:01:3282}
83
[email protected]07f54fcc2009-12-22 02:46:3084// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1885bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3286 GLuint count,
87 size_t size,
[email protected]a76b0052010-03-05 00:33:1888 unsigned int elements_per_unit,
89 uint32* dst) {
90 uint32 value;
91 if (!SafeMultiplyUint32(count, size, &value)) {
92 return false;
93 }
94 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
95 return false;
96 }
97 *dst = value;
98 return true;
[email protected]96449d2c2009-11-25 00:01:3299}
100
101// A struct to hold info about each command.
102struct CommandInfo {
103 int arg_flags; // How to handle the arguments for this command
104 int arg_count; // How many arguments are expected for this command.
105};
106
107// A table of CommandInfo for all the commands.
108const CommandInfo g_command_info[] = {
109 #define GLES2_CMD_OP(name) { \
110 name::kArgFlags, \
111 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
112
113 GLES2_COMMAND_LIST(GLES2_CMD_OP)
114
115 #undef GLES2_CMD_OP
116};
117
[email protected]6217d392010-03-25 22:08:35118// This class prevents any GL errors that occur when it is in scope from
119// being reported to the client.
120class ScopedGLErrorSuppressor {
121 public:
122 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
123 ~ScopedGLErrorSuppressor();
124 private:
125 GLES2DecoderImpl* decoder_;
126 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
127};
128
129// Temporarily changes a decoder's bound 2D texture and restore it when this
130// object goes out of scope. Also temporarily switches to using active texture
131// unit zero in case the client has changed that to something invalid.
132class ScopedTexture2DBinder {
133 public:
134 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
135 ~ScopedTexture2DBinder();
136
137 private:
138 GLES2DecoderImpl* decoder_;
139 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
140};
141
142// Temporarily changes a decoder's bound render buffer and restore it when this
143// object goes out of scope.
144class ScopedRenderBufferBinder {
145 public:
146 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
147 ~ScopedRenderBufferBinder();
148
149 private:
150 GLES2DecoderImpl* decoder_;
151 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
152};
153
154// Temporarily changes a decoder's bound frame buffer and restore it when this
155// object goes out of scope.
156class ScopedFrameBufferBinder {
157 public:
158 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
159 ~ScopedFrameBufferBinder();
160
161 private:
162 GLES2DecoderImpl* decoder_;
163 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
164};
165
[email protected]2f2d7042010-04-14 21:45:58166// Temporarily switch to a decoder's default GL context, having known default
167// state.
168class ScopedDefaultGLContext {
169 public:
170 explicit ScopedDefaultGLContext(GLES2DecoderImpl* decoder);
171 ~ScopedDefaultGLContext();
172
173 private:
174 GLES2DecoderImpl* decoder_;
175 DISALLOW_COPY_AND_ASSIGN(ScopedDefaultGLContext);
176};
177
[email protected]6217d392010-03-25 22:08:35178// Encapsulates an OpenGL texture.
179class Texture {
180 public:
181 explicit Texture(GLES2DecoderImpl* decoder);
182 ~Texture();
183
184 // Create a new render texture.
185 void Create();
186
187 // Set the initial size and format of a render texture or resize it.
188 bool AllocateStorage(const gfx::Size& size);
189
190 // Copy the contents of the currently bound frame buffer.
191 void Copy(const gfx::Size& size);
192
193 // Destroy the render texture. This must be explicitly called before
194 // destroying this object.
195 void Destroy();
196
197 GLuint id() const {
198 return id_;
199 }
200
[email protected]d37231fa2010-04-09 21:16:02201 gfx::Size size() const {
202 return size_;
203 }
204
[email protected]6217d392010-03-25 22:08:35205 private:
206 GLES2DecoderImpl* decoder_;
207 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02208 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35209 DISALLOW_COPY_AND_ASSIGN(Texture);
210};
211
212// Encapsulates an OpenGL render buffer of any format.
213class RenderBuffer {
214 public:
215 explicit RenderBuffer(GLES2DecoderImpl* decoder);
216 ~RenderBuffer();
217
218 // Create a new render buffer.
219 void Create();
220
221 // Set the initial size and format of a render buffer or resize it.
222 bool AllocateStorage(const gfx::Size& size, GLenum format);
223
224 // Destroy the render buffer. This must be explicitly called before destroying
225 // this object.
226 void Destroy();
227
228 GLuint id() const {
229 return id_;
230 }
231
232 private:
233 GLES2DecoderImpl* decoder_;
234 GLuint id_;
235 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
236};
237
238// Encapsulates an OpenGL frame buffer.
239class FrameBuffer {
240 public:
241 explicit FrameBuffer(GLES2DecoderImpl* decoder);
242 ~FrameBuffer();
243
244 // Create a new frame buffer.
245 void Create();
246
247 // Attach a color render buffer to a frame buffer.
248 void AttachRenderTexture(Texture* texture);
249
[email protected]b9363b22010-06-09 22:06:15250 // Attach a render buffer to a frame buffer. Note that this unbinds any
251 // currently bound frame buffer.
252 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35253
254 // Clear the given attached buffers.
255 void Clear(GLbitfield buffers);
256
257 // Destroy the frame buffer. This must be explicitly called before destroying
258 // this object.
259 void Destroy();
260
261 // See glCheckFramebufferStatusEXT.
262 GLenum CheckStatus();
263
264 GLuint id() const {
265 return id_;
266 }
267
268 private:
269 GLES2DecoderImpl* decoder_;
270 GLuint id_;
271 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
272};
[email protected]43f28f832010-02-03 02:28:48273// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32274
[email protected]3916c97e2010-02-25 03:20:50275GLES2Decoder::GLES2Decoder(ContextGroup* group)
276 : group_(group),
[email protected]3916c97e2010-02-25 03:20:50277 debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32278}
279
[email protected]3916c97e2010-02-25 03:20:50280GLES2Decoder::~GLES2Decoder() {
281}
282
[email protected]f39f4b3f2010-05-12 17:04:08283class VertexAttribManager {
[email protected]96449d2c2009-11-25 00:01:32284 public:
[email protected]07f54fcc2009-12-22 02:46:30285 // Info about Vertex Attributes. This is used to track what the user currently
286 // has bound on each Vertex Attribute so that checking can be done at
287 // glDrawXXX time.
288 class VertexAttribInfo {
289 public:
[email protected]f39f4b3f2010-05-12 17:04:08290 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
[email protected]b1122982010-05-17 23:04:24291 struct Vec4 {
292 float v[4];
293 };
[email protected]f39f4b3f2010-05-12 17:04:08294
[email protected]07f54fcc2009-12-22 02:46:30295 VertexAttribInfo()
[email protected]f39f4b3f2010-05-12 17:04:08296 : index_(0),
297 enabled_(false),
298 size_(4),
299 type_(GL_FLOAT),
[email protected]07f54fcc2009-12-22 02:46:30300 offset_(0),
[email protected]b1122982010-05-17 23:04:24301 normalized_(GL_FALSE),
302 gl_stride_(0),
[email protected]f39f4b3f2010-05-12 17:04:08303 real_stride_(16),
304 list_(NULL) {
[email protected]b1122982010-05-17 23:04:24305 value_.v[0] = 0.0f;
306 value_.v[1] = 0.0f;
307 value_.v[2] = 0.0f;
308 value_.v[3] = 1.0f;
[email protected]07f54fcc2009-12-22 02:46:30309 }
[email protected]3916c97e2010-02-25 03:20:50310
[email protected]07f54fcc2009-12-22 02:46:30311 // Returns true if this VertexAttrib can access index.
[email protected]f39f4b3f2010-05-12 17:04:08312 bool CanAccess(GLuint index) const;
[email protected]07f54fcc2009-12-22 02:46:30313
[email protected]3916c97e2010-02-25 03:20:50314 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30315 return buffer_;
316 }
317
[email protected]8bf5a3e2010-01-29 04:21:36318 GLsizei offset() const {
319 return offset_;
320 }
321
[email protected]f39f4b3f2010-05-12 17:04:08322 GLuint index() const {
323 return index_;
324 }
325
[email protected]b1122982010-05-17 23:04:24326 GLint size() const {
327 return size_;
328 }
329
330 GLenum type() const {
331 return type_;
332 }
333
334 GLboolean normalized() const {
335 return normalized_;
336 }
337
338 GLsizei gl_stride() const {
339 return gl_stride_;
340 }
341
[email protected]07f54fcc2009-12-22 02:46:30342 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50343 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30344 GLint size,
345 GLenum type,
[email protected]b1122982010-05-17 23:04:24346 GLboolean normalized,
347 GLsizei gl_stride,
[email protected]07f54fcc2009-12-22 02:46:30348 GLsizei real_stride,
349 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24350 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30351 buffer_ = buffer;
352 size_ = size;
353 type_ = type;
[email protected]b1122982010-05-17 23:04:24354 normalized_ = normalized;
355 gl_stride_ = gl_stride;
[email protected]07f54fcc2009-12-22 02:46:30356 real_stride_ = real_stride;
357 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50358 }
359
360 void ClearBuffer() {
361 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30362 }
363
[email protected]f39f4b3f2010-05-12 17:04:08364 bool enabled() const {
365 return enabled_;
366 }
367
[email protected]b1122982010-05-17 23:04:24368 void set_value(const Vec4& value) {
369 value_ = value;
370 }
371
372 const Vec4& value() const {
373 return value_;
374 }
375
[email protected]07f54fcc2009-12-22 02:46:30376 private:
[email protected]f39f4b3f2010-05-12 17:04:08377 friend class VertexAttribManager;
378
379 void set_enabled(bool enabled) {
380 enabled_ = enabled;
381 }
382
383 void set_index(GLuint index) {
384 index_ = index;
385 }
386
387 void SetList(VertexAttribInfoList* new_list) {
388 DCHECK(new_list);
389
390 if (list_) {
391 list_->erase(it_);
392 }
393
394 it_ = new_list->insert(new_list->end(), this);
395 list_ = new_list;
396 }
397
398 // The index of this attrib.
399 GLuint index_;
400
[email protected]07f54fcc2009-12-22 02:46:30401 // Whether or not this attribute is enabled.
402 bool enabled_;
403
404 // number of components (1, 2, 3, 4)
405 GLint size_;
406
407 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
408 GLenum type_;
409
410 // The offset into the buffer.
411 GLsizei offset_;
412
[email protected]b1122982010-05-17 23:04:24413 GLboolean normalized_;
414
415 // The stride passed to glVertexAttribPointer.
416 GLsizei gl_stride_;
417
[email protected]07f54fcc2009-12-22 02:46:30418 // The stride that will be used to access the buffer. This is the actual
419 // stide, NOT the GL bogus stride. In other words there is never a stride
420 // of 0.
421 GLsizei real_stride_;
422
[email protected]b1122982010-05-17 23:04:24423 // The current value of the attrib.
424 Vec4 value_;
425
[email protected]3916c97e2010-02-25 03:20:50426 // The buffer bound to this attribute.
427 BufferManager::BufferInfo::Ref buffer_;
[email protected]f39f4b3f2010-05-12 17:04:08428
429 // List this info is on.
430 VertexAttribInfoList* list_;
431
432 // Iterator for list this info is on. Enabled/Disabled
433 VertexAttribInfoList::iterator it_;
[email protected]07f54fcc2009-12-22 02:46:30434 };
435
[email protected]f39f4b3f2010-05-12 17:04:08436 typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
437
438 VertexAttribManager()
439 : max_vertex_attribs_(0) {
440 }
441
442 void Initialize(uint32 num_vertex_attribs);
443
444 bool Enable(GLuint index, bool enable);
445
446 const VertexAttribInfoList& GetEnabledVertexAttribInfos() const {
447 return enabled_vertex_attribs_;
448 }
449
450 VertexAttribInfo* GetVertexAttribInfo(GLuint index) {
[email protected]b1122982010-05-17 23:04:24451 if (index < max_vertex_attribs_) {
452 return &vertex_attrib_infos_[index];
453 }
454 return NULL;
[email protected]f39f4b3f2010-05-12 17:04:08455 }
456
457 private:
458 uint32 max_vertex_attribs_;
459
460 // Info for each vertex attribute saved so we can check at glDrawXXX time
461 // if it is safe to draw.
462 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
463
464 // Lists for which vertex attribs are enabled, disabled.
465 VertexAttribInfoList enabled_vertex_attribs_;
466 VertexAttribInfoList disabled_vertex_attribs_;
467};
468
469bool VertexAttribManager::VertexAttribInfo::CanAccess(GLuint index) const {
470 if (!enabled_) {
471 return true;
472 }
473
474 if (!buffer_ || buffer_->IsDeleted()) {
475 return false;
476 }
477
478 // The number of elements that can be accessed.
479 GLsizeiptr buffer_size = buffer_->size();
480 if (offset_ > buffer_size || real_stride_ == 0) {
481 return false;
482 }
483
484 uint32 usable_size = buffer_size - offset_;
485 GLuint num_elements = usable_size / real_stride_ +
486 ((usable_size % real_stride_) >=
487 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
488 return index < num_elements;
489}
490
491
492void VertexAttribManager::Initialize(uint32 max_vertex_attribs) {
493 max_vertex_attribs_ = max_vertex_attribs;
494 vertex_attrib_infos_.reset(
495 new VertexAttribInfo[max_vertex_attribs]);
496 for (uint32 vv = 0; vv < max_vertex_attribs; ++vv) {
497 vertex_attrib_infos_[vv].set_index(vv);
498 vertex_attrib_infos_[vv].SetList(&disabled_vertex_attribs_);
499 }
500}
501
502bool VertexAttribManager::Enable(GLuint index, bool enable) {
503 if (index >= max_vertex_attribs_) {
504 return false;
505 }
506 VertexAttribInfo& info = vertex_attrib_infos_[index];
507 if (info.enabled() != enable) {
508 info.set_enabled(enable);
509 info.SetList(enable ? &enabled_vertex_attribs_ : &disabled_vertex_attribs_);
510 }
511 return true;
512}
513
514// This class implements GLES2Decoder so we don't have to expose all the GLES2
515// cmd stuff to outside this class.
516class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
517 public GLES2Decoder {
518 public:
519 explicit GLES2DecoderImpl(ContextGroup* group);
520
[email protected]96449d2c2009-11-25 00:01:32521 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14522 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50523 unsigned int arg_count,
524 const void* args);
[email protected]96449d2c2009-11-25 00:01:32525
526 // Overridden from AsyncAPIInterface.
527 virtual const char* GetCommandName(unsigned int command_id) const;
528
529 // Overridden from GLES2Decoder.
[email protected]5a6db6c2010-04-22 18:32:06530 virtual bool Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:35531 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:02532 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:35533 uint32 parent_client_texture_id);
[email protected]96449d2c2009-11-25 00:01:32534 virtual void Destroy();
[email protected]6217d392010-03-25 22:08:35535 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]c71caa82010-06-02 23:25:45536 virtual bool UpdateOffscreenFrameBufferSize();
[email protected]eb54a562010-01-20 21:55:18537 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55538 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30539 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]43f28f832010-02-03 02:28:48540
541 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
542
[email protected]96449d2c2009-11-25 00:01:32543 private:
[email protected]6217d392010-03-25 22:08:35544 friend class ScopedGLErrorSuppressor;
545 friend class ScopedTexture2DBinder;
546 friend class ScopedFrameBufferBinder;
547 friend class ScopedRenderBufferBinder;
[email protected]2f2d7042010-04-14 21:45:58548 friend class ScopedDefaultGLContext;
[email protected]6217d392010-03-25 22:08:35549 friend class RenderBuffer;
550 friend class FrameBuffer;
551
[email protected]3916c97e2010-02-25 03:20:50552 // State associated with each texture unit.
553 struct TextureUnit {
554 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
555
556 // The last target that was bound to this texture unit.
557 GLenum bind_target;
558
559 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
560 TextureManager::TextureInfo::Ref bound_texture_2d;
561
562 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
563 // glBindTexture
564 TextureManager::TextureInfo::Ref bound_texture_cube_map;
565 };
566
[email protected]ae51d192010-04-27 00:48:03567 // Helpers for the glGen and glDelete functions.
568 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
569 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
570 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
571 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
572 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
573 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
574 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
575 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47576
[email protected]3916c97e2010-02-25 03:20:50577 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50578 BufferManager* buffer_manager() {
579 return group_->buffer_manager();
580 }
581
[email protected]a25fa872010-03-25 02:57:58582 RenderbufferManager* renderbuffer_manager() {
583 return group_->renderbuffer_manager();
584 }
585
586 FramebufferManager* framebuffer_manager() {
587 return group_->framebuffer_manager();
588 }
589
[email protected]3916c97e2010-02-25 03:20:50590 ProgramManager* program_manager() {
591 return group_->program_manager();
592 }
593
594 ShaderManager* shader_manager() {
595 return group_->shader_manager();
596 }
597
598 TextureManager* texture_manager() {
599 return group_->texture_manager();
600 }
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]ef526492010-06-02 23:12:25993 // Returns true if textures were set.
994 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:50995 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]96449d2c2009-11-25 00:01:321042 // Generate a member function prototype for each command in an automated and
1043 // typesafe way.
1044 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141045 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191046 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321047 const gles2::name& args); \
1048
1049 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1050
1051 #undef GLES2_CMD_OP
1052
[email protected]2f2d7042010-04-14 21:45:581053 // The GL context this decoder renders to on behalf of the client.
[email protected]66791e382010-07-14 20:48:301054 scoped_ptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021055
[email protected]2f2d7042010-04-14 21:45:581056 // A GLContext that is kept in its default state. It is used to perform
1057 // operations that should not be dependent on client set GLContext state, like
1058 // clearing a render buffer when it is created.
1059 // TODO(apatrick): Decoders in the same ContextGroup could potentially share
1060 // the same default GL context.
[email protected]5a6db6c2010-04-22 18:32:061061 scoped_ptr<gfx::GLContext> default_context_;
[email protected]2f2d7042010-04-14 21:45:581062
[email protected]6217d392010-03-25 22:08:351063 // A parent decoder can access this decoders saved offscreen frame buffer.
1064 // The parent pointer is reset if the parent is destroyed.
1065 base::WeakPtr<GLES2DecoderImpl> parent_;
1066
1067 // Width and height to which an offscreen frame buffer should be resized on
1068 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021069 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351070
[email protected]96449d2c2009-11-25 00:01:321071 // Current GL error bits.
1072 uint32 error_bits_;
1073
[email protected]96449d2c2009-11-25 00:01:321074 // Util to help with GL.
1075 GLES2Util util_;
1076
1077 // pack alignment as last set by glPixelStorei
1078 GLint pack_alignment_;
1079
1080 // unpack alignment as last set by glPixelStorei
1081 GLint unpack_alignment_;
1082
1083 // The currently bound array buffer. If this is 0 it is illegal to call
1084 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501085 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321086
1087 // The currently bound element array buffer. If this is 0 it is illegal
1088 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501089 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301090
[email protected]f39f4b3f2010-05-12 17:04:081091 // Class that manages vertex attribs.
1092 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301093
[email protected]b1122982010-05-17 23:04:241094 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1095 GLuint attrib_0_buffer_id_;
1096
1097 // The value currently in attrib_0.
1098 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1099
1100 // The size of attrib 0.
1101 GLsizei attrib_0_size_;
1102
[email protected]3916c97e2010-02-25 03:20:501103 // Current active texture by 0 - n index.
1104 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1105 // be 2.
1106 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301107
[email protected]3916c97e2010-02-25 03:20:501108 // Which textures are bound to texture units through glActiveTexture.
1109 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471110
[email protected]cd6cd4762010-06-01 23:07:211111 // Black (0,0,0,1) textures for when non-renderable textures are used.
[email protected]3916c97e2010-02-25 03:20:501112 // NOTE: There is no corresponding TextureInfo for these textures.
1113 // TextureInfos are only for textures the client side can access.
1114 GLuint black_2d_texture_id_;
1115 GLuint black_cube_texture_id_;
[email protected]45bf5152010-02-12 00:11:311116
[email protected]1d32bc82010-01-13 22:06:461117 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501118 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301119
[email protected]86093972010-03-11 00:13:561120 // The currently bound framebuffer
[email protected]051b1372010-04-12 02:42:081121 FramebufferManager::FramebufferInfo::Ref bound_framebuffer_;
[email protected]86093972010-03-11 00:13:561122
1123 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081124 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561125
[email protected]96449d2c2009-11-25 00:01:321126 bool anti_aliased_;
1127
[email protected]b9363b22010-06-09 22:06:151128 // The offscreen frame buffer that the client renders to. With EGL, the
1129 // depth and stencil buffers are separate. With regular GL there is a single
1130 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1131 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351132 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1133 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]b9363b22010-06-09 22:06:151134 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1135 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]6217d392010-03-25 22:08:351136
1137 // The copy that is saved when SwapBuffers is called.
1138 scoped_ptr<Texture> offscreen_saved_color_texture_;
1139
[email protected]43f28f832010-02-03 02:28:481140 scoped_ptr<Callback0::Type> swap_buffers_callback_;
1141
[email protected]8eee29c2010-04-29 03:38:291142 // The last error message set.
1143 std::string last_error_;
1144
[email protected]b1d2dcb2010-05-17 19:24:181145 bool use_shader_translator_;
1146
[email protected]9438b012010-06-15 22:55:051147 // Cached from the context group.
1148 const Validators* validators_;
1149
[email protected]96449d2c2009-11-25 00:01:321150 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1151};
1152
[email protected]6217d392010-03-25 22:08:351153ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1154 : decoder_(decoder) {
1155 decoder_->CopyRealGLErrorsToWrapper();
1156}
1157
1158ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1159 decoder_->ClearRealGLErrors();
1160}
1161
1162ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1163 GLuint id)
1164 : decoder_(decoder) {
1165 ScopedGLErrorSuppressor suppressor(decoder_);
1166
1167 // TODO(apatrick): Check if there are any other states that need to be reset
1168 // before binding a new texture.
1169 glActiveTexture(GL_TEXTURE0);
1170 glBindTexture(GL_TEXTURE_2D, id);
1171}
1172
1173ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1174 ScopedGLErrorSuppressor suppressor(decoder_);
1175 GLES2DecoderImpl::TextureUnit& info = decoder_->texture_units_[0];
1176 GLuint last_id;
1177 if (info.bound_texture_2d)
[email protected]ae51d192010-04-27 00:48:031178 last_id = info.bound_texture_2d->service_id();
[email protected]6217d392010-03-25 22:08:351179 else
1180 last_id = 0;
1181
1182 glBindTexture(GL_TEXTURE_2D, last_id);
1183 glActiveTexture(GL_TEXTURE0 + decoder_->active_texture_unit_);
1184}
1185
1186ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1187 GLuint id)
1188 : decoder_(decoder) {
1189 ScopedGLErrorSuppressor suppressor(decoder_);
1190 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1191}
1192
1193ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1194 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:081195 glBindRenderbufferEXT(
1196 GL_RENDERBUFFER,
1197 decoder_->bound_renderbuffer_ ?
[email protected]ae51d192010-04-27 00:48:031198 decoder_->bound_renderbuffer_->service_id() : 0);
[email protected]6217d392010-03-25 22:08:351199}
1200
1201ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1202 GLuint id)
1203 : decoder_(decoder) {
1204 ScopedGLErrorSuppressor suppressor(decoder_);
1205 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1206}
1207
1208ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1209 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]051b1372010-04-12 02:42:081210 FramebufferManager::FramebufferInfo* info =
1211 decoder_->bound_framebuffer_.get();
[email protected]ae51d192010-04-27 00:48:031212 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]051b1372010-04-12 02:42:081213 if (framebuffer_id == 0 &&
[email protected]6217d392010-03-25 22:08:351214 decoder_->offscreen_target_frame_buffer_.get()) {
1215 glBindFramebufferEXT(GL_FRAMEBUFFER,
1216 decoder_->offscreen_target_frame_buffer_->id());
1217 } else {
[email protected]051b1372010-04-12 02:42:081218 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_id);
[email protected]6217d392010-03-25 22:08:351219 }
1220}
1221
[email protected]2f2d7042010-04-14 21:45:581222ScopedDefaultGLContext::ScopedDefaultGLContext(GLES2DecoderImpl* decoder)
1223 : decoder_(decoder) {
1224 decoder_->default_context_->MakeCurrent();
1225}
1226
1227ScopedDefaultGLContext::~ScopedDefaultGLContext() {
1228 decoder_->context_->MakeCurrent();
1229}
1230
[email protected]6217d392010-03-25 22:08:351231Texture::Texture(GLES2DecoderImpl* decoder)
1232 : decoder_(decoder),
1233 id_(0) {
1234}
1235
1236Texture::~Texture() {
1237 // This does not destroy the render texture because that would require that
1238 // the associated GL context was current. Just check that it was explicitly
1239 // destroyed.
1240 DCHECK_EQ(id_, 0u);
1241}
1242
1243void Texture::Create() {
1244 ScopedGLErrorSuppressor suppressor(decoder_);
1245 Destroy();
1246 glGenTextures(1, &id_);
1247}
1248
1249bool Texture::AllocateStorage(const gfx::Size& size) {
1250 DCHECK_NE(id_, 0u);
1251 ScopedGLErrorSuppressor suppressor(decoder_);
1252 ScopedTexture2DBinder binder(decoder_, id_);
1253 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1254 glTexParameteri(
1255 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1256 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1257 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351258
1259 glTexImage2D(GL_TEXTURE_2D,
1260 0, // mip level
1261 GL_RGBA,
1262 size.width(),
1263 size.height(),
1264 0, // border
1265 GL_RGBA,
1266 GL_UNSIGNED_BYTE,
1267 NULL);
1268
[email protected]d37231fa2010-04-09 21:16:021269 size_ = size;
1270
[email protected]6217d392010-03-25 22:08:351271 return glGetError() == GL_NO_ERROR;
1272}
1273
1274void Texture::Copy(const gfx::Size& size) {
1275 DCHECK_NE(id_, 0u);
1276 ScopedGLErrorSuppressor suppressor(decoder_);
1277 ScopedTexture2DBinder binder(decoder_, id_);
1278 glCopyTexImage2D(GL_TEXTURE_2D,
1279 0, // level
1280 GL_RGBA,
1281 0, 0,
1282 size.width(),
1283 size.height(),
1284 0); // border
1285}
1286
1287void Texture::Destroy() {
1288 if (id_ != 0) {
1289 ScopedGLErrorSuppressor suppressor(decoder_);
1290 glDeleteTextures(1, &id_);
1291 id_ = 0;
1292 }
1293}
1294
1295RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1296 : decoder_(decoder),
1297 id_(0) {
1298}
1299
1300RenderBuffer::~RenderBuffer() {
1301 // This does not destroy the render buffer because that would require that
1302 // the associated GL context was current. Just check that it was explicitly
1303 // destroyed.
1304 DCHECK_EQ(id_, 0u);
1305}
1306
1307void RenderBuffer::Create() {
1308 ScopedGLErrorSuppressor suppressor(decoder_);
1309 Destroy();
1310 glGenRenderbuffersEXT(1, &id_);
1311}
1312
1313bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format) {
1314 ScopedGLErrorSuppressor suppressor(decoder_);
1315 ScopedRenderBufferBinder binder(decoder_, id_);
1316 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1317 format,
1318 size.width(),
1319 size.height());
1320 return glGetError() == GL_NO_ERROR;
1321}
1322
1323void RenderBuffer::Destroy() {
1324 if (id_ != 0) {
1325 ScopedGLErrorSuppressor suppressor(decoder_);
1326 glDeleteRenderbuffersEXT(1, &id_);
1327 id_ = 0;
1328 }
1329}
1330
1331FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1332 : decoder_(decoder),
1333 id_(0) {
1334}
1335
1336FrameBuffer::~FrameBuffer() {
1337 // This does not destroy the frame buffer because that would require that
1338 // the associated GL context was current. Just check that it was explicitly
1339 // destroyed.
1340 DCHECK_EQ(id_, 0u);
1341}
1342
1343void FrameBuffer::Create() {
1344 ScopedGLErrorSuppressor suppressor(decoder_);
1345 Destroy();
1346 glGenFramebuffersEXT(1, &id_);
1347}
1348
1349void FrameBuffer::AttachRenderTexture(Texture* texture) {
1350 DCHECK_NE(id_, 0u);
1351 ScopedGLErrorSuppressor suppressor(decoder_);
1352 ScopedFrameBufferBinder binder(decoder_, id_);
1353 GLuint attach_id = texture ? texture->id() : 0;
1354 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1355 GL_COLOR_ATTACHMENT0,
1356 GL_TEXTURE_2D,
1357 attach_id,
1358 0);
1359}
1360
[email protected]b9363b22010-06-09 22:06:151361void FrameBuffer::AttachRenderBuffer(GLenum target,
1362 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351363 DCHECK_NE(id_, 0u);
1364 ScopedGLErrorSuppressor suppressor(decoder_);
1365 ScopedFrameBufferBinder binder(decoder_, id_);
1366 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1367 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151368 target,
[email protected]6217d392010-03-25 22:08:351369 GL_RENDERBUFFER,
1370 attach_id);
1371}
1372
1373void FrameBuffer::Clear(GLbitfield buffers) {
1374 ScopedGLErrorSuppressor suppressor(decoder_);
1375 ScopedFrameBufferBinder binder(decoder_, id_);
1376 glClear(buffers);
1377}
1378
1379void FrameBuffer::Destroy() {
1380 if (id_ != 0) {
1381 ScopedGLErrorSuppressor suppressor(decoder_);
1382 glDeleteFramebuffersEXT(1, &id_);
1383 id_ = 0;
1384 }
1385}
1386
1387GLenum FrameBuffer::CheckStatus() {
1388 DCHECK_NE(id_, 0u);
1389 ScopedGLErrorSuppressor suppressor(decoder_);
1390 ScopedFrameBufferBinder binder(decoder_, id_);
1391 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1392}
1393
[email protected]3916c97e2010-02-25 03:20:501394GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1395 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321396}
1397
[email protected]3916c97e2010-02-25 03:20:501398GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
1399 : GLES2Decoder(group),
[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),
[email protected]9438b012010-06-15 22:55:051410 use_shader_translator_(true),
1411 validators_(group->validators()) {
[email protected]b1122982010-05-17 23:04:241412 attrib_0_value_.v[0] = 0.0f;
1413 attrib_0_value_.v[1] = 0.0f;
1414 attrib_0_value_.v[2] = 0.0f;
1415 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151416
1417 // The shader translator is not needed for EGL because it already uses the
1418 // GLSL ES syntax. It is translated for the unit tests because
1419 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the empty
1420 // string to CompileShader and this is not a valid shader. TODO(apatrick):
1421 // fix this test.
1422 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ||
1423 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1424 use_shader_translator_ = false;
1425 }
[email protected]96449d2c2009-11-25 00:01:321426}
1427
[email protected]5a6db6c2010-04-22 18:32:061428bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
[email protected]6217d392010-03-25 22:08:351429 const gfx::Size& size,
[email protected]d37231fa2010-04-09 21:16:021430 GLES2Decoder* parent,
[email protected]6217d392010-03-25 22:08:351431 uint32 parent_client_texture_id) {
[email protected]4bedba72010-04-20 22:08:541432 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301433 DCHECK(!context_.get());
1434
1435 // Take ownership of the GLContext.
1436 context_.reset(context);
[email protected]d37231fa2010-04-09 21:16:021437
[email protected]2f2d7042010-04-14 21:45:581438 // Create a GL context that is kept in a default state and shares a namespace
1439 // with the main GL context.
[email protected]66791e382010-07-14 20:48:301440 default_context_.reset(gfx::GLContext::CreateOffscreenGLContext(
1441 context_.get()));
[email protected]4bedba72010-04-20 22:08:541442 if (!default_context_.get()) {
[email protected]2f2d7042010-04-14 21:45:581443 Destroy();
1444 return false;
1445 }
1446
[email protected]6217d392010-03-25 22:08:351447 // Keep only a weak pointer to the parent so we don't unmap its client
[email protected]d37231fa2010-04-09 21:16:021448 // frame buffer after it has been destroyed.
[email protected]6217d392010-03-25 22:08:351449 if (parent)
1450 parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
1451
[email protected]246a70452010-03-05 21:53:501452 if (!MakeCurrent()) {
1453 Destroy();
1454 return false;
[email protected]eb54a562010-01-20 21:55:181455 }
1456
[email protected]246a70452010-03-05 21:53:501457 CHECK_GL_ERROR();
1458
1459 if (!group_->Initialize()) {
1460 Destroy();
1461 return false;
1462 }
1463
[email protected]f39f4b3f2010-05-12 17:04:081464 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]b1122982010-05-17 23:04:241465 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1466 // OpenGL ES 2.0 does not have this issue.
1467 glEnableVertexAttribArray(0);
1468 glGenBuffersARB(1, &attrib_0_buffer_id_);
1469 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1470 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1471 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]f39f4b3f2010-05-12 17:04:081472
[email protected]246a70452010-03-05 21:53:501473 texture_units_.reset(
1474 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151475 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
1476 texture_units_[tt].bound_texture_2d =
1477 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1478 texture_units_[tt].bound_texture_cube_map =
1479 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
1480 }
[email protected]4e8a5b122010-05-08 22:00:101481
[email protected]246a70452010-03-05 21:53:501482 GLuint ids[2];
1483 glGenTextures(2, ids);
1484 // Make black textures for replacing non-renderable textures.
1485 black_2d_texture_id_ = ids[0];
1486 black_cube_texture_id_ = ids[1];
[email protected]cd6cd4762010-06-01 23:07:211487 static uint8 black[] = {0, 0, 0, 255};
[email protected]246a70452010-03-05 21:53:501488 glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
1489 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
1490 GL_UNSIGNED_BYTE, black);
1491 glBindTexture(GL_TEXTURE_2D, 0);
1492 glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
[email protected]1958e0e2010-04-22 05:17:151493 for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
1494 glTexImage2D(GLES2Util::IndexToGLFaceTarget(ii), 0, GL_RGBA, 1, 1, 0,
1495 GL_RGBA, GL_UNSIGNED_BYTE, black);
[email protected]246a70452010-03-05 21:53:501496 }
1497 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
1498 CHECK_GL_ERROR();
1499
[email protected]d37231fa2010-04-09 21:16:021500 if (context_->IsOffscreen()) {
[email protected]6217d392010-03-25 22:08:351501 // Create the target frame buffer. This is the one that the client renders
1502 // directly to.
1503 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1504 offscreen_target_frame_buffer_->Create();
1505 offscreen_target_color_texture_.reset(new Texture(this));
1506 offscreen_target_color_texture_->Create();
[email protected]b9363b22010-06-09 22:06:151507 offscreen_target_depth_render_buffer_.reset(
[email protected]6217d392010-03-25 22:08:351508 new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151509 offscreen_target_depth_render_buffer_->Create();
1510 offscreen_target_stencil_render_buffer_.reset(
1511 new RenderBuffer(this));
1512 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:351513
1514 // Create the saved offscreen texture. The target frame buffer is copied
1515 // here when SwapBuffers is called.
1516 offscreen_saved_color_texture_.reset(new Texture(this));
1517 offscreen_saved_color_texture_->Create();
1518
[email protected]6217d392010-03-25 22:08:351519 // Map the ID of the saved offscreen texture into the parent so that
1520 // it can reference it.
1521 if (parent_) {
1522 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]6217d392010-03-25 22:08:351523 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:031524 parent_->CreateTextureInfo(parent_client_texture_id, service_id);
[email protected]6217d392010-03-25 22:08:351525 parent_->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
1526 }
1527
1528 // Allocate the render buffers at their initial size and check the status
1529 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021530 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351531 if (!UpdateOffscreenFrameBufferSize()) {
1532 DLOG(ERROR) << "Could not allocate offscreen buffer storage.";
1533 Destroy();
1534 return false;
1535 }
1536
1537 // Bind to the new default frame buffer (the offscreen target frame buffer).
1538 // This should now be associated with ID zero.
1539 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
1540 }
1541
[email protected]76a0ee102010-04-07 21:03:041542 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1543 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1544 // isn't well documented; it was discovered in the Khronos OpenGL ES
1545 // mailing list archives.
[email protected]b9363b22010-06-09 22:06:151546 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1547 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
1548 }
[email protected]de17df392010-04-23 21:09:411549
[email protected]b9363b22010-06-09 22:06:151550#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
[email protected]de17df392010-04-23 21:09:411551 // Initialize GLSL ES to GLSL translator.
[email protected]b9363b22010-06-09 22:06:151552 static bool glsl_translator_initialized = false;
1553 if (!glsl_translator_initialized) {
1554 if (!ShInitialize()) {
1555 DLOG(ERROR) << "Could not initialize GLSL translator.";
1556 Destroy();
1557 return false;
1558 }
1559 glsl_translator_initialized = true;
[email protected]de17df392010-04-23 21:09:411560 }
1561#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
[email protected]76a0ee102010-04-07 21:03:041562
[email protected]246a70452010-03-05 21:53:501563 return true;
[email protected]96449d2c2009-11-25 00:01:321564}
1565
[email protected]ae51d192010-04-27 00:48:031566bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471567 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031568 if (GetBufferInfo(client_ids[ii])) {
1569 return false;
1570 }
1571 }
1572 scoped_array<GLuint> service_ids(new GLuint[n]);
1573 glGenBuffersARB(n, service_ids.get());
1574 for (GLsizei ii = 0; ii < n; ++ii) {
1575 CreateBufferInfo(client_ids[ii], service_ids[ii]);
1576 }
1577 return true;
1578}
1579
1580bool GLES2DecoderImpl::GenFramebuffersHelper(
1581 GLsizei n, const GLuint* client_ids) {
1582 for (GLsizei ii = 0; ii < n; ++ii) {
1583 if (GetFramebufferInfo(client_ids[ii])) {
1584 return false;
1585 }
1586 }
1587 scoped_array<GLuint> service_ids(new GLuint[n]);
1588 glGenFramebuffersEXT(n, service_ids.get());
1589 for (GLsizei ii = 0; ii < n; ++ii) {
1590 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
1591 }
1592 return true;
1593}
1594
1595bool GLES2DecoderImpl::GenRenderbuffersHelper(
1596 GLsizei n, const GLuint* client_ids) {
1597 for (GLsizei ii = 0; ii < n; ++ii) {
1598 if (GetRenderbufferInfo(client_ids[ii])) {
1599 return false;
1600 }
1601 }
1602 scoped_array<GLuint> service_ids(new GLuint[n]);
1603 glGenRenderbuffersEXT(n, service_ids.get());
1604 for (GLsizei ii = 0; ii < n; ++ii) {
1605 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
1606 }
1607 return true;
1608}
1609
1610bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
1611 for (GLsizei ii = 0; ii < n; ++ii) {
1612 if (GetTextureInfo(client_ids[ii])) {
1613 return false;
1614 }
1615 }
1616 scoped_array<GLuint> service_ids(new GLuint[n]);
1617 glGenTextures(n, service_ids.get());
1618 for (GLsizei ii = 0; ii < n; ++ii) {
1619 CreateTextureInfo(client_ids[ii], service_ids[ii]);
1620 }
1621 return true;
1622}
1623
1624void GLES2DecoderImpl::DeleteBuffersHelper(
1625 GLsizei n, const GLuint* client_ids) {
1626 for (GLsizei ii = 0; ii < n; ++ii) {
1627 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
1628 if (info) {
1629 GLuint service_id = info->service_id();
1630 glDeleteBuffersARB(1, &service_id);
1631 RemoveBufferInfo(client_ids[ii]);
1632 }
[email protected]a93bb842010-02-16 23:03:471633 }
[email protected]07f54fcc2009-12-22 02:46:301634}
1635
[email protected]ae51d192010-04-27 00:48:031636void GLES2DecoderImpl::DeleteFramebuffersHelper(
1637 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:581638 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031639 FramebufferManager::FramebufferInfo* info =
1640 GetFramebufferInfo(client_ids[ii]);
1641 if (info) {
1642 GLuint service_id = info->service_id();
1643 glDeleteFramebuffersEXT(1, &service_id);
1644 RemoveFramebufferInfo(client_ids[ii]);
1645 }
[email protected]a25fa872010-03-25 02:57:581646 }
[email protected]07f54fcc2009-12-22 02:46:301647}
1648
[email protected]ae51d192010-04-27 00:48:031649void GLES2DecoderImpl::DeleteRenderbuffersHelper(
1650 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:581651 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031652 RenderbufferManager::RenderbufferInfo* info =
1653 GetRenderbufferInfo(client_ids[ii]);
1654 if (info) {
1655 GLuint service_id = info->service_id();
1656 glDeleteRenderbuffersEXT(1, &service_id);
1657 RemoveRenderbufferInfo(client_ids[ii]);
1658 }
[email protected]a25fa872010-03-25 02:57:581659 }
[email protected]07f54fcc2009-12-22 02:46:301660}
1661
[email protected]ae51d192010-04-27 00:48:031662void GLES2DecoderImpl::DeleteTexturesHelper(
1663 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471664 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031665 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
1666 if (info) {
1667 GLuint service_id = info->service_id();
1668 glDeleteTextures(1, &service_id);
1669 RemoveTextureInfo(client_ids[ii]);
1670 }
[email protected]a93bb842010-02-16 23:03:471671 }
[email protected]07f54fcc2009-12-22 02:46:301672}
1673
[email protected]43f28f832010-02-03 02:28:481674// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:321675
[email protected]eb54a562010-01-20 21:55:181676bool GLES2DecoderImpl::MakeCurrent() {
[email protected]66791e382010-07-14 20:48:301677 return context_.get() ? context_->MakeCurrent() : false;
[email protected]eb54a562010-01-20 21:55:181678}
1679
[email protected]d37231fa2010-04-09 21:16:021680gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() {
1681 if (bound_framebuffer_ != 0) {
1682 int width = 0;
1683 int height = 0;
[email protected]246a70452010-03-05 21:53:501684
[email protected]d37231fa2010-04-09 21:16:021685 // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
1686 // stencil.
1687 GLint fb_type = 0;
1688 glGetFramebufferAttachmentParameterivEXT(
1689 GL_FRAMEBUFFER,
1690 GL_COLOR_ATTACHMENT0,
1691 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
1692 &fb_type);
1693 switch (fb_type) {
1694 case GL_RENDERBUFFER:
1695 {
1696 GLint renderbuffer_id = 0;
1697 glGetFramebufferAttachmentParameterivEXT(
1698 GL_FRAMEBUFFER,
1699 GL_COLOR_ATTACHMENT0,
1700 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1701 &renderbuffer_id);
1702 if (renderbuffer_id != 0) {
1703 glGetRenderbufferParameterivEXT(
1704 GL_RENDERBUFFER,
1705 GL_RENDERBUFFER_WIDTH,
1706 &width);
1707 glGetRenderbufferParameterivEXT(
1708 GL_RENDERBUFFER,
1709 GL_RENDERBUFFER_HEIGHT,
1710 &height);
1711 }
1712 break;
1713 }
1714 case GL_TEXTURE:
1715 {
1716 GLint texture_id = 0;
1717 glGetFramebufferAttachmentParameterivEXT(
1718 GL_FRAMEBUFFER,
1719 GL_COLOR_ATTACHMENT0,
1720 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
1721 &texture_id);
1722 if (texture_id != 0) {
[email protected]ae51d192010-04-27 00:48:031723 GLuint client_id = 0;
1724 if (texture_manager()->GetClientId(texture_id, &client_id)) {
1725 TextureManager::TextureInfo* texture_info =
1726 GetTextureInfo(client_id);
1727 if (texture_info) {
1728 GLint level = 0;
1729 GLint face = 0;
1730 glGetFramebufferAttachmentParameterivEXT(
1731 GL_FRAMEBUFFER,
1732 GL_COLOR_ATTACHMENT0,
1733 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
1734 &level);
1735 glGetFramebufferAttachmentParameterivEXT(
1736 GL_FRAMEBUFFER,
1737 GL_COLOR_ATTACHMENT0,
1738 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
1739 &face);
1740 texture_info->GetLevelSize(
1741 face ? face : GL_TEXTURE_2D, level, &width, &height);
1742 }
[email protected]d37231fa2010-04-09 21:16:021743 }
1744 }
1745 break;
1746 }
1747 default:
1748 // unknown so assume width and height are zero.
1749 break;
[email protected]246a70452010-03-05 21:53:501750 }
1751
[email protected]d37231fa2010-04-09 21:16:021752 return gfx::Size(width, height);
1753 } else if (offscreen_target_color_texture_.get()) {
1754 return offscreen_target_color_texture_->size();
[email protected]6217d392010-03-25 22:08:351755 } else {
[email protected]d37231fa2010-04-09 21:16:021756 return context_->GetSize();
[email protected]d37231fa2010-04-09 21:16:021757 }
[email protected]246a70452010-03-05 21:53:501758}
1759
[email protected]6217d392010-03-25 22:08:351760bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]d37231fa2010-04-09 21:16:021761 if (offscreen_target_color_texture_->size() == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:351762 return true;
1763
1764 // Reallocate the offscreen target buffers.
[email protected]d37231fa2010-04-09 21:16:021765 if (!offscreen_target_color_texture_->AllocateStorage(
1766 pending_offscreen_size_)) {
[email protected]6217d392010-03-25 22:08:351767 return false;
1768 }
1769
[email protected]b9363b22010-06-09 22:06:151770 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1771 // ANGLE only allows 16-bit depth buffers to be requested. As it happens,
1772 // it creates a 24-bit depth buffer behind the scenes.
1773 // TODO(apatrick): Attempt to use a packed 24/8 depth stencil buffer here if
1774 // the extension is available.
1775 if (!offscreen_target_depth_render_buffer_->AllocateStorage(
1776 pending_offscreen_size_, GL_DEPTH_COMPONENT16)) {
1777 return false;
1778 }
1779
1780 if (!offscreen_target_stencil_render_buffer_->AllocateStorage(
1781 pending_offscreen_size_, GL_STENCIL_INDEX8)) {
1782 return false;
1783 }
1784 } else {
1785 if (!offscreen_target_depth_render_buffer_->AllocateStorage(
1786 pending_offscreen_size_, GL_DEPTH24_STENCIL8)) {
1787 return false;
1788 }
[email protected]6217d392010-03-25 22:08:351789 }
1790
[email protected]2f2d7042010-04-14 21:45:581791 // Attach the offscreen target buffers to the target frame buffer.
[email protected]6217d392010-03-25 22:08:351792 offscreen_target_frame_buffer_->AttachRenderTexture(
1793 offscreen_target_color_texture_.get());
[email protected]b9363b22010-06-09 22:06:151794 offscreen_target_frame_buffer_->AttachRenderBuffer(
1795 GL_DEPTH_ATTACHMENT,
1796 offscreen_target_depth_render_buffer_.get());
1797 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1798 offscreen_target_frame_buffer_->AttachRenderBuffer(
1799 GL_STENCIL_ATTACHMENT,
1800 offscreen_target_stencil_render_buffer_.get());
1801 } else {
1802 offscreen_target_frame_buffer_->AttachRenderBuffer(
1803 GL_STENCIL_ATTACHMENT,
1804 offscreen_target_depth_render_buffer_.get());
1805 }
[email protected]6217d392010-03-25 22:08:351806 if (offscreen_target_frame_buffer_->CheckStatus() !=
1807 GL_FRAMEBUFFER_COMPLETE) {
1808 return false;
1809 }
1810
[email protected]b9363b22010-06-09 22:06:151811 // TODO(apatrick): Fix this once ANGLE supports shared contexts.
[email protected]2f2d7042010-04-14 21:45:581812 // Clear offscreen frame buffer to its initial state. Use default GL context
1813 // to ensure clear is not affected by client set state.
[email protected]b9363b22010-06-09 22:06:151814 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]2f2d7042010-04-14 21:45:581815 ScopedDefaultGLContext scoped_context(this);
[email protected]b9363b22010-06-09 22:06:151816 glBindFramebufferEXT(GL_FRAMEBUFFER,
[email protected]2f2d7042010-04-14 21:45:581817 offscreen_target_frame_buffer_->id());
1818 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
[email protected]b9363b22010-06-09 22:06:151819 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
[email protected]2f2d7042010-04-14 21:45:581820
1821 if (glGetError() != GL_NO_ERROR)
1822 return false;
1823 }
[email protected]2f2d7042010-04-14 21:45:581824
[email protected]6217d392010-03-25 22:08:351825 if (parent_) {
[email protected]e566b955d2010-06-22 19:26:511826 // Adjust the saved offscreen color texture (only accessible to parent).
[email protected]d37231fa2010-04-09 21:16:021827 offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
1828
[email protected]2f2d7042010-04-14 21:45:581829 // Update the info about the offscreen saved color texture in the parent.
1830 // The reference to the parent is a weak pointer and will become null if the
1831 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:351832 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:141833 GLuint client_id;
1834 CHECK(parent_->texture_manager()->GetClientId(service_id, &client_id));
1835 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:351836 DCHECK(info);
1837
[email protected]ef526492010-06-02 23:12:251838 texture_manager()->SetLevelInfo(
1839 info,
1840 GL_TEXTURE_2D,
1841 0, // level
1842 GL_RGBA,
1843 pending_offscreen_size_.width(),
1844 pending_offscreen_size_.height(),
1845 1, // depth
1846 0, // border
1847 GL_RGBA,
1848 GL_UNSIGNED_BYTE);
[email protected]6217d392010-03-25 22:08:351849
[email protected]0c8c9d22010-06-25 17:36:391850 // Attach the saved offscreen color texture to a frame buffer so we can
1851 // clear it with glClear.
1852 offscreen_target_frame_buffer_->AttachRenderTexture(
1853 offscreen_saved_color_texture_.get());
1854 if (offscreen_target_frame_buffer_->CheckStatus() !=
1855 GL_FRAMEBUFFER_COMPLETE) {
[email protected]e566b955d2010-06-22 19:26:511856 return false;
[email protected]0c8c9d22010-06-25 17:36:391857 }
[email protected]e566b955d2010-06-22 19:26:511858
[email protected]0c8c9d22010-06-25 17:36:391859 // TODO(apatrick): Fix this once ANGLE supports shared contexts.
1860 // Clear the saved offscreen color texture. Use default GL context
1861 // to ensure clear is not affected by client set state.
1862 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1863 ScopedDefaultGLContext scoped_context(this);
1864 glBindFramebufferEXT(GL_FRAMEBUFFER,
1865 offscreen_target_frame_buffer_->id());
1866 glClear(GL_COLOR_BUFFER_BIT);
1867 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
1868
1869 if (glGetError() != GL_NO_ERROR)
1870 return false;
1871 }
1872
1873 // Re-attach the offscreen render texture to the target frame buffer.
1874 offscreen_target_frame_buffer_->AttachRenderTexture(
1875 offscreen_target_color_texture_.get());
1876 }
[email protected]e566b955d2010-06-22 19:26:511877
[email protected]6217d392010-03-25 22:08:351878 return true;
1879}
1880
[email protected]43f28f832010-02-03 02:28:481881void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
1882 swap_buffers_callback_.reset(callback);
1883}
1884
[email protected]96449d2c2009-11-25 00:01:321885void GLES2DecoderImpl::Destroy() {
[email protected]66791e382010-07-14 20:48:301886 if (context_.get()) {
[email protected]4bedba72010-04-20 22:08:541887 MakeCurrent();
[email protected]6217d392010-03-25 22:08:351888
[email protected]b1122982010-05-17 23:04:241889 if (black_2d_texture_id_) {
1890 glDeleteTextures(1, &black_2d_texture_id_);
1891 }
1892 if (black_cube_texture_id_) {
1893 glDeleteTextures(1, &black_cube_texture_id_);
1894 }
1895 if (attrib_0_buffer_id_) {
1896 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
1897 }
1898
[email protected]4bedba72010-04-20 22:08:541899 // Remove the saved frame buffer mapping from the parent decoder. The
1900 // parent pointer is a weak pointer so it will be null if the parent has
1901 // already been destroyed.
1902 if (parent_) {
1903 // First check the texture has been mapped into the parent. This might not
1904 // be the case if initialization failed midway through.
1905 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]ae51d192010-04-27 00:48:031906 GLuint client_id = 0;
1907 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
1908 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]4bedba72010-04-20 22:08:541909 }
[email protected]6217d392010-03-25 22:08:351910 }
[email protected]6217d392010-03-25 22:08:351911
[email protected]4bedba72010-04-20 22:08:541912 if (offscreen_target_frame_buffer_.get()) {
1913 offscreen_target_frame_buffer_->Destroy();
1914 offscreen_target_frame_buffer_.reset();
1915 }
[email protected]6217d392010-03-25 22:08:351916
[email protected]4bedba72010-04-20 22:08:541917 if (offscreen_target_color_texture_.get()) {
1918 offscreen_target_color_texture_->Destroy();
1919 offscreen_target_color_texture_.reset();
1920 }
[email protected]6217d392010-03-25 22:08:351921
[email protected]b9363b22010-06-09 22:06:151922 if (offscreen_target_depth_render_buffer_.get()) {
1923 offscreen_target_depth_render_buffer_->Destroy();
1924 offscreen_target_depth_render_buffer_.reset();
1925 }
1926
1927 if (offscreen_target_stencil_render_buffer_.get()) {
1928 offscreen_target_stencil_render_buffer_->Destroy();
1929 offscreen_target_stencil_render_buffer_.reset();
[email protected]4bedba72010-04-20 22:08:541930 }
[email protected]6217d392010-03-25 22:08:351931
[email protected]4bedba72010-04-20 22:08:541932 if (offscreen_saved_color_texture_.get()) {
1933 offscreen_saved_color_texture_->Destroy();
1934 offscreen_saved_color_texture_.reset();
1935 }
[email protected]66791e382010-07-14 20:48:301936
1937 context_->Destroy();
1938 context_.reset();
[email protected]d37231fa2010-04-09 21:16:021939 }
[email protected]2f2d7042010-04-14 21:45:581940
1941 if (default_context_.get()) {
1942 default_context_->Destroy();
1943 default_context_.reset();
1944 }
[email protected]96449d2c2009-11-25 00:01:321945}
1946
[email protected]6217d392010-03-25 22:08:351947void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
1948 // We can't resize the render buffers immediately because there might be a
1949 // partial frame rendered into them and we don't want the tail end of that
1950 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021951 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351952}
1953
[email protected]96449d2c2009-11-25 00:01:321954const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
1955 if (command_id > kStartPoint && command_id < kNumCommands) {
1956 return gles2::GetCommandName(static_cast<CommandId>(command_id));
1957 }
1958 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
1959}
1960
1961// Decode command with its arguments, and call the corresponding GL function.
1962// Note: args is a pointer to the command buffer. As such, it could be changed
1963// by a (malicious) client at any time, so if validation has to happen, it
1964// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:141965error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:321966 unsigned int command,
1967 unsigned int arg_count,
1968 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:141969 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191970 if (debug()) {
1971 // TODO(gman): Change output to something useful for NaCl.
[email protected]f39f4b3f2010-05-12 17:04:081972 DLOG(INFO) << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:191973 }
[email protected]96449d2c2009-11-25 00:01:321974 unsigned int command_index = command - kStartPoint - 1;
1975 if (command_index < arraysize(g_command_info)) {
1976 const CommandInfo& info = g_command_info[command_index];
1977 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
1978 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
1979 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:191980 uint32 immediate_data_size =
1981 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:321982 switch (command) {
1983 #define GLES2_CMD_OP(name) \
1984 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:191985 result = Handle ## name( \
1986 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321987 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:191988 break; \
[email protected]96449d2c2009-11-25 00:01:321989
1990 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:321991 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:381992 }
1993 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:301994 GLenum error;
1995 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:381996 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:291997 SetGLError(error, NULL);
[email protected]f39f4b3f2010-05-12 17:04:081998 DLOG(INFO) << "GL ERROR: " << error
1999 << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192000 }
[email protected]96449d2c2009-11-25 00:01:322001 }
2002 } else {
[email protected]f7a64ee2010-02-01 22:24:142003 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322004 }
[email protected]b9849abf2009-11-25 19:13:192005 } else {
2006 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322007 }
[email protected]b9849abf2009-11-25 19:13:192008 return result;
[email protected]96449d2c2009-11-25 00:01:322009}
2010
[email protected]ae51d192010-04-27 00:48:032011void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2012 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502013}
2014
[email protected]ae51d192010-04-27 00:48:032015bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2016 if (GetProgramInfo(client_id)) {
2017 return false;
2018 }
[email protected]96449d2c2009-11-25 00:01:322019 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032020 if (service_id != 0) {
2021 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322022 }
[email protected]ae51d192010-04-27 00:48:032023 return true;
[email protected]96449d2c2009-11-25 00:01:322024}
2025
[email protected]ae51d192010-04-27 00:48:032026bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2027 if (GetShaderInfo(client_id)) {
2028 return false;
[email protected]96449d2c2009-11-25 00:01:322029 }
[email protected]ae51d192010-04-27 00:48:032030 GLuint service_id = glCreateShader(type);
2031 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382032 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032033 }
2034 return true;
[email protected]96449d2c2009-11-25 00:01:322035}
2036
[email protected]3916c97e2010-02-25 03:20:502037void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452038 GLuint texture_index = texture_unit - GL_TEXTURE0;
2039 if (texture_index > group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292040 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502041 return;
2042 }
[email protected]36cef8ce2010-03-16 07:34:452043 active_texture_unit_ = texture_index;
2044 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502045}
2046
[email protected]051b1372010-04-12 02:42:082047void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502048 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082049 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032050 if (client_id != 0) {
2051 info = GetBufferInfo(client_id);
2052 if (!info) {
2053 // It's a new id so make a buffer info for it.
2054 glGenBuffersARB(1, &service_id);
2055 CreateBufferInfo(client_id, service_id);
2056 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102057 IdAllocator* id_allocator =
2058 group_->GetIdAllocator(id_namespaces::kBuffers);
2059 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032060 }
[email protected]051b1372010-04-12 02:42:082061 }
[email protected]ae51d192010-04-27 00:48:032062 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102063 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292064 SetGLError(GL_INVALID_OPERATION,
2065 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472066 return;
2067 }
[email protected]ae51d192010-04-27 00:48:032068 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472069 }
[email protected]96449d2c2009-11-25 00:01:322070 switch (target) {
2071 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502072 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322073 break;
2074 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502075 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322076 break;
2077 default:
[email protected]a93bb842010-02-16 23:03:472078 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322079 break;
2080 }
[email protected]051b1372010-04-12 02:42:082081 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322082}
2083
[email protected]051b1372010-04-12 02:42:082084void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2085 FramebufferManager::FramebufferInfo* info = NULL;
2086 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032087 if (client_id != 0) {
2088 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082089 if (!info) {
[email protected]ae51d192010-04-27 00:48:032090 // It's a new id so make a framebuffer info for it.
2091 glGenFramebuffersEXT(1, &service_id);
2092 CreateFramebufferInfo(client_id, service_id);
2093 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102094 IdAllocator* id_allocator =
2095 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2096 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032097 } else {
2098 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082099 }
2100 }
2101 bound_framebuffer_ = info;
[email protected]6217d392010-03-25 22:08:352102
2103 // When rendering to an offscreen frame buffer, instead of unbinding from
2104 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]051b1372010-04-12 02:42:082105 if (info == NULL && offscreen_target_frame_buffer_.get())
2106 service_id = offscreen_target_frame_buffer_->id();
[email protected]6217d392010-03-25 22:08:352107
[email protected]051b1372010-04-12 02:42:082108 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562109}
2110
[email protected]051b1372010-04-12 02:42:082111void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2112 RenderbufferManager::RenderbufferInfo* info = NULL;
2113 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032114 if (client_id != 0) {
2115 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082116 if (!info) {
[email protected]ae51d192010-04-27 00:48:032117 // It's a new id so make a renderbuffer info for it.
2118 glGenRenderbuffersEXT(1, &service_id);
2119 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102120 info = GetRenderbufferInfo(client_id);
2121 IdAllocator* id_allocator =
2122 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2123 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032124 } else {
2125 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082126 }
2127 }
2128 bound_renderbuffer_ = info;
2129 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562130}
2131
[email protected]051b1372010-04-12 02:42:082132void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032133 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082134 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032135 if (client_id != 0) {
2136 info = GetTextureInfo(client_id);
2137 if (!info) {
2138 // It's a new id so make a texture info for it.
2139 glGenTextures(1, &service_id);
2140 CreateTextureInfo(client_id, service_id);
2141 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:102142 IdAllocator* id_allocator =
2143 group_->GetIdAllocator(id_namespaces::kTextures);
2144 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032145 }
2146 } else {
2147 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082148 }
[email protected]ae51d192010-04-27 00:48:032149
[email protected]1958e0e2010-04-22 05:17:152150 // Check the texture exists
2151 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032152 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292153 SetGLError(GL_INVALID_OPERATION,
2154 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152155 return;
2156 }
2157 if (info->target() == 0) {
2158 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472159 }
[email protected]ae51d192010-04-27 00:48:032160 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502161 TextureUnit& unit = texture_units_[active_texture_unit_];
2162 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472163 switch (target) {
2164 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502165 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472166 break;
2167 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502168 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472169 break;
2170 default:
2171 NOTREACHED(); // Validation should prevent us getting here.
2172 break;
2173 }
2174}
2175
[email protected]07f54fcc2009-12-22 02:46:302176void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082177 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]b1122982010-05-17 23:04:242178 if (index != 0) {
2179 glDisableVertexAttribArray(index);
2180 }
[email protected]07f54fcc2009-12-22 02:46:302181 } else {
[email protected]8eee29c2010-04-29 03:38:292182 SetGLError(GL_INVALID_VALUE,
2183 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302184 }
2185}
2186
2187void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082188 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302189 glEnableVertexAttribArray(index);
2190 } else {
[email protected]8eee29c2010-04-29 03:38:292191 SetGLError(GL_INVALID_VALUE,
2192 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302193 }
2194}
2195
[email protected]a93bb842010-02-16 23:03:472196void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502197 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]ef526492010-06-02 23:12:252198 if (!info || !texture_manager()->MarkMipmapsGenerated(info)) {
[email protected]8eee29c2010-04-29 03:38:292199 SetGLError(GL_INVALID_OPERATION,
2200 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472201 return;
2202 }
2203 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:472204}
2205
[email protected]b273e432010-04-12 17:23:582206bool GLES2DecoderImpl::GetHelper(
2207 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582208 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152209 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2210 switch (pname) {
[email protected]b273e432010-04-12 17:23:582211 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2212 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102213 if (params) {
2214 *params = GL_RGBA; // TODO(gman): get correct format.
2215 }
[email protected]b273e432010-04-12 17:23:582216 return true;
2217 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2218 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102219 if (params) {
2220 *params = GL_UNSIGNED_BYTE; // TODO(gman): get correct type.
2221 }
[email protected]b273e432010-04-12 17:23:582222 return true;
2223 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2224 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102225 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482226 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102227 }
[email protected]b273e432010-04-12 17:23:582228 return true;
2229 case GL_MAX_VARYING_VECTORS:
2230 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102231 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482232 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102233 }
[email protected]b273e432010-04-12 17:23:582234 return true;
2235 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2236 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102237 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482238 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102239 }
[email protected]b273e432010-04-12 17:23:582240 return true;
[email protected]b9363b22010-06-09 22:06:152241 }
2242 }
2243 switch (pname) {
[email protected]656dcaad2010-05-07 17:18:372244 case GL_COMPRESSED_TEXTURE_FORMATS:
2245 *num_written = 0;
2246 // We don't support compressed textures.
2247 return true;
[email protected]b273e432010-04-12 17:23:582248 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
2249 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102250 if (params) {
2251 *params = 0; // We don't support compressed textures.
2252 }
[email protected]b273e432010-04-12 17:23:582253 return true;
2254 case GL_NUM_SHADER_BINARY_FORMATS:
2255 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102256 if (params) {
2257 *params = 0; // We don't support binary shader formats.
2258 }
[email protected]b273e432010-04-12 17:23:582259 return true;
2260 case GL_SHADER_BINARY_FORMATS:
2261 *num_written = 0;
2262 return true; // We don't support binary shader format.s
2263 case GL_SHADER_COMPILER:
2264 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102265 if (params) {
2266 *params = GL_TRUE;
2267 }
[email protected]b273e432010-04-12 17:23:582268 return true;
[email protected]6b8cf1a2010-05-06 16:13:582269 case GL_ARRAY_BUFFER_BINDING:
2270 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102271 if (params) {
2272 if (bound_array_buffer_) {
2273 GLuint client_id = 0;
2274 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
2275 &client_id);
2276 *params = client_id;
2277 } else {
2278 *params = 0;
2279 }
[email protected]6b8cf1a2010-05-06 16:13:582280 }
2281 return true;
2282 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
2283 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102284 if (params) {
2285 if (bound_element_array_buffer_) {
2286 GLuint client_id = 0;
2287 buffer_manager()->GetClientId(
2288 bound_element_array_buffer_->service_id(),
2289 &client_id);
2290 *params = client_id;
2291 } else {
2292 *params = 0;
2293 }
[email protected]6b8cf1a2010-05-06 16:13:582294 }
2295 return true;
2296 case GL_FRAMEBUFFER_BINDING:
2297 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102298 if (params) {
2299 if (bound_framebuffer_) {
2300 GLuint client_id = 0;
2301 framebuffer_manager()->GetClientId(
2302 bound_framebuffer_->service_id(), &client_id);
2303 *params = client_id;
2304 } else {
2305 *params = 0;
2306 }
[email protected]6b8cf1a2010-05-06 16:13:582307 }
2308 return true;
2309 case GL_RENDERBUFFER_BINDING:
2310 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102311 if (params) {
2312 if (bound_renderbuffer_) {
2313 GLuint client_id = 0;
2314 renderbuffer_manager()->GetClientId(
2315 bound_renderbuffer_->service_id(), &client_id);
2316 *params = client_id;
2317 } else {
2318 *params = 0;
2319 }
[email protected]6b8cf1a2010-05-06 16:13:582320 }
2321 return true;
2322 case GL_CURRENT_PROGRAM:
2323 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102324 if (params) {
2325 if (current_program_) {
2326 GLuint client_id = 0;
2327 program_manager()->GetClientId(
2328 current_program_->service_id(), &client_id);
2329 *params = client_id;
2330 } else {
2331 *params = 0;
2332 }
[email protected]6b8cf1a2010-05-06 16:13:582333 }
2334 return true;
[email protected]4e8a5b122010-05-08 22:00:102335 case GL_TEXTURE_BINDING_2D:
2336 *num_written = 1;
2337 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582338 TextureUnit& unit = texture_units_[active_texture_unit_];
2339 if (unit.bound_texture_2d) {
2340 GLuint client_id = 0;
2341 texture_manager()->GetClientId(
2342 unit.bound_texture_2d->service_id(), &client_id);
2343 *params = client_id;
2344 } else {
2345 *params = 0;
2346 }
[email protected]6b8cf1a2010-05-06 16:13:582347 }
[email protected]4e8a5b122010-05-08 22:00:102348 return true;
2349 case GL_TEXTURE_BINDING_CUBE_MAP:
2350 *num_written = 1;
2351 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:582352 TextureUnit& unit = texture_units_[active_texture_unit_];
2353 if (unit.bound_texture_cube_map) {
2354 GLuint client_id = 0;
2355 texture_manager()->GetClientId(
2356 unit.bound_texture_cube_map->service_id(), &client_id);
2357 *params = client_id;
2358 } else {
2359 *params = 0;
2360 }
[email protected]6b8cf1a2010-05-06 16:13:582361 }
[email protected]4e8a5b122010-05-08 22:00:102362 return true;
[email protected]b273e432010-04-12 17:23:582363 default:
[email protected]4e8a5b122010-05-08 22:00:102364 *num_written = util_.GLGetNumValuesReturned(pname);
2365 if (params) {
2366 glGetIntegerv(pname, params);
2367 }
2368 return true;
[email protected]b273e432010-04-12 17:23:582369 }
2370}
2371
[email protected]4e8a5b122010-05-08 22:00:102372bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
2373 GLenum pname, GLsizei* num_values) {
2374 return GetHelper(pname, NULL, num_values);
2375}
2376
[email protected]b273e432010-04-12 17:23:582377void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
2378 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:102379 GLsizei num_written = 0;
2380 if (GetHelper(pname, NULL, &num_written)) {
2381 scoped_array<GLint> values(new GLint[num_written]);
2382 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:582383 for (GLsizei ii = 0; ii < num_written; ++ii) {
2384 params[ii] = static_cast<GLboolean>(values[ii]);
2385 }
2386 } else {
2387 glGetBooleanv(pname, params);
2388 }
2389}
2390
2391void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
2392 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:102393 GLsizei num_written = 0;
2394 if (GetHelper(pname, NULL, &num_written)) {
2395 scoped_array<GLint> values(new GLint[num_written]);
2396 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:582397 for (GLsizei ii = 0; ii < num_written; ++ii) {
2398 params[ii] = static_cast<GLfloat>(values[ii]);
2399 }
2400 } else {
2401 glGetFloatv(pname, params);
2402 }
2403}
2404
2405void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
2406 DCHECK(params);
2407 GLsizei num_written;
2408 if (!GetHelper(pname, params, &num_written)) {
2409 glGetIntegerv(pname, params);
2410 }
2411}
2412
[email protected]a0c3e972010-04-21 00:49:132413void GLES2DecoderImpl::DoGetProgramiv(
2414 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:582415 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2416 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:132417 if (!info) {
[email protected]a0c3e972010-04-21 00:49:132418 return;
2419 }
2420 info->GetProgramiv(pname, params);
2421}
2422
[email protected]558847a2010-03-24 07:02:542423error::Error GLES2DecoderImpl::HandleBindAttribLocation(
2424 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:582425 GLuint program = static_cast<GLuint>(c.program);
2426 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2427 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032428 if (!info) {
[email protected]558847a2010-03-24 07:02:542429 return error::kNoError;
2430 }
2431 GLuint index = static_cast<GLuint>(c.index);
2432 uint32 name_size = c.data_size;
2433 const char* name = GetSharedMemoryAs<const char*>(
2434 c.name_shm_id, c.name_shm_offset, name_size);
2435 if (name == NULL) {
2436 return error::kOutOfBounds;
2437 }
2438 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:032439 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542440 return error::kNoError;
2441}
2442
2443error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
2444 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:582445 GLuint program = static_cast<GLuint>(c.program);
2446 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2447 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032448 if (!info) {
[email protected]558847a2010-03-24 07:02:542449 return error::kNoError;
2450 }
2451 GLuint index = static_cast<GLuint>(c.index);
2452 uint32 name_size = c.data_size;
2453 const char* name = GetImmediateDataAs<const char*>(
2454 c, name_size, immediate_data_size);
2455 if (name == NULL) {
2456 return error::kOutOfBounds;
2457 }
2458 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:032459 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542460 return error::kNoError;
2461}
2462
2463error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
2464 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:582465 GLuint program = static_cast<GLuint>(c.program);
2466 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2467 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:032468 if (!info) {
[email protected]558847a2010-03-24 07:02:542469 return error::kNoError;
2470 }
2471 GLuint index = static_cast<GLuint>(c.index);
2472 Bucket* bucket = GetBucket(c.name_bucket_id);
2473 if (!bucket || bucket->size() == 0) {
2474 return error::kInvalidArguments;
2475 }
2476 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:182477 if (!bucket->GetAsString(&name_str)) {
2478 return error::kInvalidArguments;
2479 }
[email protected]ae51d192010-04-27 00:48:032480 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:542481 return error::kNoError;
2482}
2483
[email protected]f7a64ee2010-02-01 22:24:142484error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:462485 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:032486 GLuint client_id = c.shader;
2487 if (client_id) {
2488 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
2489 if (info) {
2490 glDeleteShader(info->service_id());
2491 RemoveShaderInfo(client_id);
2492 } else {
[email protected]8eee29c2010-04-29 03:38:292493 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:032494 }
[email protected]96449d2c2009-11-25 00:01:322495 }
[email protected]f7a64ee2010-02-01 22:24:142496 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322497}
2498
[email protected]f7a64ee2010-02-01 22:24:142499error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:462500 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:032501 GLuint client_id = c.program;
2502 if (client_id) {
2503 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
2504 if (info) {
2505 glDeleteProgram(info->service_id());
2506 RemoveProgramInfo(client_id);
2507 } else {
[email protected]8eee29c2010-04-29 03:38:292508 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:032509 }
[email protected]96449d2c2009-11-25 00:01:322510 }
[email protected]f7a64ee2010-02-01 22:24:142511 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322512}
2513
[email protected]066849e32010-05-03 19:14:102514void GLES2DecoderImpl::DoDeleteSharedIds(
2515 GLuint namespace_id, GLsizei n, const GLuint* ids) {
2516 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2517 for (GLsizei ii = 0; ii < n; ++ii) {
2518 id_allocator->FreeID(ids[ii]);
2519 }
2520}
2521
2522error::Error GLES2DecoderImpl::HandleDeleteSharedIds(
2523 uint32 immediate_data_size, const gles2::DeleteSharedIds& c) {
2524 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2525 GLsizei n = static_cast<GLsizei>(c.n);
2526 uint32 data_size;
2527 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2528 return error::kOutOfBounds;
2529 }
2530 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
2531 c.ids_shm_id, c.ids_shm_offset, data_size);
2532 if (n < 0) {
2533 SetGLError(GL_INVALID_VALUE, "DeleteSharedIds: n < 0");
2534 return error::kNoError;
2535 }
2536 if (ids == NULL) {
2537 return error::kOutOfBounds;
2538 }
2539 DoDeleteSharedIds(namespace_id, n, ids);
2540 return error::kNoError;
2541}
2542
2543void GLES2DecoderImpl::DoGenSharedIds(
2544 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
2545 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2546 if (id_offset == 0) {
2547 for (GLsizei ii = 0; ii < n; ++ii) {
2548 ids[ii] = id_allocator->AllocateID();
2549 }
2550 } else {
2551 for (GLsizei ii = 0; ii < n; ++ii) {
2552 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
2553 id_offset = ids[ii] + 1;
2554 }
2555 }
2556}
2557
2558error::Error GLES2DecoderImpl::HandleGenSharedIds(
2559 uint32 immediate_data_size, const gles2::GenSharedIds& c) {
2560 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2561 GLuint id_offset = static_cast<GLuint>(c.id_offset);
2562 GLsizei n = static_cast<GLsizei>(c.n);
2563 uint32 data_size;
2564 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2565 return error::kOutOfBounds;
2566 }
2567 GLuint* ids = GetSharedMemoryAs<GLuint*>(
2568 c.ids_shm_id, c.ids_shm_offset, data_size);
2569 if (n < 0) {
2570 SetGLError(GL_INVALID_VALUE, "GenSharedIds: n < 0");
2571 return error::kNoError;
2572 }
2573 if (ids == NULL) {
2574 return error::kOutOfBounds;
2575 }
2576 DoGenSharedIds(namespace_id, id_offset, n, ids);
2577 return error::kNoError;
2578}
2579
2580void GLES2DecoderImpl::DoRegisterSharedIds(
2581 GLuint namespace_id, GLsizei n, const GLuint* ids) {
2582 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
2583 for (GLsizei ii = 0; ii < n; ++ii) {
2584 if (!id_allocator->MarkAsUsed(ids[ii])) {
2585 for (GLsizei jj = 0; jj < ii; ++jj) {
2586 id_allocator->FreeID(ids[jj]);
2587 }
2588 SetGLError(
2589 GL_INVALID_VALUE,
2590 "RegisterSharedIds: attempt to register id that already exists");
2591 return;
2592 }
2593 }
2594}
2595
2596error::Error GLES2DecoderImpl::HandleRegisterSharedIds(
2597 uint32 immediate_data_size, const gles2::RegisterSharedIds& c) {
2598 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
2599 GLsizei n = static_cast<GLsizei>(c.n);
2600 uint32 data_size;
2601 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
2602 return error::kOutOfBounds;
2603 }
2604 GLuint* ids = GetSharedMemoryAs<GLuint*>(
2605 c.ids_shm_id, c.ids_shm_offset, data_size);
2606 if (n < 0) {
2607 SetGLError(GL_INVALID_VALUE, "RegisterSharedIds: n < 0");
2608 return error::kNoError;
2609 }
2610 if (ids == NULL) {
2611 return error::kOutOfBounds;
2612 }
2613 DoRegisterSharedIds(namespace_id, n, ids);
2614 return error::kNoError;
2615}
2616
[email protected]07f54fcc2009-12-22 02:46:302617void GLES2DecoderImpl::DoDrawArrays(
2618 GLenum mode, GLint first, GLsizei count) {
[email protected]d81e8c52010-06-07 17:58:322619 // We have to check this here because the prototype for glDrawArrays
2620 // is GLint not GLsizei.
2621 if (first < 0) {
2622 SetGLError(GL_INVALID_ENUM, "glDrawArrays: first < 0");
2623 return;
2624 }
[email protected]07f54fcc2009-12-22 02:46:302625 if (IsDrawValid(first + count - 1)) {
[email protected]b1122982010-05-17 23:04:242626 bool simulated_attrib_0 = SimulateAttrib0(first + count - 1);
[email protected]ef526492010-06-02 23:12:252627 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]07f54fcc2009-12-22 02:46:302628 glDrawArrays(mode, first, count);
[email protected]ef526492010-06-02 23:12:252629 if (textures_set) {
[email protected]3916c97e2010-02-25 03:20:502630 RestoreStateForNonRenderableTextures();
2631 }
[email protected]b1122982010-05-17 23:04:242632 if (simulated_attrib_0) {
2633 RestoreStateForSimulatedAttrib0();
2634 }
[email protected]07f54fcc2009-12-22 02:46:302635 }
2636}
2637
[email protected]36cef8ce2010-03-16 07:34:452638void GLES2DecoderImpl::DoFramebufferRenderbuffer(
2639 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:032640 GLuint client_renderbuffer_id) {
[email protected]051b1372010-04-12 02:42:082641 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292642 SetGLError(GL_INVALID_OPERATION,
2643 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452644 return;
2645 }
[email protected]ae51d192010-04-27 00:48:032646 GLuint service_id = 0;
2647 if (client_renderbuffer_id) {
2648 RenderbufferManager::RenderbufferInfo* info =
2649 GetRenderbufferInfo(client_renderbuffer_id);
2650 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292651 SetGLError(GL_INVALID_OPERATION,
2652 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:032653 return;
2654 }
2655 service_id = info->service_id();
2656 }
2657 glFramebufferRenderbufferEXT(
2658 target, attachment, renderbuffertarget, service_id);
[email protected]36cef8ce2010-03-16 07:34:452659}
2660
2661GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]051b1372010-04-12 02:42:082662 if (!bound_framebuffer_) {
[email protected]36cef8ce2010-03-16 07:34:452663 return GL_FRAMEBUFFER_COMPLETE;
2664 }
2665 return glCheckFramebufferStatusEXT(target);
2666}
2667
2668void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:032669 GLenum target, GLenum attachment, GLenum textarget,
2670 GLuint client_texture_id, GLint level) {
[email protected]051b1372010-04-12 02:42:082671 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292672 SetGLError(GL_INVALID_OPERATION,
2673 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:452674 return;
2675 }
[email protected]ae51d192010-04-27 00:48:032676 GLuint service_id = 0;
2677 if (client_texture_id) {
2678 TextureManager::TextureInfo* info = GetTextureInfo(client_texture_id);
2679 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292680 SetGLError(GL_INVALID_OPERATION,
2681 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:032682 return;
2683 }
2684 service_id = info->service_id();
2685 }
2686 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]36cef8ce2010-03-16 07:34:452687}
2688
2689void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
2690 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082691 if (!bound_framebuffer_) {
[email protected]8eee29c2010-04-29 03:38:292692 SetGLError(GL_INVALID_OPERATION,
2693 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452694 return;
2695 }
2696 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
2697}
2698
2699void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
2700 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:082701 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:292702 SetGLError(GL_INVALID_OPERATION,
2703 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452704 return;
2705 }
[email protected]b71f52c2010-06-18 22:20:202706 if (pname == GL_RENDERBUFFER_INTERNAL_FORMAT) {
2707 *params = bound_renderbuffer_->internal_format();
2708 return;
2709 }
[email protected]36cef8ce2010-03-16 07:34:452710 glGetRenderbufferParameterivEXT(target, pname, params);
2711}
2712
2713void GLES2DecoderImpl::DoRenderbufferStorage(
2714 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:082715 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:292716 SetGLError(GL_INVALID_OPERATION,
2717 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:452718 return;
2719 }
[email protected]b71f52c2010-06-18 22:20:202720 bound_renderbuffer_->set_internal_format(internalformat);
2721#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
2722 switch (internalformat) {
2723 case GL_DEPTH_COMPONENT16:
2724 internalformat = GL_DEPTH_COMPONENT;
2725 break;
2726 case GL_RGBA4:
2727 case GL_RGB5_A1:
2728 internalformat = GL_RGBA;
2729 break;
2730 case GL_RGB565:
2731 internalformat = GL_RGB;
2732 break;
2733 }
2734#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
[email protected]36cef8ce2010-03-16 07:34:452735 glRenderbufferStorageEXT(target, internalformat, width, height);
2736}
2737
[email protected]07f54fcc2009-12-22 02:46:302738void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]6b8cf1a2010-05-06 16:13:582739 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
2740 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:472741 if (!info) {
[email protected]a93bb842010-02-16 23:03:472742 return;
2743 }
[email protected]d81e8c52010-06-07 17:58:322744 if (!info->CanLink()) {
[email protected]d81e8c52010-06-07 17:58:322745 return;
2746 }
[email protected]ae51d192010-04-27 00:48:032747 glLinkProgram(info->service_id());
[email protected]6b8cf1a2010-05-06 16:13:582748 GLint success = 0;
2749 glGetProgramiv(info->service_id(), GL_LINK_STATUS, &success);
2750 if (success) {
[email protected]a93bb842010-02-16 23:03:472751 info->Update();
[email protected]6b8cf1a2010-05-06 16:13:582752 } else {
2753 info->Reset();
[email protected]07f54fcc2009-12-22 02:46:302754 }
2755};
2756
[email protected]3916c97e2010-02-25 03:20:502757void GLES2DecoderImpl::DoTexParameterf(
2758 GLenum target, GLenum pname, GLfloat param) {
2759 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:302760 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292761 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]07f54fcc2009-12-22 02:46:302762 } else {
[email protected]ef526492010-06-02 23:12:252763 texture_manager()->SetParameter(info, pname, static_cast<GLint>(param));
[email protected]3916c97e2010-02-25 03:20:502764 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:302765 }
2766}
2767
[email protected]3916c97e2010-02-25 03:20:502768void GLES2DecoderImpl::DoTexParameteri(
2769 GLenum target, GLenum pname, GLint param) {
2770 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2771 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292772 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502773 } else {
[email protected]ef526492010-06-02 23:12:252774 texture_manager()->SetParameter(info, pname, param);
[email protected]3916c97e2010-02-25 03:20:502775 glTexParameteri(target, pname, param);
2776 }
2777}
2778
2779void GLES2DecoderImpl::DoTexParameterfv(
2780 GLenum target, GLenum pname, const GLfloat* params) {
2781 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2782 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292783 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502784 } else {
[email protected]ef526492010-06-02 23:12:252785 texture_manager()->SetParameter(
2786 info, pname, *reinterpret_cast<const GLint*>(params));
[email protected]3916c97e2010-02-25 03:20:502787 glTexParameterfv(target, pname, params);
2788 }
2789}
2790
2791void GLES2DecoderImpl::DoTexParameteriv(
2792 GLenum target, GLenum pname, const GLint* params) {
2793 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
2794 if (!info) {
[email protected]8eee29c2010-04-29 03:38:292795 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]3916c97e2010-02-25 03:20:502796 } else {
[email protected]ef526492010-06-02 23:12:252797 texture_manager()->SetParameter(info, pname, *params);
[email protected]3916c97e2010-02-25 03:20:502798 glTexParameteriv(target, pname, params);
2799 }
2800}
2801
[email protected]939e7362010-05-13 20:49:102802bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]3916c97e2010-02-25 03:20:502803 if (!current_program_ || current_program_->IsDeleted()) {
[email protected]939e7362010-05-13 20:49:102804 // The program does not exist.
2805 SetGLError(GL_INVALID_OPERATION,
2806 (std::string(function_name) + ": no program in use").c_str());
2807 return false;
2808 }
2809 if (!current_program_->IsValid()) {
2810 SetGLError(GL_INVALID_OPERATION,
2811 (std::string(function_name) + ": program not linked").c_str());
2812 return false;
2813 }
2814 return true;
2815}
2816
2817bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
2818 GLint location, const char* function_name) {
2819 if (!CheckCurrentProgram(function_name)) {
2820 return false;
2821 }
2822 return location != -1;
2823}
2824
2825bool GLES2DecoderImpl::GetUniformTypeByLocation(
2826 GLint location, const char* function_name, GLenum* type) {
2827 if (!CheckCurrentProgramForUniform(location, function_name)) {
2828 return false;
2829 }
2830 if (!current_program_->GetUniformTypeByLocation(location, type)) {
2831 SetGLError(GL_INVALID_OPERATION,
2832 (std::string(function_name) + ": program not linked").c_str());
2833 return false;
2834 }
2835 return true;
2836}
2837
2838
2839void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
2840 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:502841 return;
2842 }
2843 current_program_->SetSamplers(location, 1, &v0);
2844 glUniform1i(location, v0);
2845}
2846
2847void GLES2DecoderImpl::DoUniform1iv(
2848 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:102849 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:502850 return;
2851 }
2852 current_program_->SetSamplers(location, count, value);
2853 glUniform1iv(location, count, value);
2854}
2855
[email protected]939e7362010-05-13 20:49:102856void GLES2DecoderImpl::DoUniform1fv(
2857 GLint location, GLsizei count, const GLfloat* value) {
2858 GLenum type;
2859 if (!GetUniformTypeByLocation(location, "glUniform1fv", &type)) {
2860 return;
2861 }
2862 if (type == GL_BOOL) {
2863 scoped_array<GLint> temp(new GLint[count]);
2864 for (GLsizei ii = 0; ii < count; ++ii) {
2865 temp[ii] = static_cast<GLint>(value[ii]);
2866 }
2867 DoUniform1iv(location, count, temp.get());
2868 } else {
2869 glUniform1fv(location, count, value);
2870 }
2871}
2872
2873void GLES2DecoderImpl::DoUniform2fv(
2874 GLint location, GLsizei count, const GLfloat* value) {
2875 GLenum type;
2876 if (!GetUniformTypeByLocation(location, "glUniform2fv", &type)) {
2877 return;
2878 }
2879 if (type == GL_BOOL_VEC2) {
2880 GLsizei num_values = count * 2;
2881 scoped_array<GLint> temp(new GLint[num_values]);
2882 for (GLsizei ii = 0; ii < num_values; ++ii) {
2883 temp[ii] = static_cast<GLint>(value[ii]);
2884 }
2885 glUniform2iv(location, count, temp.get());
2886 } else {
2887 glUniform2fv(location, count, value);
2888 }
2889}
2890
2891void GLES2DecoderImpl::DoUniform3fv(
2892 GLint location, GLsizei count, const GLfloat* value) {
2893 GLenum type;
2894 if (!GetUniformTypeByLocation(location, "glUniform3fv", &type)) {
2895 return;
2896 }
2897 if (type == GL_BOOL_VEC3) {
2898 GLsizei num_values = count * 3;
2899 scoped_array<GLint> temp(new GLint[num_values]);
2900 for (GLsizei ii = 0; ii < num_values; ++ii) {
2901 temp[ii] = static_cast<GLint>(value[ii]);
2902 }
2903 glUniform3iv(location, count, temp.get());
2904 } else {
2905 glUniform3fv(location, count, value);
2906 }
2907}
2908
2909void GLES2DecoderImpl::DoUniform4fv(
2910 GLint location, GLsizei count, const GLfloat* value) {
2911 GLenum type;
2912 if (!GetUniformTypeByLocation(location, "glUniform4fv", &type)) {
2913 return;
2914 }
2915 if (type == GL_BOOL_VEC4) {
2916 GLsizei num_values = count * 4;
2917 scoped_array<GLint> temp(new GLint[num_values]);
2918 for (GLsizei ii = 0; ii < num_values; ++ii) {
2919 temp[ii] = static_cast<GLint>(value[ii]);
2920 }
2921 glUniform4iv(location, count, temp.get());
2922 } else {
2923 glUniform4fv(location, count, value);
2924 }
2925}
2926
[email protected]3916c97e2010-02-25 03:20:502927void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:032928 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:502929 ProgramManager::ProgramInfo* info = NULL;
2930 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:582931 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:502932 if (!info) {
[email protected]ae51d192010-04-27 00:48:032933 return;
2934 }
2935 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:502936 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:292937 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:502938 return;
2939 }
[email protected]ae51d192010-04-27 00:48:032940 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:502941 }
2942 current_program_ = info;
[email protected]ae51d192010-04-27 00:48:032943 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:502944}
2945
[email protected]96449d2c2009-11-25 00:01:322946GLenum GLES2DecoderImpl::GetGLError() {
2947 // Check the GL error first, then our wrapped error.
2948 GLenum error = glGetError();
2949 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:372950 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:322951 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:292952 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:322953 break;
2954 }
2955 }
2956 }
2957
2958 if (error != GL_NO_ERROR) {
2959 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:292960 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322961 }
2962 return error;
2963}
2964
[email protected]8eee29c2010-04-29 03:38:292965void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
2966 if (msg) {
2967 last_error_ = msg;
2968 DLOG(ERROR) << last_error_;
2969 }
[email protected]ddd968b82010-03-02 00:44:292970 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:322971}
2972
[email protected]07f54fcc2009-12-22 02:46:302973void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
2974 GLenum error;
2975 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:292976 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:302977 }
2978}
2979
[email protected]6217d392010-03-25 22:08:352980void GLES2DecoderImpl::ClearRealGLErrors() {
2981 GLenum error;
2982 while ((error = glGetError()) != GL_NO_ERROR) {
2983 NOTREACHED() << "GL error " << error << " was unhandled.";
2984 }
2985}
2986
[email protected]ef526492010-06-02 23:12:252987bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:502988 DCHECK(current_program_);
2989 DCHECK(!current_program_->IsDeleted());
[email protected]ef526492010-06-02 23:12:252990 // Only check if there are some unrenderable textures.
2991 if (!texture_manager()->HaveUnrenderableTextures()) {
2992 return false;
2993 }
2994 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:502995 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
2996 current_program_->sampler_indices();
2997 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
2998 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2999 current_program_->GetUniformInfo(sampler_indices[ii]);
3000 DCHECK(uniform_info);
3001 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
3002 GLuint texture_unit_index = uniform_info->texture_units[jj];
3003 if (texture_unit_index < group_->max_texture_units()) {
3004 TextureUnit& texture_unit = texture_units_[texture_unit_index];
3005 TextureManager::TextureInfo* texture_info =
3006 uniform_info->type == GL_SAMPLER_2D ?
3007 texture_unit.bound_texture_2d :
3008 texture_unit.bound_texture_cube_map;
3009 if (!texture_info || !texture_info->CanRender()) {
[email protected]ef526492010-06-02 23:12:253010 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:503011 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
3012 glBindTexture(
3013 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
3014 GL_TEXTURE_CUBE_MAP,
3015 uniform_info->type == GL_SAMPLER_2D ? black_2d_texture_id_ :
3016 black_cube_texture_id_);
3017 }
3018 }
3019 // else: should this be an error?
3020 }
3021 }
[email protected]ef526492010-06-02 23:12:253022 return textures_set;
[email protected]3916c97e2010-02-25 03:20:503023}
3024
3025void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
3026 DCHECK(current_program_);
3027 DCHECK(!current_program_->IsDeleted());
3028 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
3029 current_program_->sampler_indices();
3030 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
3031 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
3032 current_program_->GetUniformInfo(sampler_indices[ii]);
3033 DCHECK(uniform_info);
3034 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
3035 GLuint texture_unit_index = uniform_info->texture_units[jj];
3036 if (texture_unit_index < group_->max_texture_units()) {
3037 TextureUnit& texture_unit = texture_units_[texture_unit_index];
3038 TextureManager::TextureInfo* texture_info =
3039 uniform_info->type == GL_SAMPLER_2D ?
3040 texture_unit.bound_texture_2d :
3041 texture_unit.bound_texture_cube_map;
3042 if (!texture_info || !texture_info->CanRender()) {
3043 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
3044 // Get the texture info that was previously bound here.
3045 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
3046 texture_unit.bound_texture_2d :
3047 texture_unit.bound_texture_cube_map;
3048 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:033049 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:503050 }
3051 }
3052 }
3053 }
3054 // Set the active texture back to whatever the user had it as.
3055 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:303056}
3057
3058bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:033059 // NOTE: We specifically do not check current_program->IsValid() because
3060 // it could never be invalid since glUseProgram would have failed. While
3061 // glLinkProgram could later mark the program as invalid the previous
3062 // valid program will still function if it is still the current program.
3063 if (!current_program_ || current_program_->IsDeleted()) {
[email protected]3916c97e2010-02-25 03:20:503064 // The program does not exist.
3065 // But GL says no ERROR.
3066 return false;
3067 }
[email protected]f39f4b3f2010-05-12 17:04:083068 // Validate all attribs currently enabled. If they are used by the current
3069 // program then check that they have enough elements to handle the draw call.
3070 // If they are not used by the current program check that they have a buffer
3071 // assigned.
3072 const VertexAttribManager::VertexAttribInfoList& infos =
3073 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
3074 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
3075 infos.begin(); it != infos.end(); ++it) {
3076 const VertexAttribManager::VertexAttribInfo* info = *it;
3077 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
3078 current_program_->GetAttribInfoByLocation(info->index());
3079 if (attrib_info) {
3080 // This attrib is used in the current program.
3081 if (!info->CanAccess(max_vertex_accessed)) {
3082 SetGLError(GL_INVALID_OPERATION,
3083 "glDrawXXX: attempt to access out of range vertices");
3084 return false;
3085 }
3086 } else {
3087 // This attrib is not used in the current program.
3088 if (!info->buffer() || info->buffer()->IsDeleted()) {
3089 SetGLError(
3090 GL_INVALID_OPERATION,
3091 "glDrawXXX: attempt to render with no buffer attached to enabled "
3092 "attrib");
3093 return false;
3094 }
[email protected]1d32bc82010-01-13 22:06:463095 }
[email protected]07f54fcc2009-12-22 02:46:303096 }
[email protected]3916c97e2010-02-25 03:20:503097 return true;
[email protected]b1122982010-05-17 23:04:243098}
3099
3100bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
3101#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
3102 const VertexAttribManager::VertexAttribInfo* info =
3103 vertex_attrib_manager_.GetVertexAttribInfo(0);
3104 // If it's enabled or it's not used then we don't need to do anything.
3105 if (info->enabled() || !current_program_->GetAttribInfoByLocation(0)) {
3106 return false;
3107 }
3108
3109 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
3110
3111 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
3112
3113 // Make a buffer with a single repeated vec4 value enough to
3114 // simulate the constant value that is supposed to be here.
3115 // This is required to emulate GLES2 on GL.
3116 GLsizei num_vertices = max_vertex_accessed + 1;
3117 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
3118 if (size_needed > attrib_0_size_ ||
3119 info->value().v[0] != attrib_0_value_.v[0] ||
3120 info->value().v[1] != attrib_0_value_.v[1] ||
3121 info->value().v[2] != attrib_0_value_.v[2] ||
3122 info->value().v[3] != attrib_0_value_.v[3]) {
3123 scoped_array<Vec4> temp(new Vec4[num_vertices]);
3124 for (GLsizei ii = 0; ii < num_vertices; ++ii) {
3125 temp[ii] = info->value();
3126 }
3127 glBufferData(
3128 GL_ARRAY_BUFFER,
3129 size_needed,
3130 &temp[0].v[0],
3131 GL_DYNAMIC_DRAW);
3132 attrib_0_value_ = info->value();
3133 attrib_0_size_ = size_needed;
3134 }
3135
3136 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
3137
3138 return true;
3139#else // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
3140 return false;
3141#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
3142}
3143
3144void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
3145 const VertexAttribManager::VertexAttribInfo* info =
3146 vertex_attrib_manager_.GetVertexAttribInfo(0);
3147 const void* ptr = reinterpret_cast<const void*>(info->offset());
3148 BufferManager::BufferInfo* buffer_info = info->buffer();
3149 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
3150 glVertexAttribPointer(
3151 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
3152 ptr);
3153 glBindBuffer(GL_ARRAY_BUFFER,
3154 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
3155}
[email protected]07f54fcc2009-12-22 02:46:303156
[email protected]f7a64ee2010-02-01 22:24:143157error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:193158 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:503159 if (!bound_element_array_buffer_ ||
3160 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:293161 SetGLError(GL_INVALID_OPERATION,
3162 "glDrawElements: No element array buffer bound");
3163 return error::kNoError;
3164 }
3165
3166 GLenum mode = c.mode;
3167 GLsizei count = c.count;
3168 GLenum type = c.type;
3169 int32 offset = c.index_offset;
3170 if (count < 0) {
3171 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
3172 return error::kNoError;
3173 }
3174 if (offset < 0) {
3175 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
3176 return error::kNoError;
3177 }
[email protected]9438b012010-06-15 22:55:053178 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:293179 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
3180 return error::kNoError;
3181 }
[email protected]9438b012010-06-15 22:55:053182 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:293183 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
3184 return error::kNoError;
3185 }
3186
3187 GLuint max_vertex_accessed;
3188 if (!bound_element_array_buffer_->GetMaxValueForRange(
3189 offset, count, type, &max_vertex_accessed)) {
3190 SetGLError(GL_INVALID_OPERATION,
3191 "glDrawElements: range out of bounds for buffer");
3192 return error::kNoError;
3193 }
3194
3195 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:243196 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]ef526492010-06-02 23:12:253197 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]8eee29c2010-04-29 03:38:293198 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
3199 glDrawElements(mode, count, type, indices);
[email protected]ef526492010-06-02 23:12:253200 if (textures_set) {
[email protected]8eee29c2010-04-29 03:38:293201 RestoreStateForNonRenderableTextures();
[email protected]ba3176a2009-12-16 18:19:463202 }
[email protected]b1122982010-05-17 23:04:243203 if (simulated_attrib_0) {
3204 RestoreStateForSimulatedAttrib0();
3205 }
[email protected]96449d2c2009-11-25 00:01:323206 }
[email protected]f7a64ee2010-02-01 22:24:143207 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323208}
3209
[email protected]29a9eb52010-04-13 09:04:233210GLuint GLES2DecoderImpl::DoGetMaxValueInBuffer(
3211 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
3212 GLuint max_vertex_accessed = 0;
3213 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:293214 if (!info) {
[email protected]ae51d192010-04-27 00:48:033215 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:293216 SetGLError(GL_INVALID_VALUE,
3217 "GetMaxValueInBuffer: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:233218 } else {
3219 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:033220 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:293221 SetGLError(GL_INVALID_OPERATION,
3222 "GetMaxValueInBuffer: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:233223 }
3224 }
3225 return max_vertex_accessed;
3226}
3227
[email protected]96449d2c2009-11-25 00:01:323228// Calls glShaderSource for the various versions of the ShaderSource command.
3229// Assumes that data / data_size points to a piece of memory that is in range
3230// of whatever context it came from (shared memory, immediate memory, bucket
3231// memory.)
[email protected]45bf5152010-02-12 00:11:313232error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:033233 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:583234 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3235 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:313236 if (!info) {
[email protected]45bf5152010-02-12 00:11:313237 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323238 }
[email protected]45bf5152010-02-12 00:11:313239 // Note: We don't actually call glShaderSource here. We wait until
3240 // the call to glCompileShader.
3241 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:143242 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323243}
3244
[email protected]f7a64ee2010-02-01 22:24:143245error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:193246 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:323247 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:313248 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:323249 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:463250 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143251 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:323252 }
[email protected]ae51d192010-04-27 00:48:033253 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:323254}
3255
[email protected]f7a64ee2010-02-01 22:24:143256error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:193257 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:323258 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:313259 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:303260 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:463261 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:143262 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:323263 }
[email protected]ae51d192010-04-27 00:48:033264 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:313265}
3266
[email protected]558847a2010-03-24 07:02:543267error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
3268 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:543269 Bucket* bucket = GetBucket(c.data_bucket_id);
3270 if (!bucket || bucket->size() == 0) {
3271 return error::kInvalidArguments;
3272 }
3273 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:033274 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:543275 bucket->size() - 1);
3276}
3277
[email protected]ae51d192010-04-27 00:48:033278void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583279 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3280 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:313281 if (!info) {
[email protected]45bf5152010-02-12 00:11:313282 return;
3283 }
[email protected]de17df392010-04-23 21:09:413284 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
3285 // glShaderSource and then glCompileShader.
3286 const char* shader_src = info->source().c_str();
[email protected]de17df392010-04-23 21:09:413287#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER)
[email protected]8f1ccdac2010-05-19 21:01:483288 ShHandle compiler = 0;
[email protected]b1d2dcb2010-05-17 19:24:183289 if (use_shader_translator_) {
3290 int dbg_options = 0;
3291 EShLanguage language = info->shader_type() == GL_VERTEX_SHADER ?
3292 EShLangVertex : EShLangFragment;
3293 TBuiltInResource resources;
[email protected]b1d2dcb2010-05-17 19:24:183294 resources.maxVertexAttribs = group_->max_vertex_attribs();
[email protected]8f1ccdac2010-05-19 21:01:483295 resources.maxVertexUniformVectors =
3296 group_->max_vertex_uniform_vectors();
3297 resources.maxVaryingVectors = group_->max_varying_vectors();
3298 resources.maxVertexTextureImageUnits =
3299 group_->max_vertex_texture_image_units();
[email protected]b1d2dcb2010-05-17 19:24:183300 resources.maxCombinedTextureImageUnits = group_->max_texture_units();
[email protected]8f1ccdac2010-05-19 21:01:483301 resources.maxTextureImageUnits = group_->max_texture_image_units();
3302 resources.maxFragmentUniformVectors =
3303 group_->max_fragment_uniform_vectors();
[email protected]b1d2dcb2010-05-17 19:24:183304 resources.maxDrawBuffers = 1;
3305 compiler = ShConstructCompiler(language, dbg_options);
3306 if (!ShCompile(compiler, &shader_src, 1, EShOptNone, &resources,
3307 dbg_options)) {
[email protected]e5186162010-06-14 18:54:413308 info->SetStatus(false, ShGetInfoLog(compiler));
[email protected]b1d2dcb2010-05-17 19:24:183309 ShDestruct(compiler);
3310 return;
3311 }
3312 shader_src = ShGetObjectCode(compiler);
[email protected]de17df392010-04-23 21:09:413313 }
[email protected]de17df392010-04-23 21:09:413314#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
[email protected]de17df392010-04-23 21:09:413315
[email protected]ae51d192010-04-27 00:48:033316 glShaderSource(info->service_id(), 1, &shader_src, NULL);
3317 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:413318 GLint status = GL_FALSE;
3319 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
3320 if (status) {
3321 info->SetStatus(true, "");
3322 } else {
3323 GLint len = 0;
3324 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &len);
3325 scoped_array<char> temp(new char[len]);
3326 glGetShaderInfoLog(info->service_id(), len, &len, temp.get());
3327 info->SetStatus(false, std::string(temp.get(), len));
3328 }
[email protected]de17df392010-04-23 21:09:413329#ifdef GLES2_GPU_SERVICE_TRANSLATE_SHADER
[email protected]b1d2dcb2010-05-17 19:24:183330 if (use_shader_translator_) {
3331 ShDestruct(compiler);
3332 }
[email protected]de17df392010-04-23 21:09:413333#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER
[email protected]45bf5152010-02-12 00:11:313334};
3335
[email protected]ddd968b82010-03-02 00:44:293336void GLES2DecoderImpl::DoGetShaderiv(
3337 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583338 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3339 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:293340 if (!info) {
[email protected]ddd968b82010-03-02 00:44:293341 return;
3342 }
[email protected]8f1ccdac2010-05-19 21:01:483343 switch (pname) {
3344 case GL_SHADER_SOURCE_LENGTH:
3345 *params = info->source().size();
3346 return;
3347 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:413348 *params = info->IsValid();
3349 return;
[email protected]8f1ccdac2010-05-19 21:01:483350 case GL_INFO_LOG_LENGTH:
[email protected]e5186162010-06-14 18:54:413351 *params = info->log_info().size() + 1;
3352 return;
[email protected]8f1ccdac2010-05-19 21:01:483353 default:
3354 break;
[email protected]ddd968b82010-03-02 00:44:293355 }
[email protected]8f1ccdac2010-05-19 21:01:483356 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:293357}
3358
[email protected]ae51d192010-04-27 00:48:033359error::Error GLES2DecoderImpl::HandleGetShaderSource(
3360 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
3361 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:033362 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3363 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:583364 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3365 shader, "glGetShaderSource");
[email protected]8eee29c2010-04-29 03:38:293366 if (!info) {
3367 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:293368 return error::kNoError;
3369 }
[email protected]ae51d192010-04-27 00:48:033370 bucket->SetFromString(info->source());
3371 return error::kNoError;
3372}
3373
3374error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
3375 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
3376 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:583377 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3378 Bucket* bucket = CreateBucket(bucket_id);
3379 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3380 program, "glGetProgramInfoLog");
[email protected]ae51d192010-04-27 00:48:033381 if (!info) {
[email protected]ae51d192010-04-27 00:48:033382 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:313383 }
[email protected]e5186162010-06-14 18:54:413384 bucket->SetFromString(info->log_info());
[email protected]ae51d192010-04-27 00:48:033385 return error::kNoError;
3386}
3387
3388error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
3389 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
3390 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:583391 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
3392 Bucket* bucket = CreateBucket(bucket_id);
3393 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
3394 shader, "glGetShaderInfoLog");
[email protected]ae51d192010-04-27 00:48:033395 if (!info) {
[email protected]6b8cf1a2010-05-06 16:13:583396 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:033397 return error::kNoError;
3398 }
[email protected]e5186162010-06-14 18:54:413399 bucket->SetFromString(info->log_info());
[email protected]ae51d192010-04-27 00:48:033400 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323401}
3402
[email protected]1958e0e2010-04-22 05:17:153403bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033404 return GetBufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153405}
3406
3407bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033408 return GetFramebufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153409}
3410
3411bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033412 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153413}
3414
3415bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033416 return GetRenderbufferInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153417}
3418
3419bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033420 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:153421}
3422
3423bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033424 return GetTextureInfo(client_id) != NULL;
3425}
3426
3427void GLES2DecoderImpl::DoAttachShader(
3428 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583429 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
3430 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:033431 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:033432 return;
[email protected]1958e0e2010-04-22 05:17:153433 }
[email protected]6b8cf1a2010-05-06 16:13:583434 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
3435 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:033436 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:033437 return;
3438 }
[email protected]d81e8c52010-06-07 17:58:323439 program_info->AttachShader(shader_info);
[email protected]ae51d192010-04-27 00:48:033440 glAttachShader(program_info->service_id(), shader_info->service_id());
3441}
3442
3443void GLES2DecoderImpl::DoDetachShader(
3444 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583445 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
3446 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:033447 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:033448 return;
3449 }
[email protected]6b8cf1a2010-05-06 16:13:583450 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
3451 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:033452 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:033453 return;
3454 }
[email protected]d81e8c52010-06-07 17:58:323455 program_info->DetachShader(shader_info);
[email protected]ae51d192010-04-27 00:48:033456 glDetachShader(program_info->service_id(), shader_info->service_id());
3457}
3458
3459void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:583460 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3461 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:033462 if (!info) {
[email protected]ae51d192010-04-27 00:48:033463 return;
3464 }
[email protected]e5186162010-06-14 18:54:413465 if (!info->CanLink()) {
3466 info->set_log_info("Missing Shader");
3467 return;
3468 }
[email protected]ae51d192010-04-27 00:48:033469 glValidateProgram(info->service_id());
[email protected]e5186162010-06-14 18:54:413470 info->UpdateLogInfo();
[email protected]1958e0e2010-04-22 05:17:153471}
3472
[email protected]b1122982010-05-17 23:04:243473void GLES2DecoderImpl::DoGetVertexAttribfv(
3474 GLuint index, GLenum pname, GLfloat* params) {
3475 VertexAttribManager::VertexAttribInfo* info =
3476 vertex_attrib_manager_.GetVertexAttribInfo(index);
3477 if (!info) {
3478 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
3479 return;
3480 }
3481 switch (pname) {
3482 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
3483 BufferManager::BufferInfo* buffer = info->buffer();
3484 if (buffer && !buffer->IsDeleted()) {
3485 GLuint client_id;
3486 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
3487 *params = static_cast<GLfloat>(client_id);
3488 }
3489 break;
3490 }
3491 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3492 *params = static_cast<GLfloat>(info->enabled());
3493 break;
3494 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3495 *params = static_cast<GLfloat>(info->size());
3496 break;
3497 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3498 *params = static_cast<GLfloat>(info->gl_stride());
3499 break;
3500 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3501 *params = static_cast<GLfloat>(info->type());
3502 break;
3503 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3504 *params = static_cast<GLfloat>(info->normalized());
3505 break;
3506 case GL_CURRENT_VERTEX_ATTRIB:
3507 params[0] = info->value().v[0];
3508 params[1] = info->value().v[1];
3509 params[2] = info->value().v[2];
3510 params[3] = info->value().v[3];
3511 break;
3512 default:
3513 NOTREACHED();
3514 break;
3515 }
3516}
3517
3518void GLES2DecoderImpl::DoGetVertexAttribiv(
3519 GLuint index, GLenum pname, GLint* params) {
3520 VertexAttribManager::VertexAttribInfo* info =
3521 vertex_attrib_manager_.GetVertexAttribInfo(index);
3522 if (!info) {
3523 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
3524 return;
3525 }
3526 switch (pname) {
3527 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
3528 BufferManager::BufferInfo* buffer = info->buffer();
3529 if (buffer && !buffer->IsDeleted()) {
3530 GLuint client_id;
3531 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
3532 *params = client_id;
3533 }
3534 break;
3535 }
3536 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3537 *params = info->enabled();
3538 break;
3539 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3540 *params = info->size();
3541 break;
3542 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3543 *params = info->gl_stride();
3544 break;
3545 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3546 *params = info->type();
3547 break;
3548 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3549 *params = static_cast<GLint>(info->normalized());
3550 break;
3551 case GL_CURRENT_VERTEX_ATTRIB:
3552 params[0] = static_cast<GLint>(info->value().v[0]);
3553 params[1] = static_cast<GLint>(info->value().v[1]);
3554 params[2] = static_cast<GLint>(info->value().v[2]);
3555 params[3] = static_cast<GLint>(info->value().v[3]);
3556 break;
3557 default:
3558 NOTREACHED();
3559 break;
3560 }
3561}
3562
3563void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
3564 VertexAttribManager::VertexAttribInfo* info =
3565 vertex_attrib_manager_.GetVertexAttribInfo(index);
3566 if (!info) {
3567 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
3568 return;
3569 }
3570 VertexAttribManager::VertexAttribInfo::Vec4 value;
3571 value.v[0] = v0;
3572 value.v[1] = 0.0f;
3573 value.v[2] = 0.0f;
3574 value.v[3] = 1.0f;
3575 info->set_value(value);
3576 glVertexAttrib1f(index, v0);
3577}
3578
3579void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
3580 VertexAttribManager::VertexAttribInfo* info =
3581 vertex_attrib_manager_.GetVertexAttribInfo(index);
3582 if (!info) {
3583 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
3584 return;
3585 }
3586 VertexAttribManager::VertexAttribInfo::Vec4 value;
3587 value.v[0] = v0;
3588 value.v[1] = v1;
3589 value.v[2] = 0.0f;
3590 value.v[3] = 1.0f;
3591 info->set_value(value);
3592 glVertexAttrib2f(index, v0, v1);
3593}
3594
3595void GLES2DecoderImpl::DoVertexAttrib3f(
3596 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
3597 VertexAttribManager::VertexAttribInfo* info =
3598 vertex_attrib_manager_.GetVertexAttribInfo(index);
3599 if (!info) {
3600 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
3601 return;
3602 }
3603 VertexAttribManager::VertexAttribInfo::Vec4 value;
3604 value.v[0] = v0;
3605 value.v[1] = v1;
3606 value.v[2] = v2;
3607 value.v[3] = 1.0f;
3608 info->set_value(value);
3609 glVertexAttrib3f(index, v0, v1, v2);
3610}
3611
3612void GLES2DecoderImpl::DoVertexAttrib4f(
3613 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
3614 VertexAttribManager::VertexAttribInfo* info =
3615 vertex_attrib_manager_.GetVertexAttribInfo(index);
3616 if (!info) {
3617 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
3618 return;
3619 }
3620 VertexAttribManager::VertexAttribInfo::Vec4 value;
3621 value.v[0] = v0;
3622 value.v[1] = v1;
3623 value.v[2] = v2;
3624 value.v[3] = v3;
3625 info->set_value(value);
3626 glVertexAttrib4f(index, v0, v1, v2, v3);
3627}
3628
3629void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
3630 VertexAttribManager::VertexAttribInfo* info =
3631 vertex_attrib_manager_.GetVertexAttribInfo(index);
3632 if (!info) {
3633 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
3634 return;
3635 }
3636 VertexAttribManager::VertexAttribInfo::Vec4 value;
3637 value.v[0] = v[0];
3638 value.v[1] = 0.0f;
3639 value.v[2] = 0.0f;
3640 value.v[3] = 1.0f;
3641 info->set_value(value);
3642 glVertexAttrib1fv(index, v);
3643}
3644
3645void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
3646 VertexAttribManager::VertexAttribInfo* info =
3647 vertex_attrib_manager_.GetVertexAttribInfo(index);
3648 if (!info) {
3649 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
3650 return;
3651 }
3652 VertexAttribManager::VertexAttribInfo::Vec4 value;
3653 value.v[0] = v[0];
3654 value.v[1] = v[1];
3655 value.v[2] = 0.0f;
3656 value.v[3] = 1.0f;
3657 info->set_value(value);
3658 glVertexAttrib2fv(index, v);
3659}
3660
3661void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
3662 VertexAttribManager::VertexAttribInfo* info =
3663 vertex_attrib_manager_.GetVertexAttribInfo(index);
3664 if (!info) {
3665 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
3666 return;
3667 }
3668 VertexAttribManager::VertexAttribInfo::Vec4 value;
3669 value.v[0] = v[0];
3670 value.v[1] = v[1];
3671 value.v[2] = v[2];
3672 value.v[3] = 1.0f;
3673 info->set_value(value);
3674 glVertexAttrib3fv(index, v);
3675}
3676
3677void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
3678 VertexAttribManager::VertexAttribInfo* info =
3679 vertex_attrib_manager_.GetVertexAttribInfo(index);
3680 if (!info) {
3681 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
3682 return;
3683 }
3684 VertexAttribManager::VertexAttribInfo::Vec4 value;
3685 value.v[0] = v[0];
3686 value.v[1] = v[1];
3687 value.v[2] = v[2];
3688 value.v[3] = v[3];
3689 info->set_value(value);
3690 glVertexAttrib4fv(index, v);
3691}
3692
[email protected]f7a64ee2010-02-01 22:24:143693error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:193694 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:293695 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
3696 SetGLError(GL_INVALID_VALUE,
3697 "glVertexAttribPointer: no array buffer bound");
3698 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323699 }
[email protected]8eee29c2010-04-29 03:38:293700
3701 GLuint indx = c.indx;
3702 GLint size = c.size;
3703 GLenum type = c.type;
3704 GLboolean normalized = c.normalized;
3705 GLsizei stride = c.stride;
3706 GLsizei offset = c.offset;
3707 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:053708 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:293709 SetGLError(GL_INVALID_ENUM,
3710 "glVertexAttribPointer: type GL_INVALID_ENUM");
3711 return error::kNoError;
3712 }
[email protected]9438b012010-06-15 22:55:053713 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]8eee29c2010-04-29 03:38:293714 SetGLError(GL_INVALID_ENUM,
3715 "glVertexAttribPointer: size GL_INVALID_VALUE");
3716 return error::kNoError;
3717 }
3718 if (indx >= group_->max_vertex_attribs()) {
3719 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
3720 return error::kNoError;
3721 }
3722 if (stride < 0) {
3723 SetGLError(GL_INVALID_VALUE,
3724 "glVertexAttribPointer: stride < 0");
3725 return error::kNoError;
3726 }
3727 if (stride > 255) {
3728 SetGLError(GL_INVALID_VALUE,
3729 "glVertexAttribPointer: stride > 255");
3730 return error::kNoError;
3731 }
3732 if (offset < 0) {
3733 SetGLError(GL_INVALID_VALUE,
3734 "glVertexAttribPointer: offset < 0");
3735 return error::kNoError;
3736 }
3737 GLsizei component_size =
3738 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:293739 if (offset % component_size > 0) {
3740 SetGLError(GL_INVALID_VALUE,
3741 "glVertexAttribPointer: stride not valid for type");
3742 return error::kNoError;
3743 }
[email protected]f39f4b3f2010-05-12 17:04:083744 vertex_attrib_manager_.GetVertexAttribInfo(indx)->SetInfo(
[email protected]8eee29c2010-04-29 03:38:293745 bound_array_buffer_,
3746 size,
3747 type,
[email protected]b1122982010-05-17 23:04:243748 normalized,
3749 stride,
3750 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:293751 offset);
3752 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
[email protected]f7a64ee2010-02-01 22:24:143753 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323754}
3755
[email protected]f7a64ee2010-02-01 22:24:143756error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:193757 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:313758 GLint x = c.x;
3759 GLint y = c.y;
3760 GLsizei width = c.width;
3761 GLsizei height = c.height;
3762 GLenum format = c.format;
3763 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:563764 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:293765 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:563766 return error::kNoError;
3767 }
[email protected]a51788e2010-02-24 21:54:253768 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:183769 uint32 pixels_size;
3770 if (!GLES2Util::ComputeImageDataSize(
3771 width, height, format, type, pack_alignment_, &pixels_size)) {
3772 return error::kOutOfBounds;
3773 }
[email protected]612d2f82009-12-08 20:49:313774 void* pixels = GetSharedMemoryAs<void*>(
3775 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:253776 Result* result = GetSharedMemoryAs<Result*>(
3777 c.result_shm_id, c.result_shm_offset, sizeof(*result));
3778 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:143779 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:463780 }
[email protected]a51788e2010-02-24 21:54:253781
[email protected]9438b012010-06-15 22:55:053782 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:293783 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
3784 return error::kNoError;
3785 }
[email protected]9438b012010-06-15 22:55:053786 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:293787 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:123788 return error::kNoError;
3789 }
[email protected]57f223832010-03-19 01:57:563790 if (width == 0 || height == 0) {
3791 return error::kNoError;
3792 }
3793
3794 CopyRealGLErrorsToWrapper();
3795
3796 // Get the size of the current fbo or backbuffer.
[email protected]d37231fa2010-04-09 21:16:023797 gfx::Size max_size = GetBoundFrameBufferSize();
[email protected]57f223832010-03-19 01:57:563798
3799 GLint max_x;
3800 GLint max_y;
3801 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:293802 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:143803 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:313804 }
[email protected]57f223832010-03-19 01:57:563805
[email protected]d37231fa2010-04-09 21:16:023806 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:563807 // The user requested an out of range area. Get the results 1 line
3808 // at a time.
3809 uint32 temp_size;
3810 if (!GLES2Util::ComputeImageDataSize(
3811 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:293812 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563813 return error::kNoError;
3814 }
3815 GLsizei unpadded_row_size = temp_size;
3816 if (!GLES2Util::ComputeImageDataSize(
3817 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:293818 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563819 return error::kNoError;
3820 }
3821 GLsizei padded_row_size = temp_size - unpadded_row_size;
3822 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:293823 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563824 return error::kNoError;
3825 }
3826
3827 GLint dest_x_offset = std::max(-x, 0);
3828 uint32 dest_row_offset;
3829 if (!GLES2Util::ComputeImageDataSize(
3830 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:293831 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:563832 return error::kNoError;
3833 }
3834
3835 // Copy each row into the larger dest rect.
3836 int8* dst = static_cast<int8*>(pixels);
3837 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:023838 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:563839 GLint read_width = read_end_x - read_x;
3840 for (GLint yy = 0; yy < height; ++yy) {
3841 GLint ry = y + yy;
3842
3843 // Clear the row.
3844 memset(dst, 0, unpadded_row_size);
3845
3846 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:023847 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:563848 glReadPixels(
3849 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
3850 }
3851 dst += padded_row_size;
3852 }
3853 } else {
3854 glReadPixels(x, y, width, height, format, type, pixels);
3855 }
[email protected]a51788e2010-02-24 21:54:253856 GLenum error = glGetError();
3857 if (error == GL_NO_ERROR) {
3858 *result = true;
3859 } else {
[email protected]8eee29c2010-04-29 03:38:293860 SetGLError(error, NULL);
[email protected]a51788e2010-02-24 21:54:253861 }
[email protected]f7a64ee2010-02-01 22:24:143862 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323863}
3864
[email protected]f7a64ee2010-02-01 22:24:143865error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:193866 uint32 immediate_data_size, const gles2::PixelStorei& c) {
3867 GLenum pname = c.pname;
3868 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:053869 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:293870 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:123871 return error::kNoError;
3872 }
[email protected]9438b012010-06-15 22:55:053873 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:293874 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:143875 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193876 }
3877 glPixelStorei(pname, param);
3878 switch (pname) {
3879 case GL_PACK_ALIGNMENT:
3880 pack_alignment_ = param;
3881 break;
3882 case GL_UNPACK_ALIGNMENT:
3883 unpack_alignment_ = param;
3884 break;
3885 default:
3886 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:373887 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:193888 break;
3889 }
[email protected]f7a64ee2010-02-01 22:24:143890 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193891}
3892
[email protected]558847a2010-03-24 07:02:543893error::Error GLES2DecoderImpl::GetAttribLocationHelper(
3894 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
3895 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:583896 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3897 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:033898 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:143899 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193900 }
[email protected]ae51d192010-04-27 00:48:033901 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:293902 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:253903 return error::kNoError;
3904 }
[email protected]b9849abf2009-11-25 19:13:193905 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:543906 location_shm_id, location_shm_offset, sizeof(GLint));
3907 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:143908 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193909 }
[email protected]558847a2010-03-24 07:02:543910 // Require the client to init this incase the context is lost and we are no
3911 // longer executing commands.
3912 if (*location != -1) {
3913 return error::kGenericError;
3914 }
[email protected]0bfd9882010-02-05 23:02:253915 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:143916 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193917}
3918
[email protected]558847a2010-03-24 07:02:543919error::Error GLES2DecoderImpl::HandleGetAttribLocation(
3920 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
3921 uint32 name_size = c.data_size;
3922 const char* name = GetSharedMemoryAs<const char*>(
3923 c.name_shm_id, c.name_shm_offset, name_size);
3924 if (!name) {
3925 return error::kOutOfBounds;
3926 }
3927 String name_str(name, name_size);
3928 return GetAttribLocationHelper(
3929 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3930}
3931
[email protected]f7a64ee2010-02-01 22:24:143932error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:193933 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:543934 uint32 name_size = c.data_size;
3935 const char* name = GetImmediateDataAs<const char*>(
3936 c, name_size, immediate_data_size);
3937 if (!name) {
3938 return error::kOutOfBounds;
3939 }
3940 String name_str(name, name_size);
3941 return GetAttribLocationHelper(
3942 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3943}
3944
3945error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
3946 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
3947 Bucket* bucket = GetBucket(c.name_bucket_id);
3948 if (!bucket) {
3949 return error::kInvalidArguments;
3950 }
3951 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183952 if (!bucket->GetAsString(&name_str)) {
3953 return error::kInvalidArguments;
3954 }
[email protected]558847a2010-03-24 07:02:543955 return GetAttribLocationHelper(
3956 c.program, c.location_shm_id, c.location_shm_offset, name_str);
3957}
3958
3959error::Error GLES2DecoderImpl::GetUniformLocationHelper(
3960 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
3961 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:583962 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3963 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:033964 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:143965 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193966 }
[email protected]ae51d192010-04-27 00:48:033967 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:293968 SetGLError(GL_INVALID_OPERATION,
3969 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:253970 return error::kNoError;
3971 }
[email protected]b9849abf2009-11-25 19:13:193972 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:543973 location_shm_id, location_shm_offset, sizeof(GLint));
3974 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:143975 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193976 }
[email protected]558847a2010-03-24 07:02:543977 // Require the client to init this incase the context is lost an we are no
3978 // longer executing commands.
3979 if (*location != -1) {
3980 return error::kGenericError;
3981 }
3982 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:143983 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:193984}
3985
[email protected]f7a64ee2010-02-01 22:24:143986error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:193987 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:193988 uint32 name_size = c.data_size;
3989 const char* name = GetSharedMemoryAs<const char*>(
3990 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:543991 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:143992 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:193993 }
3994 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:543995 return GetUniformLocationHelper(
3996 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:193997}
3998
[email protected]f7a64ee2010-02-01 22:24:143999error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:194000 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:194001 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:304002 const char* name = GetImmediateDataAs<const char*>(
4003 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:544004 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:144005 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194006 }
4007 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:544008 return GetUniformLocationHelper(
4009 c.program, c.location_shm_id, c.location_shm_offset, name_str);
4010}
4011
4012error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
4013 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
4014 Bucket* bucket = GetBucket(c.name_bucket_id);
4015 if (!bucket) {
4016 return error::kInvalidArguments;
4017 }
4018 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184019 if (!bucket->GetAsString(&name_str)) {
4020 return error::kInvalidArguments;
4021 }
[email protected]558847a2010-03-24 07:02:544022 return GetUniformLocationHelper(
4023 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:194024}
4025
[email protected]ddd968b82010-03-02 00:44:294026error::Error GLES2DecoderImpl::HandleGetString(
4027 uint32 immediate_data_size, const gles2::GetString& c) {
4028 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:054029 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:294030 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:294031 return error::kNoError;
4032 }
[email protected]1958e0e2010-04-22 05:17:154033 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
4034 const char* str = NULL;
4035 switch (name) {
4036 case GL_VERSION:
4037 str = "OpenGL ES 2.0 Chromium";
4038 break;
4039 case GL_SHADING_LANGUAGE_VERSION:
4040 str = "OpenGL ES GLSL ES 1.0 Chromium";
4041 break;
4042 case GL_EXTENSIONS:
4043 str = "";
4044 break;
4045 default:
4046 str = gl_str;
4047 break;
4048 }
[email protected]ddd968b82010-03-02 00:44:294049 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:154050 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:294051 return error::kNoError;
4052}
4053
[email protected]0c86dbf2010-03-05 08:14:114054void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:154055 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:054056 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:294057 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
4058 return;
4059 }
[email protected]9438b012010-06-15 22:55:054060 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:294061 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:114062 return;
[email protected]3b6ec202010-03-05 05:16:234063 }
4064 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:294065 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:284066 return;
[email protected]3b6ec202010-03-05 05:16:234067 }
4068 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
4069 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294070 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:284071 return;
[email protected]3b6ec202010-03-05 05:16:234072 }
4073 // Clear the buffer to 0 if no initial data was passed in.
4074 scoped_array<int8> zero;
4075 if (!data) {
4076 zero.reset(new int8[size]);
4077 memset(zero.get(), 0, size);
4078 data = zero.get();
4079 }
4080 CopyRealGLErrorsToWrapper();
4081 glBufferData(target, size, data, usage);
4082 GLenum error = glGetError();
4083 if (error != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294084 SetGLError(error, NULL);
[email protected]3b6ec202010-03-05 05:16:234085 } else {
[email protected]4e8a5b122010-05-08 22:00:104086 buffer_manager()->SetSize(info, size);
[email protected]0c86dbf2010-03-05 08:14:114087 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:234088 }
[email protected]0c86dbf2010-03-05 08:14:114089}
4090
4091error::Error GLES2DecoderImpl::HandleBufferData(
4092 uint32 immediate_data_size, const gles2::BufferData& c) {
4093 GLenum target = static_cast<GLenum>(c.target);
4094 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
4095 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
4096 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
4097 GLenum usage = static_cast<GLenum>(c.usage);
4098 const void* data = NULL;
4099 if (data_shm_id != 0 || data_shm_offset != 0) {
4100 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
4101 if (!data) {
4102 return error::kOutOfBounds;
4103 }
4104 }
4105 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:144106 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194107}
4108
[email protected]f7a64ee2010-02-01 22:24:144109error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:194110 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
4111 GLenum target = static_cast<GLenum>(c.target);
4112 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:304113 const void* data = GetImmediateDataAs<const void*>(
4114 c, size, immediate_data_size);
4115 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144116 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:304117 }
[email protected]b9849abf2009-11-25 19:13:194118 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:114119 DoBufferData(target, size, data, usage);
4120 return error::kNoError;
4121}
4122
4123void GLES2DecoderImpl::DoBufferSubData(
4124 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:504125 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474126 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294127 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:284128 return;
[email protected]a93bb842010-02-16 23:03:474129 }
[email protected]0c86dbf2010-03-05 08:14:114130 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:294131 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]07f54fcc2009-12-22 02:46:304132 } else {
[email protected]0c86dbf2010-03-05 08:14:114133 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:304134 }
[email protected]b9849abf2009-11-25 19:13:194135}
4136
[email protected]a93bb842010-02-16 23:03:474137error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
4138 GLenum target,
4139 GLint level,
4140 GLenum internal_format,
4141 GLsizei width,
4142 GLsizei height,
4143 GLint border,
4144 GLsizei image_size,
4145 const void* data) {
[email protected]a93bb842010-02-16 23:03:474146 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:054147 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:294148 SetGLError(GL_INVALID_ENUM,
4149 "glCompressedTexImage2D: target GL_INVALID_ENUM");
4150 return error::kNoError;
4151 }
[email protected]9438b012010-06-15 22:55:054152 if (!validators_->compressed_texture_format.IsValid(
4153 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:294154 SetGLError(GL_INVALID_ENUM,
4155 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:474156 return error::kNoError;
4157 }
[email protected]3916c97e2010-02-25 03:20:504158 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:474159 border != 0) {
[email protected]8eee29c2010-04-29 03:38:294160 SetGLError(GL_INVALID_VALUE,
4161 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:474162 return error::kNoError;
4163 }
[email protected]3916c97e2010-02-25 03:20:504164 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474165 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294166 SetGLError(GL_INVALID_VALUE,
4167 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:474168 return error::kNoError;
4169 }
4170 scoped_array<int8> zero;
4171 if (!data) {
4172 zero.reset(new int8[image_size]);
4173 memset(zero.get(), 0, image_size);
4174 data = zero.get();
4175 }
[email protected]ef526492010-06-02 23:12:254176 texture_manager()->SetLevelInfo(
4177 info, target, level, internal_format, width, height, 1, border, 0, 0);
[email protected]a93bb842010-02-16 23:03:474178 glCompressedTexImage2D(
4179 target, level, internal_format, width, height, border, image_size, data);
4180 return error::kNoError;
4181}
4182
[email protected]f7a64ee2010-02-01 22:24:144183error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194184 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
4185 GLenum target = static_cast<GLenum>(c.target);
4186 GLint level = static_cast<GLint>(c.level);
4187 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4188 GLsizei width = static_cast<GLsizei>(c.width);
4189 GLsizei height = static_cast<GLsizei>(c.height);
4190 GLint border = static_cast<GLint>(c.border);
4191 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
4192 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
4193 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
4194 const void* data = NULL;
4195 if (data_shm_id != 0 || data_shm_offset != 0) {
4196 data = GetSharedMemoryAs<const void*>(
4197 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:464198 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144199 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194200 }
4201 }
[email protected]a93bb842010-02-16 23:03:474202 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194203 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:194204}
4205
[email protected]f7a64ee2010-02-01 22:24:144206error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:194207 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
4208 GLenum target = static_cast<GLenum>(c.target);
4209 GLint level = static_cast<GLint>(c.level);
4210 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4211 GLsizei width = static_cast<GLsizei>(c.width);
4212 GLsizei height = static_cast<GLsizei>(c.height);
4213 GLint border = static_cast<GLint>(c.border);
4214 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:304215 const void* data = GetImmediateDataAs<const void*>(
4216 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464217 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144218 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464219 }
[email protected]a93bb842010-02-16 23:03:474220 return DoCompressedTexImage2D(
4221 target, level, internal_format, width, height, border, image_size, data);
4222}
4223
[email protected]b6140d02010-05-17 14:47:164224error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
4225 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
4226 GLenum target = static_cast<GLenum>(c.target);
4227 GLint level = static_cast<GLint>(c.level);
4228 GLenum internal_format = static_cast<GLenum>(c.internalformat);
4229 GLsizei width = static_cast<GLsizei>(c.width);
4230 GLsizei height = static_cast<GLsizei>(c.height);
4231 GLint border = static_cast<GLint>(c.border);
4232 Bucket* bucket = GetBucket(c.bucket_id);
4233 return DoCompressedTexImage2D(
4234 target, level, internal_format, width, height, border,
4235 bucket->size(), bucket->GetData(0, bucket->size()));
4236}
4237
4238error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
4239 uint32 immediate_data_size,
4240 const gles2::CompressedTexSubImage2DBucket& c) {
4241 GLenum target = static_cast<GLenum>(c.target);
4242 GLint level = static_cast<GLint>(c.level);
4243 GLint xoffset = static_cast<GLint>(c.xoffset);
4244 GLint yoffset = static_cast<GLint>(c.yoffset);
4245 GLsizei width = static_cast<GLsizei>(c.width);
4246 GLsizei height = static_cast<GLsizei>(c.height);
4247 GLenum format = static_cast<GLenum>(c.format);
4248 Bucket* bucket = GetBucket(c.bucket_id);
4249 uint32 data_size = bucket->size();
4250 GLsizei imageSize = data_size;
4251 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:054252 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:164253 SetGLError(
4254 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
4255 return error::kNoError;
4256 }
[email protected]9438b012010-06-15 22:55:054257 if (!validators_->compressed_texture_format.IsValid(format)) {
4258 SetGLError(GL_INVALID_ENUM,
4259 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
4260 return error::kNoError;
4261 }
[email protected]b6140d02010-05-17 14:47:164262 if (width < 0) {
4263 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
4264 return error::kNoError;
4265 }
4266 if (height < 0) {
4267 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
4268 return error::kNoError;
4269 }
4270 if (imageSize < 0) {
4271 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
4272 return error::kNoError;
4273 }
4274 glCompressedTexSubImage2D(
4275 target, level, xoffset, yoffset, width, height, format, imageSize, data);
4276 return error::kNoError;
4277}
4278
[email protected]a93bb842010-02-16 23:03:474279error::Error GLES2DecoderImpl::DoTexImage2D(
4280 GLenum target,
4281 GLint level,
4282 GLenum internal_format,
4283 GLsizei width,
4284 GLsizei height,
4285 GLint border,
4286 GLenum format,
4287 GLenum type,
4288 const void* pixels,
4289 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:054290 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:294291 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
4292 return error::kNoError;
4293 }
[email protected]9438b012010-06-15 22:55:054294 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:294295 SetGLError(GL_INVALID_ENUM,
4296 "glTexImage2D: internal_format GL_INVALID_ENUM");
4297 return error::kNoError;
4298 }
[email protected]9438b012010-06-15 22:55:054299 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:294300 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
4301 return error::kNoError;
4302 }
[email protected]9438b012010-06-15 22:55:054303 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294304 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:144305 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194306 }
[email protected]3916c97e2010-02-25 03:20:504307 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:474308 border != 0) {
[email protected]8eee29c2010-04-29 03:38:294309 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:474310 return error::kNoError;
4311 }
[email protected]3916c97e2010-02-25 03:20:504312 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:474313 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294314 SetGLError(GL_INVALID_OPERATION,
4315 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:474316 return error::kNoError;
4317 }
4318 scoped_array<int8> zero;
4319 if (!pixels) {
4320 zero.reset(new int8[pixels_size]);
4321 memset(zero.get(), 0, pixels_size);
4322 pixels = zero.get();
4323 }
[email protected]ef526492010-06-02 23:12:254324 texture_manager()->SetLevelInfo(info,
[email protected]a93bb842010-02-16 23:03:474325 target, level, internal_format, width, height, 1, border, format, type);
4326 glTexImage2D(
4327 target, level, internal_format, width, height, border, format, type,
4328 pixels);
[email protected]f7a64ee2010-02-01 22:24:144329 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:194330}
4331
[email protected]f7a64ee2010-02-01 22:24:144332error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194333 uint32 immediate_data_size, const gles2::TexImage2D& c) {
4334 GLenum target = static_cast<GLenum>(c.target);
4335 GLint level = static_cast<GLint>(c.level);
4336 GLint internal_format = static_cast<GLint>(c.internalformat);
4337 GLsizei width = static_cast<GLsizei>(c.width);
4338 GLsizei height = static_cast<GLsizei>(c.height);
4339 GLint border = static_cast<GLint>(c.border);
4340 GLenum format = static_cast<GLenum>(c.format);
4341 GLenum type = static_cast<GLenum>(c.type);
4342 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
4343 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:184344 uint32 pixels_size;
4345 if (!GLES2Util::ComputeImageDataSize(
4346 width, height, format, type, unpack_alignment_, &pixels_size)) {
4347 return error::kOutOfBounds;
4348 }
[email protected]b9849abf2009-11-25 19:13:194349 const void* pixels = NULL;
4350 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
4351 pixels = GetSharedMemoryAs<const void*>(
4352 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:464353 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:144354 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:194355 }
4356 }
[email protected]a93bb842010-02-16 23:03:474357 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:194358 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:474359 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:194360}
4361
[email protected]f7a64ee2010-02-01 22:24:144362error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:194363 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
4364 GLenum target = static_cast<GLenum>(c.target);
4365 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:464366 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:194367 GLsizei width = static_cast<GLsizei>(c.width);
4368 GLsizei height = static_cast<GLsizei>(c.height);
4369 GLint border = static_cast<GLint>(c.border);
4370 GLenum format = static_cast<GLenum>(c.format);
4371 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:184372 uint32 size;
4373 if (!GLES2Util::ComputeImageDataSize(
4374 width, height, format, type, unpack_alignment_, &size)) {
4375 return error::kOutOfBounds;
4376 }
[email protected]07f54fcc2009-12-22 02:46:304377 const void* pixels = GetImmediateDataAs<const void*>(
4378 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464379 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:144380 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:464381 }
[email protected]a93bb842010-02-16 23:03:474382 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:464383 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:474384 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:144385 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324386}
4387
[email protected]f7a64ee2010-02-01 22:24:144388error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:194389 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:364390 GLuint index = static_cast<GLuint>(c.index);
4391 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:254392 typedef gles2::GetVertexAttribPointerv::Result Result;
4393 Result* result = GetSharedMemoryAs<Result*>(
4394 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:364395 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:144396 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:364397 }
[email protected]07d0cc82010-02-17 04:51:404398 // Check that the client initialized the result.
4399 if (result->size != 0) {
4400 return error::kInvalidArguments;
4401 }
[email protected]9438b012010-06-15 22:55:054402 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:294403 SetGLError(GL_INVALID_ENUM,
4404 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:144405 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:364406 }
[email protected]3916c97e2010-02-25 03:20:504407 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:294408 SetGLError(GL_INVALID_VALUE,
4409 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:144410 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:364411 }
[email protected]0bfd9882010-02-05 23:02:254412 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:084413 *result->GetData() =
4414 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:144415 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324416}
4417
[email protected]f7b85372010-02-03 01:11:374418bool GLES2DecoderImpl::GetUniformSetup(
4419 GLuint program, GLint location,
4420 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:104421 error::Error* error, GLuint* service_id, void** result_pointer,
4422 GLenum* result_type) {
4423 DCHECK(error);
4424 DCHECK(service_id);
4425 DCHECK(result_pointer);
4426 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:374427 *error = error::kNoError;
4428 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:254429 SizedResult<GLint>* result;
4430 result = GetSharedMemoryAs<SizedResult<GLint>*>(
4431 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
4432 if (!result) {
[email protected]f7b85372010-02-03 01:11:374433 *error = error::kOutOfBounds;
4434 return false;
4435 }
[email protected]0bfd9882010-02-05 23:02:254436 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:374437 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:254438 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:584439 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4440 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:374441 if (!info) {
[email protected]ae51d192010-04-27 00:48:034442 return false;
4443 }
4444 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:374445 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294446 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:374447 return false;
4448 }
[email protected]ae51d192010-04-27 00:48:034449 *service_id = info->service_id();
[email protected]0bfd9882010-02-05 23:02:254450 GLenum type;
4451 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:374452 // No such location.
[email protected]8eee29c2010-04-29 03:38:294453 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:374454 return false;
4455 }
[email protected]3916c97e2010-02-25 03:20:504456 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:374457 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:294458 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:374459 return false;
4460 }
[email protected]0bfd9882010-02-05 23:02:254461 result = GetSharedMemoryAs<SizedResult<GLint>*>(
4462 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
4463 if (!result) {
[email protected]f7b85372010-02-03 01:11:374464 *error = error::kOutOfBounds;
4465 return false;
4466 }
[email protected]0bfd9882010-02-05 23:02:254467 result->size = size;
[email protected]939e7362010-05-13 20:49:104468 *result_type = type;
[email protected]f7b85372010-02-03 01:11:374469 return true;
4470}
4471
[email protected]f7a64ee2010-02-01 22:24:144472error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:194473 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:374474 GLuint program = c.program;
4475 GLint location = c.location;
4476 GLuint service_id;
[email protected]939e7362010-05-13 20:49:104477 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:374478 Error error;
[email protected]0bfd9882010-02-05 23:02:254479 void* result;
[email protected]f7b85372010-02-03 01:11:374480 if (GetUniformSetup(
4481 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:104482 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:254483 glGetUniformiv(
4484 service_id, location,
4485 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:374486 }
4487 return error;
[email protected]96449d2c2009-11-25 00:01:324488}
4489
[email protected]f7a64ee2010-02-01 22:24:144490error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:194491 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:374492 GLuint program = c.program;
4493 GLint location = c.location;
4494 GLuint service_id;
4495 Error error;
[email protected]0bfd9882010-02-05 23:02:254496 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:104497 Result* result;
4498 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:374499 if (GetUniformSetup(
4500 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:104501 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
4502 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
4503 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
4504 GLsizei num_values = result->GetNumResults();
4505 scoped_array<GLint> temp(new GLint[num_values]);
4506 glGetUniformiv(service_id, location, temp.get());
4507 GLfloat* dst = result->GetData();
4508 for (GLsizei ii = 0; ii < num_values; ++ii) {
4509 dst[ii] = (temp[ii] != 0);
4510 }
4511 } else {
4512 glGetUniformfv(service_id, location, result->GetData());
4513 }
[email protected]f7b85372010-02-03 01:11:374514 }
4515 return error;
[email protected]96449d2c2009-11-25 00:01:324516}
4517
[email protected]f7a64ee2010-02-01 22:24:144518error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:194519 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:254520 GLenum shader_type = static_cast<GLenum>(c.shadertype);
4521 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
4522 typedef gles2::GetShaderPrecisionFormat::Result Result;
4523 Result* result = GetSharedMemoryAs<Result*>(
4524 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4525 if (!result) {
4526 return error::kOutOfBounds;
4527 }
[email protected]07d0cc82010-02-17 04:51:404528 // Check that the client initialized the result.
4529 if (result->success != 0) {
4530 return error::kInvalidArguments;
4531 }
[email protected]9438b012010-06-15 22:55:054532 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:294533 SetGLError(GL_INVALID_ENUM,
4534 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
4535 return error::kNoError;
4536 }
[email protected]9438b012010-06-15 22:55:054537 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:294538 SetGLError(GL_INVALID_ENUM,
4539 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
4540 return error::kNoError;
4541 }
4542
4543 result->success = 1; // true
4544 switch (precision_type) {
4545 case GL_LOW_INT:
4546 case GL_MEDIUM_INT:
4547 case GL_HIGH_INT:
4548 result->min_range = -31;
4549 result->max_range = 31;
4550 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:104551 break;
[email protected]8eee29c2010-04-29 03:38:294552 case GL_LOW_FLOAT:
4553 case GL_MEDIUM_FLOAT:
4554 case GL_HIGH_FLOAT:
4555 result->min_range = -62;
4556 result->max_range = 62;
4557 result->precision = -16;
4558 break;
4559 default:
4560 NOTREACHED();
4561 break;
[email protected]0bfd9882010-02-05 23:02:254562 }
[email protected]f7a64ee2010-02-01 22:24:144563 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324564}
4565
[email protected]f7a64ee2010-02-01 22:24:144566error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:194567 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:254568 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:584569 GLuint program = static_cast<GLuint>(c.program);
4570 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4571 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:034572 if (!info) {
[email protected]0bfd9882010-02-05 23:02:254573 return error::kNoError;
4574 }
4575 typedef gles2::GetAttachedShaders::Result Result;
4576 uint32 max_count = Result::ComputeMaxResults(result_size);
4577 Result* result = GetSharedMemoryAs<Result*>(
4578 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
4579 if (!result) {
4580 return error::kOutOfBounds;
4581 }
[email protected]07d0cc82010-02-17 04:51:404582 // Check that the client initialized the result.
4583 if (result->size != 0) {
4584 return error::kInvalidArguments;
4585 }
[email protected]0bfd9882010-02-05 23:02:254586 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:034587 glGetAttachedShaders(
4588 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:254589 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:034590 if (!shader_manager()->GetClientId(result->GetData()[ii],
4591 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:254592 NOTREACHED();
4593 return error::kGenericError;
4594 }
4595 }
4596 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:144597 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324598}
4599
[email protected]f7a64ee2010-02-01 22:24:144600error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:194601 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:254602 GLuint program = c.program;
4603 GLuint index = c.index;
4604 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:254605 typedef gles2::GetActiveUniform::Result Result;
4606 Result* result = GetSharedMemoryAs<Result*>(
4607 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4608 if (!result) {
4609 return error::kOutOfBounds;
4610 }
[email protected]07d0cc82010-02-17 04:51:404611 // Check that the client initialized the result.
4612 if (result->success != 0) {
4613 return error::kInvalidArguments;
4614 }
[email protected]6b8cf1a2010-05-06 16:13:584615 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4616 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:034617 if (!info) {
[email protected]0bfd9882010-02-05 23:02:254618 return error::kNoError;
4619 }
4620 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4621 info->GetUniformInfo(index);
4622 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:294623 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:254624 return error::kNoError;
4625 }
4626 result->success = 1; // true.
4627 result->size = uniform_info->size;
4628 result->type = uniform_info->type;
4629 Bucket* bucket = CreateBucket(name_bucket_id);
4630 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:144631 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324632}
4633
[email protected]f7a64ee2010-02-01 22:24:144634error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:194635 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:254636 GLuint program = c.program;
4637 GLuint index = c.index;
4638 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:254639 typedef gles2::GetActiveAttrib::Result Result;
4640 Result* result = GetSharedMemoryAs<Result*>(
4641 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4642 if (!result) {
4643 return error::kOutOfBounds;
4644 }
[email protected]07d0cc82010-02-17 04:51:404645 // Check that the client initialized the result.
4646 if (result->success != 0) {
4647 return error::kInvalidArguments;
4648 }
[email protected]6b8cf1a2010-05-06 16:13:584649 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4650 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:034651 if (!info) {
[email protected]0bfd9882010-02-05 23:02:254652 return error::kNoError;
4653 }
4654 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4655 info->GetAttribInfo(index);
4656 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:294657 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:254658 return error::kNoError;
4659 }
4660 result->success = 1; // true.
4661 result->size = attrib_info->size;
4662 result->type = attrib_info->type;
4663 Bucket* bucket = CreateBucket(name_bucket_id);
4664 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:144665 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324666}
4667
[email protected]b273e432010-04-12 17:23:584668error::Error GLES2DecoderImpl::HandleShaderBinary(
4669 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
4670#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:294671 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:584672 return error::kNoError;
4673#else
4674 GLsizei n = static_cast<GLsizei>(c.n);
4675 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:294676 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:584677 return error::kNoError;
4678 }
4679 GLsizei length = static_cast<GLsizei>(c.length);
4680 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:294681 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:584682 return error::kNoError;
4683 }
4684 uint32 data_size;
4685 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4686 return error::kOutOfBounds;
4687 }
4688 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
4689 c.shaders_shm_id, c.shaders_shm_offset, data_size);
4690 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
4691 const void* binary = GetSharedMemoryAs<const void*>(
4692 c.binary_shm_id, c.binary_shm_offset, length);
4693 if (shaders == NULL || binary == NULL) {
4694 return error::kOutOfBounds;
4695 }
4696 scoped_array<GLuint> service_ids(new GLuint[n]);
4697 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:034698 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
4699 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294700 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:584701 return error::kNoError;
4702 }
[email protected]ae51d192010-04-27 00:48:034703 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:584704 }
4705 // TODO(gman): call glShaderBinary
4706 return error::kNoError;
4707#endif
4708}
4709
[email protected]6217d392010-03-25 22:08:354710error::Error GLES2DecoderImpl::HandleSwapBuffers(
4711 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]6217d392010-03-25 22:08:354712 // If offscreen then don't actually SwapBuffers to the display. Just copy
4713 // the rendered frame to another frame buffer.
4714 if (offscreen_target_frame_buffer_.get()) {
4715 ScopedGLErrorSuppressor suppressor(this);
4716
4717 // First check to see if a deferred offscreen render buffer resize is
4718 // pending.
4719 if (!UpdateOffscreenFrameBufferSize())
4720 return error::kLostContext;
4721
[email protected]0c8c9d22010-06-25 17:36:394722 if (parent_) {
4723 ScopedFrameBufferBinder binder(this,
4724 offscreen_target_frame_buffer_->id());
4725 offscreen_saved_color_texture_->Copy(
4726 offscreen_saved_color_texture_->size());
4727 }
[email protected]6217d392010-03-25 22:08:354728 } else {
[email protected]d37231fa2010-04-09 21:16:024729 context_->SwapBuffers();
[email protected]6217d392010-03-25 22:08:354730 }
4731
[email protected]7d9ce4f2010-04-14 18:39:404732 // TODO(kbr): when the back buffer is multisampled, then at least on Mac
4733 // OS X (and probably on all platforms, for best semantics), we will need
4734 // to perform the resolve step and bind the offscreen_saved_color_texture_
4735 // as the color attachment before calling the swap buffers callback, which
4736 // expects a normal (non-multisampled) frame buffer for glCopyTexImage2D /
4737 // glReadPixels. After the callback runs, the multisampled frame buffer
4738 // needs to be bound again.
4739
[email protected]6217d392010-03-25 22:08:354740 if (swap_buffers_callback_.get()) {
4741 swap_buffers_callback_->Run();
4742 }
4743
4744 return error::kNoError;
4745}
4746
[email protected]b1d2dcb2010-05-17 19:24:184747error::Error GLES2DecoderImpl::HandleCommandBufferEnable(
4748 uint32 immediate_data_size, const gles2::CommandBufferEnable& c) {
4749 Bucket* bucket = GetBucket(c.bucket_id);
4750 typedef gles2::CommandBufferEnable::Result Result;
4751 Result* result = GetSharedMemoryAs<Result*>(
4752 c.result_shm_id, c.result_shm_offset, sizeof(*result));
4753 if (!result) {
4754 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:104755 }
[email protected]b1d2dcb2010-05-17 19:24:184756 // Check that the client initialized the result.
4757 if (*result != 0) {
4758 return error::kInvalidArguments;
4759 }
4760 std::string feature_str;
4761 if (!bucket->GetAsString(&feature_str)) {
4762 return error::kInvalidArguments;
4763 }
4764
4765 // TODO(gman): make this some kind of table to function pointer thingy.
4766 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
4767 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
4768 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
4769 use_shader_translator_ = false;
4770 } else {
4771 return error::kNoError;
4772 }
4773
4774 *result = 1; // true.
4775 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:104776}
4777
[email protected]96449d2c2009-11-25 00:01:324778// Include the auto-generated part of this file. We split this because it means
4779// we can easily edit the non-auto generated parts right here in this file
4780// instead of having to edit some template or the code generator.
4781#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
4782
4783} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:254784} // namespace gpu