blob: 4c99bfff396108799a98b3f2899396281d48cb60 [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]96449d2c2009-11-25 00:01:3210#include <vector>
11#include <string>
12#include <map>
[email protected]0bfd9882010-02-05 23:02:2513#include <build/build_config.h> // NOLINT
[email protected]2041cf342010-02-19 03:15:5914#include "base/callback.h"
[email protected]a93bb842010-02-16 23:03:4715#include "base/linked_ptr.h"
[email protected]96449d2c2009-11-25 00:01:3216#include "base/scoped_ptr.h"
17#define GLES2_GPU_SERVICE 1
18#include "gpu/command_buffer/common/gles2_cmd_format.h"
19#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]3916c97e2010-02-25 03:20:5020#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3221#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5022#include "gpu/command_buffer/service/context_group.h"
[email protected]96449d2c2009-11-25 00:01:3223#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4624#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4725#include "gpu/command_buffer/service/id_manager.h"
26#include "gpu/command_buffer/service/program_manager.h"
27#include "gpu/command_buffer/service/shader_manager.h"
28#include "gpu/command_buffer/service/texture_manager.h"
[email protected]43f28f832010-02-03 02:28:4829#if defined(UNIT_TEST)
30#elif defined(OS_LINUX)
[email protected]872fe722010-02-02 16:03:3331// XWindowWrapper is stubbed out for unit-tests.
[email protected]be4f1882010-01-06 04:38:5532#include "gpu/command_buffer/service/x_utils.h"
[email protected]43f28f832010-02-03 02:28:4833#elif defined(OS_MACOSX)
[email protected]6c077af2010-03-19 14:01:3334#include "app/surface/accelerated_surface_mac.h"
[email protected]be4f1882010-01-06 04:38:5535#endif
[email protected]96449d2c2009-11-25 00:01:3236
[email protected]a7a27ace2009-12-12 00:11:2537namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3238namespace gles2 {
39
[email protected]07f54fcc2009-12-22 02:46:3040// Check that certain assumptions the code makes are true. There are places in
41// the code where shared memory is passed direclty to GL. Example, glUniformiv,
42// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
43// a few others) are 32bits. If they are not 32bits the code will have to change
44// to call those GL functions with service side memory and then copy the results
45// to shared memory, converting the sizes.
46COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
47 GLint_not_same_size_as_uint32);
48COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
49 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3750COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
51 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3052
[email protected]43f28f832010-02-03 02:28:4853// TODO(kbr): the use of this anonymous namespace core dumps the
54// linker on Mac OS X 10.6 when the symbol ordering file is used
55// namespace {
[email protected]96449d2c2009-11-25 00:01:3256
57// Returns the address of the first byte after a struct.
58template <typename T>
59const void* AddressAfterStruct(const T& pod) {
60 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
61}
62
[email protected]07f54fcc2009-12-22 02:46:3063// Returns the address of the frst byte after the struct or NULL if size >
64// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3265template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3066RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
67 uint32 size,
68 uint32 immediate_data_size) {
69 return (size <= immediate_data_size) ?
70 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
71 NULL;
[email protected]96449d2c2009-11-25 00:01:3272}
73
[email protected]07f54fcc2009-12-22 02:46:3074// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1875bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3276 GLuint count,
77 size_t size,
[email protected]a76b0052010-03-05 00:33:1878 unsigned int elements_per_unit,
79 uint32* dst) {
80 uint32 value;
81 if (!SafeMultiplyUint32(count, size, &value)) {
82 return false;
83 }
84 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
85 return false;
86 }
87 *dst = value;
88 return true;
[email protected]96449d2c2009-11-25 00:01:3289}
90
91// A struct to hold info about each command.
92struct CommandInfo {
93 int arg_flags; // How to handle the arguments for this command
94 int arg_count; // How many arguments are expected for this command.
95};
96
97// A table of CommandInfo for all the commands.
98const CommandInfo g_command_info[] = {
99 #define GLES2_CMD_OP(name) { \
100 name::kArgFlags, \
101 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
102
103 GLES2_COMMAND_LIST(GLES2_CMD_OP)
104
105 #undef GLES2_CMD_OP
106};
107
[email protected]43f28f832010-02-03 02:28:48108// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32109
[email protected]3916c97e2010-02-25 03:20:50110GLES2Decoder::GLES2Decoder(ContextGroup* group)
111 : group_(group),
[email protected]69d80ae2009-12-23 08:57:42112#if defined(UNIT_TEST)
[email protected]3916c97e2010-02-25 03:20:50113 debug_(false) {
[email protected]69d80ae2009-12-23 08:57:42114#elif defined(OS_LINUX)
[email protected]3916c97e2010-02-25 03:20:50115 debug_(false),
[email protected]b9849abf2009-11-25 19:13:19116 window_(NULL) {
117#elif defined(OS_WIN)
[email protected]3916c97e2010-02-25 03:20:50118 debug_(false),
[email protected]b9849abf2009-11-25 19:13:19119 hwnd_(NULL) {
120#else
[email protected]3916c97e2010-02-25 03:20:50121 debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32122#endif
123}
124
[email protected]3916c97e2010-02-25 03:20:50125GLES2Decoder::~GLES2Decoder() {
126}
127
[email protected]96449d2c2009-11-25 00:01:32128// This class implements GLES2Decoder so we don't have to expose all the GLES2
129// cmd stuff to outside this class.
130class GLES2DecoderImpl : public GLES2Decoder {
131 public:
[email protected]3916c97e2010-02-25 03:20:50132 explicit GLES2DecoderImpl(ContextGroup* group);
133
[email protected]07f54fcc2009-12-22 02:46:30134 // Info about Vertex Attributes. This is used to track what the user currently
135 // has bound on each Vertex Attribute so that checking can be done at
136 // glDrawXXX time.
137 class VertexAttribInfo {
138 public:
139 VertexAttribInfo()
140 : enabled_(false),
141 size_(0),
142 type_(0),
143 offset_(0),
[email protected]3916c97e2010-02-25 03:20:50144 real_stride_(0) {
[email protected]07f54fcc2009-12-22 02:46:30145 }
[email protected]3916c97e2010-02-25 03:20:50146
[email protected]07f54fcc2009-12-22 02:46:30147 // Returns true if this VertexAttrib can access index.
148 bool CanAccess(GLuint index);
149
150 void set_enabled(bool enabled) {
151 enabled_ = enabled;
152 }
153
[email protected]3916c97e2010-02-25 03:20:50154 BufferManager::BufferInfo* buffer() const {
[email protected]07f54fcc2009-12-22 02:46:30155 return buffer_;
156 }
157
[email protected]8bf5a3e2010-01-29 04:21:36158 GLsizei offset() const {
159 return offset_;
160 }
161
[email protected]07f54fcc2009-12-22 02:46:30162 void SetInfo(
[email protected]3916c97e2010-02-25 03:20:50163 BufferManager::BufferInfo* buffer,
[email protected]07f54fcc2009-12-22 02:46:30164 GLint size,
165 GLenum type,
166 GLsizei real_stride,
167 GLsizei offset) {
[email protected]8a837bb2010-01-05 00:21:24168 DCHECK_GT(real_stride, 0);
[email protected]07f54fcc2009-12-22 02:46:30169 buffer_ = buffer;
170 size_ = size;
171 type_ = type;
172 real_stride_ = real_stride;
173 offset_ = offset;
[email protected]3916c97e2010-02-25 03:20:50174 }
175
176 void ClearBuffer() {
177 buffer_ = NULL;
[email protected]07f54fcc2009-12-22 02:46:30178 }
179
180 private:
181 // Whether or not this attribute is enabled.
182 bool enabled_;
183
184 // number of components (1, 2, 3, 4)
185 GLint size_;
186
187 // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer.
188 GLenum type_;
189
190 // The offset into the buffer.
191 GLsizei offset_;
192
193 // The stride that will be used to access the buffer. This is the actual
194 // stide, NOT the GL bogus stride. In other words there is never a stride
195 // of 0.
196 GLsizei real_stride_;
197
[email protected]3916c97e2010-02-25 03:20:50198 // The buffer bound to this attribute.
199 BufferManager::BufferInfo::Ref buffer_;
[email protected]07f54fcc2009-12-22 02:46:30200 };
201
[email protected]96449d2c2009-11-25 00:01:32202 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14203 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50204 unsigned int arg_count,
205 const void* args);
[email protected]96449d2c2009-11-25 00:01:32206
207 // Overridden from AsyncAPIInterface.
208 virtual const char* GetCommandName(unsigned int command_id) const;
209
210 // Overridden from GLES2Decoder.
211 virtual bool Initialize();
[email protected]96449d2c2009-11-25 00:01:32212 virtual void Destroy();
[email protected]eb54a562010-01-20 21:55:18213 virtual bool MakeCurrent();
[email protected]8a837bb2010-01-05 00:21:24214 virtual uint32 GetServiceIdForTesting(uint32 client_id);
[email protected]56ac89b2010-03-17 21:16:55215 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]8a837bb2010-01-05 00:21:24216
[email protected]6098b712010-02-09 17:59:34217#if defined(OS_MACOSX)
[email protected]43f28f832010-02-03 02:28:48218 // Overridden from GLES2Decoder.
[email protected]1aef98132010-02-23 18:00:07219
220 // The recommended usage is to call SetWindowSizeForIOSurface() first, and if
221 // that returns 0, try calling SetWindowSizeForTransportDIB(). A return value
222 // of 0 from SetWindowSizeForIOSurface() might mean the IOSurface API is not
223 // available, which is true if you are not running on Max OS X 10.6 or later.
224 // If SetWindowSizeForTransportDIB() also returns a NULL handle, then an
225 // error has occured.
226 virtual uint64 SetWindowSizeForIOSurface(int32 width, int32 height);
227 virtual TransportDIB::Handle SetWindowSizeForTransportDIB(int32 width,
228 int32 height);
229 // |allocator| sends a message to the renderer asking for a new
230 // TransportDIB big enough to hold the rendered bits. The parameters to the
231 // call back are the size of the DIB and the handle (filled in on return).
232 virtual void SetTransportDIBAllocAndFree(
233 Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
234 Callback1<TransportDIB::Id>::Type* deallocator);
[email protected]43f28f832010-02-03 02:28:48235#endif
236
237 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
238
[email protected]96449d2c2009-11-25 00:01:32239 private:
[email protected]3916c97e2010-02-25 03:20:50240 // State associated with each texture unit.
241 struct TextureUnit {
242 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
243
244 // The last target that was bound to this texture unit.
245 GLenum bind_target;
246
247 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
248 TextureManager::TextureInfo::Ref bound_texture_2d;
249
250 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
251 // glBindTexture
252 TextureManager::TextureInfo::Ref bound_texture_cube_map;
253 };
254
[email protected]a93bb842010-02-16 23:03:47255 friend void GLGenTexturesHelper(
256 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
257 friend void GLDeleteTexturesHelper(
258 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
259 friend void GLGenBuffersHelper(
260 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
261 friend void GLDeleteBuffersHelper(
262 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids);
263
[email protected]3916c97e2010-02-25 03:20:50264 // TODO(gman): Cache these pointers?
265 IdManager* id_manager() {
266 return group_->id_manager();
267 }
268
269 BufferManager* buffer_manager() {
270 return group_->buffer_manager();
271 }
272
273 ProgramManager* program_manager() {
274 return group_->program_manager();
275 }
276
277 ShaderManager* shader_manager() {
278 return group_->shader_manager();
279 }
280
281 TextureManager* texture_manager() {
282 return group_->texture_manager();
283 }
284
[email protected]246a70452010-03-05 21:53:50285#if defined(OS_WIN)
286 static bool InitializeOneOff(bool anti_aliased);
287#endif
288
289
[email protected]96449d2c2009-11-25 00:01:32290 bool InitPlatformSpecific();
[email protected]246a70452010-03-05 21:53:50291 static bool InitGlew();
292 void DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:32293
[email protected]96449d2c2009-11-25 00:01:32294 // Template to help call glGenXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30295 template <void gl_gen_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32296 bool GenGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12297 DCHECK_GE(n, 0);
[email protected]8a837bb2010-01-05 00:21:24298 if (!ValidateIdsAreUnused(n, client_ids)) {
299 return false;
300 }
[email protected]96449d2c2009-11-25 00:01:32301 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30302 gl_gen_function(this, n, temp.get());
[email protected]07f54fcc2009-12-22 02:46:30303 return RegisterObjects(n, client_ids, temp.get());
[email protected]96449d2c2009-11-25 00:01:32304 }
305
306 // Template to help call glDeleteXXX functions.
[email protected]07f54fcc2009-12-22 02:46:30307 template <void gl_delete_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
[email protected]96449d2c2009-11-25 00:01:32308 bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) {
[email protected]d2cf0a2d2010-02-25 21:36:12309 DCHECK_GE(n, 0);
[email protected]96449d2c2009-11-25 00:01:32310 scoped_array<GLuint>temp(new GLuint[n]);
[email protected]07f54fcc2009-12-22 02:46:30311 UnregisterObjects(n, client_ids, temp.get());
312 gl_delete_function(this, n, temp.get());
[email protected]96449d2c2009-11-25 00:01:32313 return true;
314 }
315
[email protected]8a837bb2010-01-05 00:21:24316 // Check that the given ids are not used.
317 bool ValidateIdsAreUnused(GLsizei n, const GLuint* client_ids);
318
[email protected]07f54fcc2009-12-22 02:46:30319 // Register client ids with generated service ids.
320 bool RegisterObjects(
321 GLsizei n, const GLuint* client_ids, const GLuint* service_ids);
322
323 // Unregisters client ids with service ids.
324 void UnregisterObjects(
325 GLsizei n, const GLuint* client_ids, GLuint* service_ids);
326
[email protected]a93bb842010-02-16 23:03:47327 // Creates a TextureInfo for the given texture.
328 void CreateTextureInfo(GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:50329 texture_manager()->CreateTextureInfo(texture);
[email protected]a93bb842010-02-16 23:03:47330 }
331
332 // Gets the texture info for the given texture. Returns NULL if none exists.
333 TextureManager::TextureInfo* GetTextureInfo(GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:50334 TextureManager::TextureInfo* info =
335 texture_manager()->GetTextureInfo(texture);
336 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47337 }
338
339 // Deletes the texture info for the given texture.
[email protected]3916c97e2010-02-25 03:20:50340 void RemoveTextureInfo(GLuint texture) {
341 texture_manager()->RemoveTextureInfo(texture);
342 }
[email protected]a93bb842010-02-16 23:03:47343
344 // Wrapper for CompressedTexImage2D commands.
345 error::Error DoCompressedTexImage2D(
346 GLenum target,
347 GLint level,
348 GLenum internal_format,
349 GLsizei width,
350 GLsizei height,
351 GLint border,
352 GLsizei image_size,
353 const void* data);
354
355 // Wrapper for TexImage2D commands.
356 error::Error DoTexImage2D(
357 GLenum target,
358 GLint level,
359 GLenum internal_format,
360 GLsizei width,
361 GLsizei height,
362 GLint border,
363 GLenum format,
364 GLenum type,
365 const void* pixels,
366 uint32 pixels_size);
367
368 // Creates a ProgramInfo for the given program.
369 void CreateProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50370 program_manager()->CreateProgramInfo(program);
[email protected]a93bb842010-02-16 23:03:47371 }
372
[email protected]07f54fcc2009-12-22 02:46:30373 // Gets the program info for the given program. Returns NULL if none exists.
374 // Programs that have no had glLinkProgram succesfully called on them will
375 // not exist.
[email protected]1d32bc82010-01-13 22:06:46376 ProgramManager::ProgramInfo* GetProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50377 ProgramManager::ProgramInfo* info =
378 program_manager()->GetProgramInfo(program);
379 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46380 }
[email protected]07f54fcc2009-12-22 02:46:30381
[email protected]07f54fcc2009-12-22 02:46:30382 // Deletes the program info for the given program.
[email protected]1d32bc82010-01-13 22:06:46383 void RemoveProgramInfo(GLuint program) {
[email protected]3916c97e2010-02-25 03:20:50384 program_manager()->RemoveProgramInfo(program);
[email protected]1d32bc82010-01-13 22:06:46385 }
[email protected]07f54fcc2009-12-22 02:46:30386
[email protected]45bf5152010-02-12 00:11:31387 // Creates a ShaderInfo for the given shader.
388 void CreateShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50389 shader_manager()->CreateShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31390 }
391
392 // Gets the shader info for the given shader. Returns NULL if none exists.
393 ShaderManager::ShaderInfo* GetShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50394 ShaderManager::ShaderInfo* info = shader_manager()->GetShaderInfo(shader);
395 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]45bf5152010-02-12 00:11:31396 }
397
398 // Deletes the shader info for the given shader.
399 void RemoveShaderInfo(GLuint shader) {
[email protected]3916c97e2010-02-25 03:20:50400 shader_manager()->RemoveShaderInfo(shader);
[email protected]45bf5152010-02-12 00:11:31401 }
402
[email protected]a93bb842010-02-16 23:03:47403 // Creates a buffer info for the given buffer.
404 void CreateBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50405 return buffer_manager()->CreateBufferInfo(buffer);
[email protected]a93bb842010-02-16 23:03:47406 }
407
[email protected]07f54fcc2009-12-22 02:46:30408 // Gets the buffer info for the given buffer.
[email protected]1d32bc82010-01-13 22:06:46409 BufferManager::BufferInfo* GetBufferInfo(GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:50410 BufferManager::BufferInfo* info = buffer_manager()->GetBufferInfo(buffer);
411 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46412 }
[email protected]07f54fcc2009-12-22 02:46:30413
[email protected]a93bb842010-02-16 23:03:47414 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
415 // on glDeleteBuffers so we can make sure the user does not try to render
416 // with deleted buffers.
417 void RemoveBufferInfo(GLuint buffer_id);
418
[email protected]558847a2010-03-24 07:02:54419 error::Error GetAttribLocationHelper(
420 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
421 const std::string& name_str);
422
423 error::Error GetUniformLocationHelper(
424 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
425 const std::string& name_str);
426
[email protected]3916c97e2010-02-25 03:20:50427 // Helper for glShaderSource.
428 error::Error ShaderSourceHelper(
429 GLuint shader, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30430
[email protected]96449d2c2009-11-25 00:01:32431 // Wrapper for glCreateProgram
432 void CreateProgramHelper(GLuint client_id);
433
434 // Wrapper for glCreateShader
435 void CreateShaderHelper(GLenum type, GLuint client_id);
436
[email protected]3916c97e2010-02-25 03:20:50437 // Wrapper for glActiveTexture
438 void DoActiveTexture(GLenum texture_unit);
439
[email protected]96449d2c2009-11-25 00:01:32440 // Wrapper for glBindBuffer since we need to track the current targets.
441 void DoBindBuffer(GLenum target, GLuint buffer);
442
[email protected]86093972010-03-11 00:13:56443 // Wrapper for glBindFramebuffer since we need to track the current targets.
444 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
445
446 // Wrapper for glBindRenderbuffer since we need to track the current targets.
447 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
448
[email protected]a93bb842010-02-16 23:03:47449 // Wrapper for glBindTexture since we need to track the current targets.
450 void DoBindTexture(GLenum target, GLuint texture);
451
[email protected]36cef8ce2010-03-16 07:34:45452 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11453 void DoBufferData(
454 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
455
[email protected]36cef8ce2010-03-16 07:34:45456 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11457 void DoBufferSubData(
458 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
459
[email protected]36cef8ce2010-03-16 07:34:45460 // Wrapper for glCheckFramebufferStatus
461 GLenum DoCheckFramebufferStatus(GLenum target);
462
[email protected]45bf5152010-02-12 00:11:31463 // Wrapper for glCompileShader.
464 void DoCompileShader(GLuint shader);
465
[email protected]07f54fcc2009-12-22 02:46:30466 // Wrapper for glDrawArrays.
467 void DoDrawArrays(GLenum mode, GLint first, GLsizei count);
468
469 // Wrapper for glDisableVertexAttribArray.
470 void DoDisableVertexAttribArray(GLuint index);
471
472 // Wrapper for glEnableVertexAttribArray.
473 void DoEnableVertexAttribArray(GLuint index);
474
[email protected]36cef8ce2010-03-16 07:34:45475 // Wrapper for glFramebufferRenderbufffer.
476 void DoFramebufferRenderbuffer(
477 GLenum target, GLenum attachment, GLenum renderbuffertarget,
478 GLuint renderbuffer);
479
480 // Wrapper for glFramebufferTexture2D.
481 void DoFramebufferTexture2D(
482 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
483 GLint level);
484
[email protected]a93bb842010-02-16 23:03:47485 // Wrapper for glGenerateMipmap
486 void DoGenerateMipmap(GLenum target);
487
[email protected]36cef8ce2010-03-16 07:34:45488 // Wrapper for glGetFramebufferAttachmentParameteriv.
489 void DoGetFramebufferAttachmentParameteriv(
490 GLenum target, GLenum attachment, GLenum pname, GLint* params);
491
492 // Wrapper for glRenderbufferParameteriv.
493 void DoGetRenderbufferParameteriv(
494 GLenum target, GLenum pname, GLint* params);
495
[email protected]ddd968b82010-03-02 00:44:29496 // Wrapper for glGetShaderiv
497 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
498
[email protected]45bf5152010-02-12 00:11:31499 // Wrapper for glGetShaderSource.
500 void DoGetShaderSource(
501 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst);
502
[email protected]07f54fcc2009-12-22 02:46:30503 // Wrapper for glLinkProgram
504 void DoLinkProgram(GLuint program);
505
[email protected]36cef8ce2010-03-16 07:34:45506 // Wrapper for glRenderbufferStorage.
507 void DoRenderbufferStorage(
508 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
509
[email protected]96449d2c2009-11-25 00:01:32510 // Swaps the buffers (copies/renders to the current window).
511 void DoSwapBuffers();
512
[email protected]3916c97e2010-02-25 03:20:50513 // Wrappers for glTexParameter functions.
514 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
515 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
516 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
517 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
518
519 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
520 // spec only these 2 functions can be used to set sampler uniforms.
521 void DoUniform1i(GLint location, GLint v0);
522 void DoUniform1iv(GLint location, GLsizei count, const GLint *value);
523
[email protected]07f54fcc2009-12-22 02:46:30524 // Wrapper for glUseProgram
525 void DoUseProgram(GLuint program);
526
[email protected]96449d2c2009-11-25 00:01:32527 // Gets the GLError through our wrapper.
528 GLenum GetGLError();
529
530 // Sets our wrapper for the GLError.
531 void SetGLError(GLenum error);
532
[email protected]07f54fcc2009-12-22 02:46:30533 // Copies the real GL errors to the wrapper. This is so we can
534 // make sure there are no native GL errors before calling some GL function
535 // so that on return we know any error generated was for that specific
536 // command.
537 void CopyRealGLErrorsToWrapper();
538
539 // Checks if the current program and vertex attributes are valid for drawing.
540 bool IsDrawValid(GLuint max_vertex_accessed);
541
[email protected]3916c97e2010-02-25 03:20:50542 void SetBlackTextureForNonRenderableTextures(
543 bool* has_non_renderable_textures);
544 void RestoreStateForNonRenderableTextures();
545
[email protected]07f54fcc2009-12-22 02:46:30546 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:50547 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:30548 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:50549 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
550 bound_array_buffer_ : bound_element_array_buffer_;
551 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:30552 }
553
[email protected]a93bb842010-02-16 23:03:47554 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:50555 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
556 TextureUnit& unit = texture_units_[active_texture_unit_];
557 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:47558 switch (target) {
559 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:50560 info = unit.bound_texture_2d;
561 break;
[email protected]a93bb842010-02-16 23:03:47562 case GL_TEXTURE_CUBE_MAP:
563 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
564 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
565 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
566 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
567 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
568 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:50569 info = unit.bound_texture_cube_map;
570 break;
[email protected]1aef98132010-02-23 18:00:07571 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
572 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
573 // because |texture_| is used by the FBO rendering mechanism for readback
574 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:47575 default:
576 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:50577 return NULL;
[email protected]a93bb842010-02-16 23:03:47578 }
[email protected]3916c97e2010-02-25 03:20:50579 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47580 }
581
[email protected]f7b85372010-02-03 01:11:37582 // Validates the program and location for a glGetUniform call and returns
583 // a SizeResult setup to receive the result. Returns true if glGetUniform
584 // should be called.
585 bool GetUniformSetup(
586 GLuint program, GLint location,
587 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:25588 error::Error* error, GLuint* service_id, void** result);
[email protected]f7b85372010-02-03 01:11:37589
[email protected]86093972010-03-11 00:13:56590 bool ValidateGLenumCompressedTextureInternalFormat(GLenum format);
591
[email protected]96449d2c2009-11-25 00:01:32592 // Generate a member function prototype for each command in an automated and
593 // typesafe way.
594 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:14595 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:19596 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:32597 const gles2::name& args); \
598
599 GLES2_COMMAND_LIST(GLES2_CMD_OP)
600
601 #undef GLES2_CMD_OP
602
[email protected]96449d2c2009-11-25 00:01:32603 // Current GL error bits.
604 uint32 error_bits_;
605
[email protected]96449d2c2009-11-25 00:01:32606 // Util to help with GL.
607 GLES2Util util_;
608
609 // pack alignment as last set by glPixelStorei
610 GLint pack_alignment_;
611
612 // unpack alignment as last set by glPixelStorei
613 GLint unpack_alignment_;
614
615 // The currently bound array buffer. If this is 0 it is illegal to call
616 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:50617 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:32618
619 // The currently bound element array buffer. If this is 0 it is illegal
620 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:50621 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:30622
623 // Info for each vertex attribute saved so we can check at glDrawXXX time
624 // if it is safe to draw.
625 scoped_array<VertexAttribInfo> vertex_attrib_infos_;
626
[email protected]3916c97e2010-02-25 03:20:50627 // Current active texture by 0 - n index.
628 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
629 // be 2.
630 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:30631
[email protected]3916c97e2010-02-25 03:20:50632 // Which textures are bound to texture units through glActiveTexture.
633 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:47634
[email protected]3916c97e2010-02-25 03:20:50635 // Black (0,0,0,0) textures for when non-renderable textures are used.
636 // NOTE: There is no corresponding TextureInfo for these textures.
637 // TextureInfos are only for textures the client side can access.
638 GLuint black_2d_texture_id_;
639 GLuint black_cube_texture_id_;
[email protected]45bf5152010-02-12 00:11:31640
[email protected]1d32bc82010-01-13 22:06:46641 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:50642 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:30643
[email protected]86093972010-03-11 00:13:56644 // The currently bound framebuffer
645 GLuint bound_framebuffer_;
646
647 // The currently bound renderbuffer
648 GLuint bound_renderbuffer_;
649
[email protected]69d80ae2009-12-23 08:57:42650#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59651#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:42652#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:50653 static int pixel_format_;
654 HDC gl_device_context_;
[email protected]96449d2c2009-11-25 00:01:32655 HGLRC gl_context_;
[email protected]246a70452010-03-05 21:53:50656 HPBUFFERARB pbuffer_;
[email protected]43f28f832010-02-03 02:28:48657#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:35658 AcceleratedSurface surface_;
[email protected]96449d2c2009-11-25 00:01:32659#endif
660
661 bool anti_aliased_;
662
[email protected]43f28f832010-02-03 02:28:48663 scoped_ptr<Callback0::Type> swap_buffers_callback_;
664
[email protected]96449d2c2009-11-25 00:01:32665 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
666};
667
[email protected]3916c97e2010-02-25 03:20:50668GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
669 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:32670}
671
[email protected]246a70452010-03-05 21:53:50672#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59673#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]246a70452010-03-05 21:53:50674#elif defined(OS_WIN)
675int GLES2DecoderImpl::pixel_format_;
676#endif
677
[email protected]3916c97e2010-02-25 03:20:50678GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
679 : GLES2Decoder(group),
[email protected]96449d2c2009-11-25 00:01:32680 error_bits_(0),
681 util_(0), // TODO(gman): Set to actual num compress texture formats.
682 pack_alignment_(4),
683 unpack_alignment_(4),
[email protected]3916c97e2010-02-25 03:20:50684 active_texture_unit_(0),
685 black_2d_texture_id_(0),
686 black_cube_texture_id_(0),
[email protected]86093972010-03-11 00:13:56687 bound_framebuffer_(0),
688 bound_renderbuffer_(0),
[email protected]69d80ae2009-12-23 08:57:42689#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59690#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:42691#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:50692 gl_device_context_(NULL),
[email protected]96449d2c2009-11-25 00:01:32693 gl_context_(NULL),
[email protected]246a70452010-03-05 21:53:50694 pbuffer_(NULL),
[email protected]96449d2c2009-11-25 00:01:32695#endif
696 anti_aliased_(false) {
697}
698
699bool GLES2DecoderImpl::Initialize() {
[email protected]246a70452010-03-05 21:53:50700 if (!InitPlatformSpecific()) {
701 Destroy();
702 return false;
703 }
704 if (!MakeCurrent()) {
705 Destroy();
706 return false;
[email protected]eb54a562010-01-20 21:55:18707 }
708
[email protected]246a70452010-03-05 21:53:50709 // This happens in InitializeOneOff in windows. TODO(apatrick): generalize to
710 // other platforms.
711#if !defined(OS_WIN)
712 if (!InitGlew()) {
713 Destroy();
714 return false;
715 }
716#endif
717
718 CHECK_GL_ERROR();
719
720 if (!group_->Initialize()) {
721 Destroy();
722 return false;
723 }
724
725 vertex_attrib_infos_.reset(
726 new VertexAttribInfo[group_->max_vertex_attribs()]);
727 texture_units_.reset(
728 new TextureUnit[group_->max_texture_units()]);
729 GLuint ids[2];
730 glGenTextures(2, ids);
731 // Make black textures for replacing non-renderable textures.
732 black_2d_texture_id_ = ids[0];
733 black_cube_texture_id_ = ids[1];
734 static int8 black[] = {0, 0, 0, 0};
735 glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
736 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
737 GL_UNSIGNED_BYTE, black);
738 glBindTexture(GL_TEXTURE_2D, 0);
739 glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
740 static GLenum faces[] = {
741 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
742 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
743 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
744 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
745 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
746 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
747 };
748 for (size_t ii = 0; ii < arraysize(faces); ++ii) {
749 glTexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA,
750 GL_UNSIGNED_BYTE, black);
751 }
752 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
753 CHECK_GL_ERROR();
754
755 return true;
[email protected]96449d2c2009-11-25 00:01:32756}
757
[email protected]43f28f832010-02-03 02:28:48758// TODO(kbr): the use of this anonymous namespace core dumps the
759// linker on Mac OS X 10.6 when the symbol ordering file is used
760// namespace {
[email protected]96449d2c2009-11-25 00:01:32761
[email protected]69d80ae2009-12-23 08:57:42762#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:59763#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:42764#elif defined(OS_WIN)
765
[email protected]96449d2c2009-11-25 00:01:32766const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
767 sizeof(kPixelFormatDescriptor), // Size of structure.
768 1, // Default version.
769 PFD_DRAW_TO_WINDOW | // Window drawing support.
770 PFD_SUPPORT_OPENGL | // OpenGL support.
771 PFD_DOUBLEBUFFER, // Double buffering support (not stereo).
772 PFD_TYPE_RGBA, // RGBA color mode (not indexed).
773 24, // 24 bit color mode.
774 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts.
775 8, 0, // 8 bit alpha
776 0, // No accumulation buffer.
777 0, 0, 0, 0, // Ignore accumulation bits.
778 24, // 24 bit z-buffer size.
779 8, // 8-bit stencil buffer.
780 0, // No aux buffer.
781 PFD_MAIN_PLANE, // Main drawing plane (not overlay).
782 0, // Reserved.
783 0, 0, 0, // Layer masks ignored.
784};
785
786LRESULT CALLBACK IntermediateWindowProc(HWND window,
787 UINT message,
788 WPARAM w_param,
789 LPARAM l_param) {
790 return ::DefWindowProc(window, message, w_param, l_param);
791}
792
[email protected]246a70452010-03-05 21:53:50793// Helper routine that does one-off initialization like determining the
794// pixel format and initializing glew.
795bool GLES2DecoderImpl::InitializeOneOff(bool anti_aliased) {
[email protected]96449d2c2009-11-25 00:01:32796 // We must initialize a GL context before we can determine the multi-sampling
797 // supported on the current hardware, so we create an intermediate window
798 // and context here.
799 HINSTANCE module_handle;
800 if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
801 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
802 reinterpret_cast<wchar_t*>(IntermediateWindowProc),
803 &module_handle)) {
804 return false;
805 }
806
807 WNDCLASS intermediate_class;
808 intermediate_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
809 intermediate_class.lpfnWndProc = IntermediateWindowProc;
810 intermediate_class.cbClsExtra = 0;
811 intermediate_class.cbWndExtra = 0;
812 intermediate_class.hInstance = module_handle;
813 intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
814 intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
815 intermediate_class.hbrBackground = NULL;
816 intermediate_class.lpszMenuName = NULL;
817 intermediate_class.lpszClassName = L"Intermediate GL Window";
818
819 ATOM class_registration = ::RegisterClass(&intermediate_class);
820 if (!class_registration) {
821 return false;
822 }
823
824 HWND intermediate_window = ::CreateWindow(
825 reinterpret_cast<wchar_t*>(class_registration),
826 L"",
827 WS_OVERLAPPEDWINDOW,
828 0, 0,
829 CW_USEDEFAULT, CW_USEDEFAULT,
830 NULL,
831 NULL,
832 NULL,
833 NULL);
834
835 if (!intermediate_window) {
836 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
837 module_handle);
838 return false;
839 }
840
841 HDC intermediate_dc = ::GetDC(intermediate_window);
[email protected]246a70452010-03-05 21:53:50842 pixel_format_ = ::ChoosePixelFormat(intermediate_dc,
843 &kPixelFormatDescriptor);
844 if (pixel_format_ == 0) {
[email protected]96449d2c2009-11-25 00:01:32845 DLOG(ERROR) << "Unable to get the pixel format for GL context.";
846 ::ReleaseDC(intermediate_window, intermediate_dc);
847 ::DestroyWindow(intermediate_window);
848 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
849 module_handle);
850 return false;
851 }
[email protected]246a70452010-03-05 21:53:50852 if (!::SetPixelFormat(intermediate_dc, pixel_format_,
[email protected]96449d2c2009-11-25 00:01:32853 &kPixelFormatDescriptor)) {
854 DLOG(ERROR) << "Unable to set the pixel format for GL context.";
855 ::ReleaseDC(intermediate_window, intermediate_dc);
856 ::DestroyWindow(intermediate_window);
857 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
858 module_handle);
859 return false;
860 }
861
[email protected]246a70452010-03-05 21:53:50862 // Create a temporary GL context to query for multisampled pixel formats.
[email protected]96449d2c2009-11-25 00:01:32863 HGLRC gl_context = ::wglCreateContext(intermediate_dc);
864 if (::wglMakeCurrent(intermediate_dc, gl_context)) {
865 // GL context was successfully created and applied to the window's DC.
866 // Startup GLEW, the GL extensions wrangler.
[email protected]246a70452010-03-05 21:53:50867 if (InitGlew()) {
[email protected]96449d2c2009-11-25 00:01:32868 DLOG(INFO) << "Initialized GLEW " << ::glewGetString(GLEW_VERSION);
869 } else {
[email protected]96449d2c2009-11-25 00:01:32870 ::wglMakeCurrent(intermediate_dc, NULL);
871 ::wglDeleteContext(gl_context);
872 ::ReleaseDC(intermediate_window, intermediate_dc);
873 ::DestroyWindow(intermediate_window);
874 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
875 module_handle);
876 return false;
877 }
878
879 // If the multi-sample extensions are present, query the api to determine
880 // the pixel format.
881 if (anti_aliased && WGLEW_ARB_pixel_format && WGLEW_ARB_multisample) {
882 int pixel_attributes[] = {
883 WGL_SAMPLES_ARB, 4,
884 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
885 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
886 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
887 WGL_COLOR_BITS_ARB, 24,
888 WGL_ALPHA_BITS_ARB, 8,
889 WGL_DEPTH_BITS_ARB, 24,
890 WGL_STENCIL_BITS_ARB, 8,
891 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
892 WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
893 0, 0};
894
895 float pixel_attributes_f[] = {0, 0};
896 int msaa_pixel_format;
897 unsigned int num_formats;
898
899 // Query for the highest sampling rate supported, starting at 4x.
900 static const int kSampleCount[] = {4, 2};
901 static const int kNumSamples = 2;
902 for (int sample = 0; sample < kNumSamples; ++sample) {
903 pixel_attributes[1] = kSampleCount[sample];
904 if (GL_TRUE == ::wglChoosePixelFormatARB(intermediate_dc,
905 pixel_attributes,
906 pixel_attributes_f,
907 1,
908 &msaa_pixel_format,
909 &num_formats)) {
[email protected]246a70452010-03-05 21:53:50910 pixel_format_ = msaa_pixel_format;
[email protected]96449d2c2009-11-25 00:01:32911 break;
912 }
913 }
914 }
915 }
916
917 ::wglMakeCurrent(intermediate_dc, NULL);
918 ::wglDeleteContext(gl_context);
919 ::ReleaseDC(intermediate_window, intermediate_dc);
920 ::DestroyWindow(intermediate_window);
921 ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
922 module_handle);
923 return true;
924}
925
[email protected]69d80ae2009-12-23 08:57:42926#endif // OS_WIN
927
[email protected]07f54fcc2009-12-22 02:46:30928// These commands convert from c calls to local os calls.
929void GLGenBuffersHelper(
[email protected]a93bb842010-02-16 23:03:47930 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:30931 glGenBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:47932 // TODO(gman): handle error
933 for (GLsizei ii = 0; ii < n; ++ii) {
934 decoder->CreateBufferInfo(ids[ii]);
935 }
[email protected]07f54fcc2009-12-22 02:46:30936}
937
938void GLGenFramebuffersHelper(
939 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
940 glGenFramebuffersEXT(n, ids);
941}
942
943void GLGenRenderbuffersHelper(
944 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
945 glGenRenderbuffersEXT(n, ids);
946}
947
948void GLGenTexturesHelper(
[email protected]a93bb842010-02-16 23:03:47949 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:30950 glGenTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:47951 // TODO(gman): handle error
952 for (GLsizei ii = 0; ii < n; ++ii) {
953 decoder->CreateTextureInfo(ids[ii]);
954 }
[email protected]07f54fcc2009-12-22 02:46:30955}
956
957void GLDeleteBuffersHelper(
958 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
959 glDeleteBuffersARB(n, ids);
[email protected]a93bb842010-02-16 23:03:47960 // TODO(gman): handle error
[email protected]07f54fcc2009-12-22 02:46:30961 for (GLsizei ii = 0; ii < n; ++ii) {
962 decoder->RemoveBufferInfo(ids[ii]);
963 }
964}
965
966void GLDeleteFramebuffersHelper(
967 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
968 glDeleteFramebuffersEXT(n, ids);
969}
970
971void GLDeleteRenderbuffersHelper(
972 GLES2DecoderImpl*, GLsizei n, GLuint* ids) {
973 glDeleteRenderbuffersEXT(n, ids);
974}
975
976void GLDeleteTexturesHelper(
[email protected]a93bb842010-02-16 23:03:47977 GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
[email protected]07f54fcc2009-12-22 02:46:30978 glDeleteTextures(n, ids);
[email protected]a93bb842010-02-16 23:03:47979 // TODO(gman): handle error
980 for (GLsizei ii = 0; ii < n; ++ii) {
981 decoder->RemoveTextureInfo(ids[ii]);
982 }
[email protected]07f54fcc2009-12-22 02:46:30983}
984
[email protected]43f28f832010-02-03 02:28:48985// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:32986
[email protected]eb54a562010-01-20 21:55:18987bool GLES2DecoderImpl::MakeCurrent() {
988#if defined(UNIT_TEST)
989 return true;
[email protected]b5f1aa032010-03-11 00:07:59990#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
991 return true;
[email protected]eb54a562010-01-20 21:55:18992#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:50993 if (::wglGetCurrentDC() == gl_device_context_ &&
[email protected]eb54a562010-01-20 21:55:18994 ::wglGetCurrentContext() == gl_context_) {
995 return true;
996 }
[email protected]246a70452010-03-05 21:53:50997 if (!::wglMakeCurrent(gl_device_context_, gl_context_)) {
[email protected]eb54a562010-01-20 21:55:18998 DLOG(ERROR) << "Unable to make gl context current.";
999 return false;
1000 }
1001 return true;
1002#elif defined(OS_LINUX)
1003 return window()->MakeCurrent();
[email protected]43f28f832010-02-03 02:28:481004#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:351005 return surface_.MakeCurrent();
[email protected]eb54a562010-01-20 21:55:181006#else
1007 NOTREACHED();
1008 return false;
1009#endif
1010}
1011
[email protected]8a837bb2010-01-05 00:21:241012uint32 GLES2DecoderImpl::GetServiceIdForTesting(uint32 client_id) {
1013#if defined(UNIT_TEST)
1014 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501015 bool result = id_manager()->GetServiceId(client_id, &service_id);
[email protected]8a837bb2010-01-05 00:21:241016 return result ? service_id : 0u;
1017#else
1018 DCHECK(false);
1019 return 0u;
1020#endif
1021}
1022
1023bool GLES2DecoderImpl::ValidateIdsAreUnused(
1024 GLsizei n, const GLuint* client_ids) {
1025 for (GLsizei ii = 0; ii < n; ++ii) {
1026 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501027 if (id_manager()->GetServiceId(client_ids[ii], &service_id)) {
[email protected]8a837bb2010-01-05 00:21:241028 return false;
1029 }
1030 }
1031 return true;
1032}
1033
[email protected]07f54fcc2009-12-22 02:46:301034bool GLES2DecoderImpl::RegisterObjects(
1035 GLsizei n, const GLuint* client_ids, const GLuint* service_ids) {
1036 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501037 if (!id_manager()->AddMapping(client_ids[ii], service_ids[ii])) {
[email protected]8a837bb2010-01-05 00:21:241038 NOTREACHED();
1039 return false;
[email protected]07f54fcc2009-12-22 02:46:301040 }
1041 }
1042 return true;
1043}
1044
1045void GLES2DecoderImpl::UnregisterObjects(
1046 GLsizei n, const GLuint* client_ids, GLuint* service_ids) {
[email protected]07f54fcc2009-12-22 02:46:301047 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]3916c97e2010-02-25 03:20:501048 if (id_manager()->GetServiceId(client_ids[ii], &service_ids[ii])) {
1049 id_manager()->RemoveMapping(client_ids[ii], service_ids[ii]);
[email protected]07f54fcc2009-12-22 02:46:301050 } else {
1051 service_ids[ii] = 0;
1052 }
1053 }
1054}
1055
[email protected]96449d2c2009-11-25 00:01:321056bool GLES2DecoderImpl::InitPlatformSpecific() {
[email protected]69d80ae2009-12-23 08:57:421057#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591058#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:421059#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:501060 // Do one-off initialization.
1061 static bool success = InitializeOneOff(anti_aliased_);
1062 if (!success)
[email protected]96449d2c2009-11-25 00:01:321063 return false;
[email protected]246a70452010-03-05 21:53:501064
1065 if (hwnd()) {
1066 // The GL context will render to this window.
1067 gl_device_context_ = ::GetDC(hwnd());
1068
1069 if (!::SetPixelFormat(gl_device_context_,
1070 pixel_format_,
1071 &kPixelFormatDescriptor)) {
1072 DLOG(ERROR) << "Unable to set the pixel format for GL context.";
1073 DestroyPlatformSpecific();
1074 return false;
1075 }
1076 } else {
1077 // Create a device context compatible with the primary display.
1078 HDC display_device_context = ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
1079
1080 // Create a 1 x 1 pbuffer suitable for use with the device.
1081 const int kNoAttributes[] = { 0 };
1082 pbuffer_ = ::wglCreatePbufferARB(display_device_context,
1083 pixel_format_,
1084 1, 1,
1085 kNoAttributes);
1086 ::DeleteDC(display_device_context);
1087 if (!pbuffer_) {
1088 DLOG(ERROR) << "Unable to create pbuffer.";
1089 DestroyPlatformSpecific();
1090 return false;
1091 }
1092
1093 gl_device_context_ = ::wglGetPbufferDCARB(pbuffer_);
1094 if (!gl_device_context_) {
1095 DLOG(ERROR) << "Unable to get pbuffer device context.";
1096 DestroyPlatformSpecific();
1097 return false;
1098 }
[email protected]96449d2c2009-11-25 00:01:321099 }
1100
[email protected]246a70452010-03-05 21:53:501101 gl_context_ = ::wglCreateContext(gl_device_context_);
[email protected]96449d2c2009-11-25 00:01:321102 if (!gl_context_) {
1103 DLOG(ERROR) << "Failed to create GL context.";
[email protected]246a70452010-03-05 21:53:501104 DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:321105 return false;
1106 }
[email protected]96449d2c2009-11-25 00:01:321107#elif defined(OS_LINUX)
1108 DCHECK(window());
1109 if (!window()->Initialize())
1110 return false;
[email protected]43f28f832010-02-03 02:28:481111#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:351112 return surface_.Initialize();
[email protected]96449d2c2009-11-25 00:01:321113#endif
1114
1115 return true;
1116}
1117
1118bool GLES2DecoderImpl::InitGlew() {
[email protected]b5f1aa032010-03-11 00:07:591119#if !defined(UNIT_TEST) && !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]96449d2c2009-11-25 00:01:321120 DLOG(INFO) << "Initializing GL and GLEW for GLES2Decoder.";
1121
1122 GLenum glew_error = glewInit();
1123 if (glew_error != GLEW_OK) {
1124 DLOG(ERROR) << "Unable to initialise GLEW : "
1125 << ::glewGetErrorString(glew_error);
1126 return false;
1127 }
1128
1129 // Check to see that we can use the OpenGL vertex attribute APIs
1130 // TODO(petersont): Return false if this check fails, but because some
1131 // Intel hardware does not support OpenGL 2.0, yet does support all of the
1132 // extensions we require, we only log an error. A future CL should change
1133 // this check to ensure that all of the extension strings we require are
1134 // present.
1135 if (!GLEW_VERSION_2_0) {
1136 DLOG(ERROR) << "GL drivers do not have OpenGL 2.0 functionality.";
1137 }
1138
1139 bool extensions_found = true;
1140 if (!GLEW_ARB_vertex_buffer_object) {
1141 // NOTE: Linux NVidia drivers claim to support OpenGL 2.0 when using
1142 // indirect rendering (e.g. remote X), but it is actually lying. The
1143 // ARB_vertex_buffer_object functions silently no-op (!) when using
1144 // indirect rendering, leading to crashes. Fortunately, in that case, the
1145 // driver claims to not support ARB_vertex_buffer_object, so fail in that
1146 // case.
1147 DLOG(ERROR) << "GL drivers do not support vertex buffer objects.";
1148 extensions_found = false;
1149 }
1150 if (!GLEW_EXT_framebuffer_object) {
1151 DLOG(ERROR) << "GL drivers do not support framebuffer objects.";
1152 extensions_found = false;
1153 }
1154 // Check for necessary extensions
1155 if (!GLEW_VERSION_2_0 && !GLEW_EXT_stencil_two_side) {
1156 DLOG(ERROR) << "Two sided stencil extension missing.";
1157 extensions_found = false;
1158 }
1159 if (!GLEW_VERSION_1_4 && !GLEW_EXT_blend_func_separate) {
1160 DLOG(ERROR) <<"Separate blend func extension missing.";
1161 extensions_found = false;
1162 }
1163 if (!GLEW_VERSION_2_0 && !GLEW_EXT_blend_equation_separate) {
1164 DLOG(ERROR) << "Separate blend function extension missing.";
1165 extensions_found = false;
1166 }
1167 if (!extensions_found)
1168 return false;
[email protected]69d80ae2009-12-23 08:57:421169#endif
[email protected]96449d2c2009-11-25 00:01:321170
1171 return true;
1172}
1173
[email protected]246a70452010-03-05 21:53:501174void GLES2DecoderImpl::DestroyPlatformSpecific() {
1175#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591176#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]246a70452010-03-05 21:53:501177#elif defined(OS_WIN)
1178 if (gl_context_) {
1179 ::wglDeleteContext(gl_context_);
1180 }
1181
1182 if (gl_device_context_) {
1183 if (hwnd())
1184 ::ReleaseDC(hwnd(), gl_device_context_);
1185 else
1186 ::wglReleasePbufferDCARB(pbuffer_, gl_device_context_);
1187
1188 gl_device_context_ = NULL;
1189 }
1190
1191 if (pbuffer_) {
1192 ::wglDestroyPbufferARB(pbuffer_);
1193 pbuffer_ = NULL;
1194 }
1195#endif
1196}
1197
[email protected]6098b712010-02-09 17:59:341198#if defined(OS_MACOSX)
[email protected]1aef98132010-02-23 18:00:071199
1200uint64 GLES2DecoderImpl::SetWindowSizeForIOSurface(int32 width, int32 height) {
[email protected]6098b712010-02-09 17:59:341201#if defined(UNIT_TEST)
1202 return 0;
[email protected]b5f1aa032010-03-11 00:07:591203#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1204 return 0;
[email protected]6098b712010-02-09 17:59:341205#else
[email protected]3d1e89d2010-03-10 20:01:351206 return surface_.SetSurfaceSize(width, height);
[email protected]6098b712010-02-09 17:59:341207#endif // !defined(UNIT_TEST)
[email protected]43f28f832010-02-03 02:28:481208}
[email protected]1aef98132010-02-23 18:00:071209
1210TransportDIB::Handle GLES2DecoderImpl::SetWindowSizeForTransportDIB(
1211 int32 width, int32 height) {
1212#if defined(UNIT_TEST)
1213 return TransportDIB::DefaultHandleValue();
[email protected]b5f1aa032010-03-11 00:07:591214#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
1215 return TransportDIB::DefaultHandleValue();
[email protected]1aef98132010-02-23 18:00:071216#else
[email protected]3d1e89d2010-03-10 20:01:351217 return surface_.SetTransportDIBSize(width, height);
[email protected]1aef98132010-02-23 18:00:071218#endif // !defined(UNIT_TEST)
1219}
1220
1221void GLES2DecoderImpl::SetTransportDIBAllocAndFree(
1222 Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
1223 Callback1<TransportDIB::Id>::Type* deallocator) {
[email protected]3d1e89d2010-03-10 20:01:351224 surface_.SetTransportDIBAllocAndFree(allocator, deallocator);
[email protected]1aef98132010-02-23 18:00:071225}
[email protected]6098b712010-02-09 17:59:341226#endif // defined(OS_MACOSX)
[email protected]43f28f832010-02-03 02:28:481227
1228void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
1229 swap_buffers_callback_.reset(callback);
1230}
1231
[email protected]96449d2c2009-11-25 00:01:321232void GLES2DecoderImpl::Destroy() {
[email protected]69d80ae2009-12-23 08:57:421233#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591234#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:421235#elif defined(OS_LINUX)
[email protected]96449d2c2009-11-25 00:01:321236 DCHECK(window());
1237 window()->Destroy();
[email protected]43f28f832010-02-03 02:28:481238#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:351239 surface_.Destroy();
[email protected]96449d2c2009-11-25 00:01:321240#endif
[email protected]246a70452010-03-05 21:53:501241
1242 DestroyPlatformSpecific();
[email protected]96449d2c2009-11-25 00:01:321243}
1244
1245const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
1246 if (command_id > kStartPoint && command_id < kNumCommands) {
1247 return gles2::GetCommandName(static_cast<CommandId>(command_id));
1248 }
1249 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
1250}
1251
1252// Decode command with its arguments, and call the corresponding GL function.
1253// Note: args is a pointer to the command buffer. As such, it could be changed
1254// by a (malicious) client at any time, so if validation has to happen, it
1255// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:141256error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:321257 unsigned int command,
1258 unsigned int arg_count,
1259 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:141260 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191261 if (debug()) {
1262 // TODO(gman): Change output to something useful for NaCl.
[email protected]b9849abf2009-11-25 19:13:191263 printf("cmd: %s\n", GetCommandName(command));
1264 }
[email protected]96449d2c2009-11-25 00:01:321265 unsigned int command_index = command - kStartPoint - 1;
1266 if (command_index < arraysize(g_command_info)) {
1267 const CommandInfo& info = g_command_info[command_index];
1268 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
1269 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
1270 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:191271 uint32 immediate_data_size =
1272 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:321273 switch (command) {
1274 #define GLES2_CMD_OP(name) \
1275 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:191276 result = Handle ## name( \
1277 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321278 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:191279 break; \
[email protected]96449d2c2009-11-25 00:01:321280
1281 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:321282 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:381283 }
1284 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:301285 GLenum error;
1286 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:381287 // TODO(gman): Change output to something useful for NaCl.
[email protected]07f54fcc2009-12-22 02:46:301288 SetGLError(error);
[email protected]bf0985e2009-12-17 03:04:381289 printf("GL ERROR b4: %s\n", GetCommandName(command));
[email protected]b9849abf2009-11-25 19:13:191290 }
[email protected]96449d2c2009-11-25 00:01:321291 }
1292 } else {
[email protected]f7a64ee2010-02-01 22:24:141293 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:321294 }
[email protected]b9849abf2009-11-25 19:13:191295 } else {
1296 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:321297 }
[email protected]b9849abf2009-11-25 19:13:191298 return result;
[email protected]96449d2c2009-11-25 00:01:321299}
1300
[email protected]3916c97e2010-02-25 03:20:501301void GLES2DecoderImpl::RemoveBufferInfo(GLuint buffer_id) {
1302 buffer_manager()->RemoveBufferInfo(buffer_id);
1303 // TODO(gman): See if we can remove the rest of this function as
1304 // buffers are now reference counted and have a "IsDeleted" function.
1305 if (bound_array_buffer_ && bound_array_buffer_->buffer_id() == buffer_id) {
1306 bound_array_buffer_ = NULL;
1307 }
1308 if (bound_element_array_buffer_ &&
1309 bound_element_array_buffer_->buffer_id() == buffer_id) {
1310 bound_element_array_buffer_ = NULL;
1311 }
1312
1313 // go through VertexAttribInfo and update any info that references the buffer.
1314 for (GLuint ii = 0; ii < group_->max_vertex_attribs(); ++ii) {
1315 VertexAttribInfo& info = vertex_attrib_infos_[ii];
1316 if (info.buffer() && info.buffer()->buffer_id() == buffer_id) {
1317 info.ClearBuffer();
1318 }
1319 }
1320}
1321
[email protected]96449d2c2009-11-25 00:01:321322void GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
1323 // TODO(gman): verify client_id is unused.
1324 GLuint service_id = glCreateProgram();
1325 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501326 id_manager()->AddMapping(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:471327 CreateProgramInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321328 }
1329}
1330
1331void GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
1332 // TODO(gman): verify client_id is unused.
1333 GLuint service_id = glCreateShader(type);
1334 if (service_id) {
[email protected]3916c97e2010-02-25 03:20:501335 id_manager()->AddMapping(client_id, service_id);
[email protected]45bf5152010-02-12 00:11:311336 CreateShaderInfo(service_id);
[email protected]96449d2c2009-11-25 00:01:321337 }
1338}
1339
[email protected]86093972010-03-11 00:13:561340bool GLES2DecoderImpl::ValidateGLenumCompressedTextureInternalFormat(GLenum) {
1341 // TODO(gman): Add support for compressed texture formats.
1342 return false;
1343}
1344
[email protected]3916c97e2010-02-25 03:20:501345void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:451346 GLuint texture_index = texture_unit - GL_TEXTURE0;
1347 if (texture_index > group_->max_texture_units()) {
[email protected]3916c97e2010-02-25 03:20:501348 SetGLError(GL_INVALID_ENUM);
1349 return;
1350 }
[email protected]36cef8ce2010-03-16 07:34:451351 active_texture_unit_ = texture_index;
1352 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:501353}
1354
[email protected]96449d2c2009-11-25 00:01:321355void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint buffer) {
[email protected]3916c97e2010-02-25 03:20:501356 BufferManager::BufferInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471357 if (buffer) {
[email protected]3916c97e2010-02-25 03:20:501358 info = GetBufferInfo(buffer);
[email protected]0c86dbf2010-03-05 08:14:111359 // Check the buffer exists
1360 // Check that we are not trying to bind it to a different target.
1361 if (!info || (info->target() != 0 && info->target() != target)) {
[email protected]a93bb842010-02-16 23:03:471362 SetGLError(GL_INVALID_OPERATION);
1363 return;
1364 }
[email protected]0c86dbf2010-03-05 08:14:111365 if (info->target() == 0) {
1366 info->set_target(target);
1367 }
[email protected]a93bb842010-02-16 23:03:471368 }
[email protected]96449d2c2009-11-25 00:01:321369 switch (target) {
1370 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501371 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321372 break;
1373 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:501374 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:321375 break;
1376 default:
[email protected]a93bb842010-02-16 23:03:471377 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:321378 break;
1379 }
1380 glBindBuffer(target, buffer);
1381}
1382
[email protected]86093972010-03-11 00:13:561383void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint framebuffer) {
1384 bound_framebuffer_ = framebuffer;
1385 glBindFramebufferEXT(target, framebuffer);
1386}
1387
1388void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint renderbuffer) {
1389 bound_renderbuffer_ = renderbuffer;
1390 glBindRenderbufferEXT(target, renderbuffer);
1391}
1392
[email protected]a93bb842010-02-16 23:03:471393void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint texture) {
[email protected]3916c97e2010-02-25 03:20:501394 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471395 if (texture) {
[email protected]3916c97e2010-02-25 03:20:501396 info = GetTextureInfo(texture);
1397 // Check the texture exists
1398 // Check that we are not trying to bind it to a different target.
[email protected]a93bb842010-02-16 23:03:471399 if (!info || (info->target() != 0 && info->target() != target)) {
1400 SetGLError(GL_INVALID_OPERATION);
1401 return;
1402 }
1403 if (info->target() == 0) {
[email protected]3916c97e2010-02-25 03:20:501404 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:471405 }
1406 }
1407 glBindTexture(target, texture);
[email protected]3916c97e2010-02-25 03:20:501408 TextureUnit& unit = texture_units_[active_texture_unit_];
1409 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:471410 switch (target) {
1411 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501412 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:471413 break;
1414 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:501415 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:471416 break;
1417 default:
1418 NOTREACHED(); // Validation should prevent us getting here.
1419 break;
1420 }
1421}
1422
[email protected]07f54fcc2009-12-22 02:46:301423void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501424 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301425 vertex_attrib_infos_[index].set_enabled(false);
[email protected]8a837bb2010-01-05 00:21:241426 glDisableVertexAttribArray(index);
[email protected]07f54fcc2009-12-22 02:46:301427 } else {
1428 SetGLError(GL_INVALID_VALUE);
1429 }
1430}
1431
1432void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501433 if (index < group_->max_vertex_attribs()) {
[email protected]07f54fcc2009-12-22 02:46:301434 vertex_attrib_infos_[index].set_enabled(true);
1435 glEnableVertexAttribArray(index);
1436 } else {
1437 SetGLError(GL_INVALID_VALUE);
1438 }
1439}
1440
[email protected]a93bb842010-02-16 23:03:471441void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:501442 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1443 if (!info || !info->MarkMipmapsGenerated()) {
[email protected]a93bb842010-02-16 23:03:471444 SetGLError(GL_INVALID_OPERATION);
1445 return;
1446 }
1447 glGenerateMipmapEXT(target);
[email protected]a93bb842010-02-16 23:03:471448}
1449
[email protected]558847a2010-03-24 07:02:541450error::Error GLES2DecoderImpl::HandleBindAttribLocation(
1451 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
1452 GLuint program;
1453 if (!id_manager()->GetServiceId(c.program, &program)) {
1454 SetGLError(GL_INVALID_VALUE);
1455 return error::kNoError;
1456 }
1457 GLuint index = static_cast<GLuint>(c.index);
1458 uint32 name_size = c.data_size;
1459 const char* name = GetSharedMemoryAs<const char*>(
1460 c.name_shm_id, c.name_shm_offset, name_size);
1461 if (name == NULL) {
1462 return error::kOutOfBounds;
1463 }
1464 String name_str(name, name_size);
1465 glBindAttribLocation(program, index, name_str.c_str());
1466 return error::kNoError;
1467}
1468
1469error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
1470 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
1471 GLuint program;
1472 if (!id_manager()->GetServiceId(c.program, &program)) {
1473 SetGLError(GL_INVALID_VALUE);
1474 return error::kNoError;
1475 }
1476 GLuint index = static_cast<GLuint>(c.index);
1477 uint32 name_size = c.data_size;
1478 const char* name = GetImmediateDataAs<const char*>(
1479 c, name_size, immediate_data_size);
1480 if (name == NULL) {
1481 return error::kOutOfBounds;
1482 }
1483 String name_str(name, name_size);
1484 glBindAttribLocation(program, index, name_str.c_str());
1485 return error::kNoError;
1486}
1487
1488error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
1489 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
1490 GLuint program;
1491 if (!id_manager()->GetServiceId(c.program, &program)) {
1492 SetGLError(GL_INVALID_VALUE);
1493 return error::kNoError;
1494 }
1495 GLuint index = static_cast<GLuint>(c.index);
1496 Bucket* bucket = GetBucket(c.name_bucket_id);
1497 if (!bucket || bucket->size() == 0) {
1498 return error::kInvalidArguments;
1499 }
1500 std::string name_str;
1501 bucket->GetAsString(&name_str);
1502 glBindAttribLocation(program, index, name_str.c_str());
1503 return error::kNoError;
1504}
1505
[email protected]f7a64ee2010-02-01 22:24:141506error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:461507 uint32 immediate_data_size, const gles2::DeleteShader& c) {
1508 GLuint shader = c.shader;
[email protected]96449d2c2009-11-25 00:01:321509 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501510 if (!id_manager()->GetServiceId(shader, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:461511 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141512 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321513 }
[email protected]45bf5152010-02-12 00:11:311514 RemoveShaderInfo(service_id);
[email protected]07f54fcc2009-12-22 02:46:301515 glDeleteShader(service_id);
[email protected]3916c97e2010-02-25 03:20:501516 id_manager()->RemoveMapping(shader, service_id);
[email protected]f7a64ee2010-02-01 22:24:141517 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321518}
1519
[email protected]f7a64ee2010-02-01 22:24:141520error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:461521 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
1522 GLuint program = c.program;
[email protected]96449d2c2009-11-25 00:01:321523 GLuint service_id;
[email protected]3916c97e2010-02-25 03:20:501524 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]ba3176a2009-12-16 18:19:461525 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141526 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321527 }
[email protected]1d32bc82010-01-13 22:06:461528 RemoveProgramInfo(service_id);
[email protected]ba3176a2009-12-16 18:19:461529 glDeleteProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:501530 id_manager()->RemoveMapping(program, service_id);
[email protected]f7a64ee2010-02-01 22:24:141531 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321532}
1533
[email protected]07f54fcc2009-12-22 02:46:301534void GLES2DecoderImpl::DoDrawArrays(
1535 GLenum mode, GLint first, GLsizei count) {
1536 if (IsDrawValid(first + count - 1)) {
[email protected]3916c97e2010-02-25 03:20:501537 bool has_non_renderable_textures;
1538 SetBlackTextureForNonRenderableTextures(&has_non_renderable_textures);
[email protected]07f54fcc2009-12-22 02:46:301539 glDrawArrays(mode, first, count);
[email protected]3916c97e2010-02-25 03:20:501540 if (has_non_renderable_textures) {
1541 RestoreStateForNonRenderableTextures();
1542 }
[email protected]07f54fcc2009-12-22 02:46:301543 }
1544}
1545
[email protected]36cef8ce2010-03-16 07:34:451546void GLES2DecoderImpl::DoFramebufferRenderbuffer(
1547 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1548 GLuint renderbuffer) {
1549 if (bound_framebuffer_ == 0) {
1550 SetGLError(GL_INVALID_OPERATION);
1551 return;
1552 }
1553 glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget,
1554 renderbuffer);
1555}
1556
1557GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
1558 if (bound_framebuffer_ == 0) {
1559 return GL_FRAMEBUFFER_COMPLETE;
1560 }
1561 return glCheckFramebufferStatusEXT(target);
1562}
1563
1564void GLES2DecoderImpl::DoFramebufferTexture2D(
1565 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1566 GLint level) {
1567 if (bound_framebuffer_ == 0) {
1568 SetGLError(GL_INVALID_OPERATION);
1569 return;
1570 }
1571 glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
1572}
1573
1574void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
1575 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
1576 if (bound_framebuffer_ == 0) {
1577 SetGLError(GL_INVALID_OPERATION);
1578 return;
1579 }
1580 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
1581}
1582
1583void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
1584 GLenum target, GLenum pname, GLint* params) {
1585 if (bound_renderbuffer_ == 0) {
1586 SetGLError(GL_INVALID_OPERATION);
1587 return;
1588 }
1589 glGetRenderbufferParameterivEXT(target, pname, params);
1590}
1591
1592void GLES2DecoderImpl::DoRenderbufferStorage(
1593 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
1594 if (bound_renderbuffer_ == 0) {
1595 SetGLError(GL_INVALID_OPERATION);
1596 return;
1597 }
1598 glRenderbufferStorageEXT(target, internalformat, width, height);
1599}
1600
[email protected]07f54fcc2009-12-22 02:46:301601void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]a93bb842010-02-16 23:03:471602 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
1603 if (!info) {
1604 SetGLError(GL_INVALID_OPERATION);
1605 return;
1606 }
[email protected]07f54fcc2009-12-22 02:46:301607 CopyRealGLErrorsToWrapper();
1608 glLinkProgram(program);
1609 GLenum error = glGetError();
1610 if (error != GL_NO_ERROR) {
1611 RemoveProgramInfo(program);
1612 SetGLError(error);
1613 } else {
[email protected]a93bb842010-02-16 23:03:471614 info->Update();
[email protected]07f54fcc2009-12-22 02:46:301615 }
1616};
1617
[email protected]96449d2c2009-11-25 00:01:321618void GLES2DecoderImpl::DoSwapBuffers() {
[email protected]69d80ae2009-12-23 08:57:421619#if defined(UNIT_TEST)
[email protected]b5f1aa032010-03-11 00:07:591620#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
[email protected]69d80ae2009-12-23 08:57:421621#elif defined(OS_WIN)
[email protected]246a70452010-03-05 21:53:501622 ::SwapBuffers(gl_device_context_);
[email protected]69d80ae2009-12-23 08:57:421623#elif defined(OS_LINUX)
[email protected]96449d2c2009-11-25 00:01:321624 DCHECK(window());
1625 window()->SwapBuffers();
[email protected]43f28f832010-02-03 02:28:481626#elif defined(OS_MACOSX)
[email protected]3d1e89d2010-03-10 20:01:351627 // TODO(kbr): Need to property hook up and track the OpenGL state and hook
1628 // up the notion of the currently bound FBO.
1629 surface_.SwapBuffers();
[email protected]96449d2c2009-11-25 00:01:321630#endif
[email protected]43f28f832010-02-03 02:28:481631 if (swap_buffers_callback_.get()) {
1632 swap_buffers_callback_->Run();
1633 }
[email protected]96449d2c2009-11-25 00:01:321634}
1635
[email protected]3916c97e2010-02-25 03:20:501636void GLES2DecoderImpl::DoTexParameterf(
1637 GLenum target, GLenum pname, GLfloat param) {
1638 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:301639 if (!info) {
[email protected]3916c97e2010-02-25 03:20:501640 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:301641 } else {
[email protected]3916c97e2010-02-25 03:20:501642 info->SetParameter(pname, static_cast<GLint>(param));
1643 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:301644 }
1645}
1646
[email protected]3916c97e2010-02-25 03:20:501647void GLES2DecoderImpl::DoTexParameteri(
1648 GLenum target, GLenum pname, GLint param) {
1649 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1650 if (!info) {
1651 SetGLError(GL_INVALID_VALUE);
1652 } else {
1653 info->SetParameter(pname, param);
1654 glTexParameteri(target, pname, param);
1655 }
1656}
1657
1658void GLES2DecoderImpl::DoTexParameterfv(
1659 GLenum target, GLenum pname, const GLfloat* params) {
1660 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1661 if (!info) {
1662 SetGLError(GL_INVALID_VALUE);
1663 } else {
1664 info->SetParameter(pname, *reinterpret_cast<const GLint*>(params));
1665 glTexParameterfv(target, pname, params);
1666 }
1667}
1668
1669void GLES2DecoderImpl::DoTexParameteriv(
1670 GLenum target, GLenum pname, const GLint* params) {
1671 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1672 if (!info) {
1673 SetGLError(GL_INVALID_VALUE);
1674 } else {
1675 info->SetParameter(pname, *params);
1676 glTexParameteriv(target, pname, params);
1677 }
1678}
1679
1680void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
1681 if (!current_program_ || current_program_->IsDeleted()) {
1682 // The program does not exist.
1683 SetGLError(GL_INVALID_OPERATION);
1684 return;
1685 }
1686 current_program_->SetSamplers(location, 1, &v0);
1687 glUniform1i(location, v0);
1688}
1689
1690void GLES2DecoderImpl::DoUniform1iv(
1691 GLint location, GLsizei count, const GLint *value) {
1692 if (!current_program_ || current_program_->IsDeleted()) {
1693 // The program does not exist.
1694 SetGLError(GL_INVALID_OPERATION);
1695 return;
1696 }
1697 current_program_->SetSamplers(location, count, value);
1698 glUniform1iv(location, count, value);
1699}
1700
1701void GLES2DecoderImpl::DoUseProgram(GLuint program) {
1702 ProgramManager::ProgramInfo* info = NULL;
1703 if (program) {
1704 info = GetProgramInfo(program);
1705 if (!info) {
1706 // Program was not linked successfully. (ie, glLinkProgram)
1707 SetGLError(GL_INVALID_OPERATION);
1708 return;
1709 }
1710 }
1711 current_program_ = info;
1712 glUseProgram(program);
1713}
1714
[email protected]96449d2c2009-11-25 00:01:321715GLenum GLES2DecoderImpl::GetGLError() {
1716 // Check the GL error first, then our wrapped error.
1717 GLenum error = glGetError();
1718 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:371719 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:321720 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:291721 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:321722 break;
1723 }
1724 }
1725 }
1726
1727 if (error != GL_NO_ERROR) {
1728 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:291729 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:321730 }
1731 return error;
1732}
1733
1734void GLES2DecoderImpl::SetGLError(GLenum error) {
[email protected]ddd968b82010-03-02 00:44:291735 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:321736}
1737
[email protected]07f54fcc2009-12-22 02:46:301738void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
1739 GLenum error;
1740 while ((error = glGetError()) != GL_NO_ERROR) {
1741 SetGLError(error);
1742 }
1743}
1744
[email protected]07f54fcc2009-12-22 02:46:301745bool GLES2DecoderImpl::VertexAttribInfo::CanAccess(GLuint index) {
[email protected]3916c97e2010-02-25 03:20:501746 if (!enabled_) {
1747 return true;
1748 }
1749
1750 if (!buffer_ || buffer_->IsDeleted()) {
1751 return false;
1752 }
1753
1754 // The number of elements that can be accessed.
1755 GLsizeiptr buffer_size = buffer_->size();
1756 if (offset_ > buffer_size || real_stride_ == 0) {
1757 return false;
1758 }
1759
1760 uint32 usable_size = buffer_size - offset_;
1761 GLuint num_elements = usable_size / real_stride_ +
1762 ((usable_size % real_stride_) >=
1763 (GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type_) * size_) ? 1 : 0);
1764 return index < num_elements;
1765}
1766
1767void GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures(
1768 bool* has_non_renderable_textures) {
1769 DCHECK(has_non_renderable_textures);
1770 DCHECK(current_program_);
1771 DCHECK(!current_program_->IsDeleted());
1772 *has_non_renderable_textures = false;
1773 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
1774 current_program_->sampler_indices();
1775 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
1776 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
1777 current_program_->GetUniformInfo(sampler_indices[ii]);
1778 DCHECK(uniform_info);
1779 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
1780 GLuint texture_unit_index = uniform_info->texture_units[jj];
1781 if (texture_unit_index < group_->max_texture_units()) {
1782 TextureUnit& texture_unit = texture_units_[texture_unit_index];
1783 TextureManager::TextureInfo* texture_info =
1784 uniform_info->type == GL_SAMPLER_2D ?
1785 texture_unit.bound_texture_2d :
1786 texture_unit.bound_texture_cube_map;
1787 if (!texture_info || !texture_info->CanRender()) {
1788 *has_non_renderable_textures = true;
1789 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
1790 glBindTexture(
1791 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
1792 GL_TEXTURE_CUBE_MAP,
1793 uniform_info->type == GL_SAMPLER_2D ? black_2d_texture_id_ :
1794 black_cube_texture_id_);
1795 }
1796 }
1797 // else: should this be an error?
1798 }
1799 }
1800}
1801
1802void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
1803 DCHECK(current_program_);
1804 DCHECK(!current_program_->IsDeleted());
1805 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
1806 current_program_->sampler_indices();
1807 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
1808 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
1809 current_program_->GetUniformInfo(sampler_indices[ii]);
1810 DCHECK(uniform_info);
1811 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
1812 GLuint texture_unit_index = uniform_info->texture_units[jj];
1813 if (texture_unit_index < group_->max_texture_units()) {
1814 TextureUnit& texture_unit = texture_units_[texture_unit_index];
1815 TextureManager::TextureInfo* texture_info =
1816 uniform_info->type == GL_SAMPLER_2D ?
1817 texture_unit.bound_texture_2d :
1818 texture_unit.bound_texture_cube_map;
1819 if (!texture_info || !texture_info->CanRender()) {
1820 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
1821 // Get the texture info that was previously bound here.
1822 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
1823 texture_unit.bound_texture_2d :
1824 texture_unit.bound_texture_cube_map;
1825 glBindTexture(texture_unit.bind_target,
1826 texture_info ? texture_info->texture_id() : 0);
1827 }
1828 }
1829 }
1830 }
1831 // Set the active texture back to whatever the user had it as.
1832 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:301833}
1834
1835bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]3916c97e2010-02-25 03:20:501836 if (!current_program_ || current_program_->IsDeleted()) {
1837 // The program does not exist.
1838 // But GL says no ERROR.
1839 return false;
1840 }
1841 // Validate that all attribs current program needs are setup correctly.
1842 const ProgramManager::ProgramInfo::AttribInfoVector& infos =
1843 current_program_->GetAttribInfos();
1844 for (size_t ii = 0; ii < infos.size(); ++ii) {
1845 GLint location = infos[ii].location;
1846 if (location < 0) {
1847 return false;
1848 }
1849 DCHECK_LT(static_cast<GLuint>(location), group_->max_vertex_attribs());
1850 if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:461851 SetGLError(GL_INVALID_OPERATION);
1852 return false;
1853 }
[email protected]07f54fcc2009-12-22 02:46:301854 }
[email protected]3916c97e2010-02-25 03:20:501855 return true;
[email protected]07f54fcc2009-12-22 02:46:301856};
1857
[email protected]f7a64ee2010-02-01 22:24:141858error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:191859 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:501860 if (!bound_element_array_buffer_ ||
1861 bound_element_array_buffer_->IsDeleted()) {
1862 SetGLError(GL_INVALID_OPERATION);
1863 } else {
[email protected]96449d2c2009-11-25 00:01:321864 GLenum mode = c.mode;
1865 GLsizei count = c.count;
1866 GLenum type = c.type;
[email protected]1d32bc82010-01-13 22:06:461867 int32 offset = c.index_offset;
[email protected]a76b0052010-03-05 00:33:181868 if (count < 0 || offset < 0) {
[email protected]d2cf0a2d2010-02-25 21:36:121869 SetGLError(GL_INVALID_VALUE);
1870 } else if (!ValidateGLenumDrawMode(mode) ||
1871 !ValidateGLenumIndexType(type)) {
[email protected]1d32bc82010-01-13 22:06:461872 SetGLError(GL_INVALID_ENUM);
[email protected]ba3176a2009-12-16 18:19:461873 } else {
[email protected]0c86dbf2010-03-05 08:14:111874 GLuint max_vertex_accessed;
1875 if (!bound_element_array_buffer_->GetMaxValueForRange(
1876 offset, count, type, &max_vertex_accessed)) {
[email protected]1d32bc82010-01-13 22:06:461877 SetGLError(GL_INVALID_OPERATION);
1878 } else {
[email protected]0c86dbf2010-03-05 08:14:111879 if (IsDrawValid(max_vertex_accessed)) {
1880 bool has_non_renderable_textures;
1881 SetBlackTextureForNonRenderableTextures(
1882 &has_non_renderable_textures);
[email protected]3916c97e2010-02-25 03:20:501883 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]0c86dbf2010-03-05 08:14:111884 glDrawElements(mode, count, type, indices);
1885 if (has_non_renderable_textures) {
1886 RestoreStateForNonRenderableTextures();
[email protected]1d32bc82010-01-13 22:06:461887 }
1888 }
[email protected]07f54fcc2009-12-22 02:46:301889 }
[email protected]ba3176a2009-12-16 18:19:461890 }
[email protected]96449d2c2009-11-25 00:01:321891 }
[email protected]f7a64ee2010-02-01 22:24:141892 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321893}
1894
[email protected]96449d2c2009-11-25 00:01:321895// Calls glShaderSource for the various versions of the ShaderSource command.
1896// Assumes that data / data_size points to a piece of memory that is in range
1897// of whatever context it came from (shared memory, immediate memory, bucket
1898// memory.)
[email protected]45bf5152010-02-12 00:11:311899error::Error GLES2DecoderImpl::ShaderSourceHelper(
1900 GLuint shader, const char* data, uint32 data_size) {
1901 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
1902 if (!info) {
1903 SetGLError(GL_INVALID_OPERATION);
1904 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321905 }
[email protected]45bf5152010-02-12 00:11:311906 // Note: We don't actually call glShaderSource here. We wait until
1907 // the call to glCompileShader.
1908 info->Update(std::string(data, data + data_size));
[email protected]f7a64ee2010-02-01 22:24:141909 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:321910}
1911
[email protected]f7a64ee2010-02-01 22:24:141912error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:191913 uint32 immediate_data_size, const gles2::ShaderSource& c) {
1914 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:501915 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:191916 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141917 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191918 }
[email protected]96449d2c2009-11-25 00:01:321919 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:311920 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:321921 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:461922 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:141923 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:321924 }
[email protected]45bf5152010-02-12 00:11:311925 return ShaderSourceHelper(shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:321926}
1927
[email protected]f7a64ee2010-02-01 22:24:141928error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:191929 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
1930 GLuint shader;
[email protected]3916c97e2010-02-25 03:20:501931 if (!id_manager()->GetServiceId(c.shader, &shader)) {
[email protected]b9849abf2009-11-25 19:13:191932 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:141933 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:191934 }
[email protected]96449d2c2009-11-25 00:01:321935 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:311936 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:301937 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:461938 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:141939 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:321940 }
[email protected]45bf5152010-02-12 00:11:311941 return ShaderSourceHelper(shader, data, data_size);
1942}
1943
[email protected]558847a2010-03-24 07:02:541944error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
1945 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
1946 GLuint shader;
1947 if (!id_manager()->GetServiceId(c.shader, &shader)) {
1948 SetGLError(GL_INVALID_VALUE);
1949 return error::kNoError;
1950 }
1951 Bucket* bucket = GetBucket(c.data_bucket_id);
1952 if (!bucket || bucket->size() == 0) {
1953 return error::kInvalidArguments;
1954 }
1955 return ShaderSourceHelper(
1956 shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
1957 bucket->size() - 1);
1958}
1959
[email protected]45bf5152010-02-12 00:11:311960void GLES2DecoderImpl::DoCompileShader(GLuint shader) {
1961 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
1962 if (!info) {
1963 SetGLError(GL_INVALID_OPERATION);
1964 return;
1965 }
1966 // TODO(gman): Run shader through compiler that converts GL ES 2.0 shader
1967 // to DesktopGL shader and pass that to glShaderSource and then
1968 // glCompileShader.
1969 const char* ptr = info->source().c_str();
1970 glShaderSource(shader, 1, &ptr, NULL);
1971 glCompileShader(shader);
1972};
1973
[email protected]ddd968b82010-03-02 00:44:291974void GLES2DecoderImpl::DoGetShaderiv(
1975 GLuint shader, GLenum pname, GLint* params) {
1976 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
1977 if (!info) {
1978 SetGLError(GL_INVALID_OPERATION);
1979 return;
1980 }
1981 if (pname == GL_SHADER_SOURCE_LENGTH) {
1982 *params = info->source().size();
1983 } else {
1984 glGetShaderiv(shader, pname, params);
1985 }
1986}
1987
[email protected]45bf5152010-02-12 00:11:311988void GLES2DecoderImpl::DoGetShaderSource(
1989 GLuint shader, GLsizei bufsize, GLsizei* length, char* dst) {
1990 ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
1991 if (!info) {
1992 SetGLError(GL_INVALID_OPERATION);
1993 return;
1994 }
[email protected]a76b0052010-03-05 00:33:181995 // bufsize is set by the service side code and should always be positive.
1996 DCHECK_GT(bufsize, 0);
[email protected]45bf5152010-02-12 00:11:311997 const std::string& source = info->source();
1998 GLsizei size = std::min(bufsize - 1, static_cast<GLsizei>(source.size()));
1999 if (length) {
2000 *length = size;
2001 }
2002 memcpy(dst, source.c_str(), size);
2003 dst[size] = '\0';
[email protected]96449d2c2009-11-25 00:01:322004}
2005
[email protected]f7a64ee2010-02-01 22:24:142006error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:192007 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]3916c97e2010-02-25 03:20:502008 if (bound_array_buffer_ && !bound_array_buffer_->IsDeleted()) {
[email protected]96449d2c2009-11-25 00:01:322009 GLuint indx = c.indx;
2010 GLint size = c.size;
2011 GLenum type = c.type;
2012 GLboolean normalized = c.normalized;
2013 GLsizei stride = c.stride;
[email protected]07f54fcc2009-12-22 02:46:302014 GLsizei offset = c.offset;
2015 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]ba3176a2009-12-16 18:19:462016 if (!ValidateGLenumVertexAttribType(type) ||
[email protected]d2cf0a2d2010-02-25 21:36:122017 !ValidateGLintVertexAttribSize(size)) {
2018 SetGLError(GL_INVALID_ENUM);
2019 return error::kNoError;
2020 }
2021 if (indx >= group_->max_vertex_attribs() ||
2022 stride < 0 ||
2023 offset < 0) {
[email protected]ba3176a2009-12-16 18:19:462024 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142025 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322026 }
[email protected]3916c97e2010-02-25 03:20:502027 GLsizei component_size =
2028 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]07f54fcc2009-12-22 02:46:302029 GLsizei real_stride = stride != 0 ? stride : component_size * size;
2030 if (offset % component_size > 0) {
2031 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142032 return error::kNoError;
[email protected]07f54fcc2009-12-22 02:46:302033 }
2034 vertex_attrib_infos_[indx].SetInfo(
2035 bound_array_buffer_,
[email protected]07f54fcc2009-12-22 02:46:302036 size,
2037 type,
2038 real_stride,
2039 offset);
[email protected]96449d2c2009-11-25 00:01:322040 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
2041 } else {
2042 SetGLError(GL_INVALID_VALUE);
2043 }
[email protected]f7a64ee2010-02-01 22:24:142044 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322045}
2046
[email protected]f7a64ee2010-02-01 22:24:142047error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:192048 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:312049 GLint x = c.x;
2050 GLint y = c.y;
2051 GLsizei width = c.width;
2052 GLsizei height = c.height;
2053 GLenum format = c.format;
2054 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:562055 if (width < 0 || height < 0) {
2056 SetGLError(GL_INVALID_VALUE);
2057 return error::kNoError;
2058 }
[email protected]a51788e2010-02-24 21:54:252059 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:182060 uint32 pixels_size;
2061 if (!GLES2Util::ComputeImageDataSize(
2062 width, height, format, type, pack_alignment_, &pixels_size)) {
2063 return error::kOutOfBounds;
2064 }
[email protected]612d2f82009-12-08 20:49:312065 void* pixels = GetSharedMemoryAs<void*>(
2066 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:252067 Result* result = GetSharedMemoryAs<Result*>(
2068 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2069 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:142070 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462071 }
[email protected]a51788e2010-02-24 21:54:252072
[email protected]ba3176a2009-12-16 18:19:462073 if (!ValidateGLenumReadPixelFormat(format) ||
2074 !ValidateGLenumPixelType(type)) {
[email protected]d2cf0a2d2010-02-25 21:36:122075 SetGLError(GL_INVALID_ENUM);
2076 return error::kNoError;
2077 }
[email protected]57f223832010-03-19 01:57:562078 if (width == 0 || height == 0) {
2079 return error::kNoError;
2080 }
2081
2082 CopyRealGLErrorsToWrapper();
2083
2084 // Get the size of the current fbo or backbuffer.
2085 GLsizei max_width = 0;
2086 GLsizei max_height = 0;
2087 if (bound_framebuffer_ != 0) {
2088 // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
2089 // stencil.
2090 GLint fb_type = 0;
2091 glGetFramebufferAttachmentParameterivEXT(
2092 GL_FRAMEBUFFER,
2093 GL_COLOR_ATTACHMENT0,
2094 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
2095 &fb_type);
2096 switch (fb_type) {
2097 case GL_RENDERBUFFER:
2098 {
2099 GLint renderbuffer_id = 0;
2100 glGetFramebufferAttachmentParameterivEXT(
2101 GL_FRAMEBUFFER,
2102 GL_COLOR_ATTACHMENT0,
2103 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
2104 &renderbuffer_id);
2105 if (renderbuffer_id != 0) {
2106 glGetRenderbufferParameterivEXT(
2107 GL_RENDERBUFFER,
2108 GL_RENDERBUFFER_WIDTH,
2109 &max_width);
2110 glGetRenderbufferParameterivEXT(
2111 GL_RENDERBUFFER,
2112 GL_RENDERBUFFER_HEIGHT,
2113 &max_height);
2114 }
2115 break;
2116 }
2117 case GL_TEXTURE:
2118 {
2119 GLint texture_id = 0;
2120 glGetFramebufferAttachmentParameterivEXT(
2121 GL_FRAMEBUFFER,
2122 GL_COLOR_ATTACHMENT0,
2123 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
2124 &texture_id);
2125 if (texture_id != 0) {
2126 TextureManager::TextureInfo* texture_info =
2127 GetTextureInfo(texture_id);
2128 if (texture_info) {
2129 GLint level = 0;
2130 GLint face = 0;
2131 glGetFramebufferAttachmentParameterivEXT(
2132 GL_FRAMEBUFFER,
2133 GL_COLOR_ATTACHMENT0,
2134 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
2135 &level);
2136 glGetFramebufferAttachmentParameterivEXT(
2137 GL_FRAMEBUFFER,
2138 GL_COLOR_ATTACHMENT0,
2139 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
2140 &face);
2141 texture_info->GetLevelSize(
2142 face ? face : GL_TEXTURE_2D, level, &max_width, &max_height);
2143 }
2144 }
2145 break;
2146 }
2147 default:
2148 // unknown so assume max_width = 0.
2149 break;
2150 }
2151 } else {
2152 // TODO(gman): Get these values from the proper place.
2153 max_width = 300;
2154 max_height = 150;
2155 }
2156
2157 GLint max_x;
2158 GLint max_y;
2159 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]ba3176a2009-12-16 18:19:462160 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142161 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:312162 }
[email protected]57f223832010-03-19 01:57:562163
2164 if (x < 0 || y < 0 || max_x > max_width || max_y > max_height) {
2165 // The user requested an out of range area. Get the results 1 line
2166 // at a time.
2167 uint32 temp_size;
2168 if (!GLES2Util::ComputeImageDataSize(
2169 width, 1, format, type, pack_alignment_, &temp_size)) {
2170 SetGLError(GL_INVALID_VALUE);
2171 return error::kNoError;
2172 }
2173 GLsizei unpadded_row_size = temp_size;
2174 if (!GLES2Util::ComputeImageDataSize(
2175 width, 2, format, type, pack_alignment_, &temp_size)) {
2176 SetGLError(GL_INVALID_VALUE);
2177 return error::kNoError;
2178 }
2179 GLsizei padded_row_size = temp_size - unpadded_row_size;
2180 if (padded_row_size < 0 || unpadded_row_size < 0) {
2181 SetGLError(GL_INVALID_VALUE);
2182 return error::kNoError;
2183 }
2184
2185 GLint dest_x_offset = std::max(-x, 0);
2186 uint32 dest_row_offset;
2187 if (!GLES2Util::ComputeImageDataSize(
2188 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
2189 SetGLError(GL_INVALID_VALUE);
2190 return error::kNoError;
2191 }
2192
2193 // Copy each row into the larger dest rect.
2194 int8* dst = static_cast<int8*>(pixels);
2195 GLint read_x = std::max(0, x);
2196 GLint read_end_x = std::max(0, std::min(max_width, max_x));
2197 GLint read_width = read_end_x - read_x;
2198 for (GLint yy = 0; yy < height; ++yy) {
2199 GLint ry = y + yy;
2200
2201 // Clear the row.
2202 memset(dst, 0, unpadded_row_size);
2203
2204 // If the row is in range, copy it.
2205 if (ry >= 0 && ry < max_height && read_width > 0) {
2206 glReadPixels(
2207 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
2208 }
2209 dst += padded_row_size;
2210 }
2211 } else {
2212 glReadPixels(x, y, width, height, format, type, pixels);
2213 }
[email protected]a51788e2010-02-24 21:54:252214 GLenum error = glGetError();
2215 if (error == GL_NO_ERROR) {
2216 *result = true;
2217 } else {
2218 SetGLError(error);
2219 }
[email protected]f7a64ee2010-02-01 22:24:142220 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322221}
2222
[email protected]f7a64ee2010-02-01 22:24:142223error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:192224 uint32 immediate_data_size, const gles2::PixelStorei& c) {
2225 GLenum pname = c.pname;
2226 GLenum param = c.param;
[email protected]d2cf0a2d2010-02-25 21:36:122227 if (!ValidateGLenumPixelStore(pname)) {
2228 SetGLError(GL_INVALID_ENUM);
2229 return error::kNoError;
2230 }
2231 if (!ValidateGLintPixelStoreAlignment(param)) {
[email protected]ba3176a2009-12-16 18:19:462232 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142233 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192234 }
2235 glPixelStorei(pname, param);
2236 switch (pname) {
2237 case GL_PACK_ALIGNMENT:
2238 pack_alignment_ = param;
2239 break;
2240 case GL_UNPACK_ALIGNMENT:
2241 unpack_alignment_ = param;
2242 break;
2243 default:
2244 // Validation should have prevented us from getting here.
2245 DCHECK(false);
2246 break;
2247 }
[email protected]f7a64ee2010-02-01 22:24:142248 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192249}
2250
[email protected]558847a2010-03-24 07:02:542251error::Error GLES2DecoderImpl::GetAttribLocationHelper(
2252 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
2253 const std::string& name_str) {
[email protected]b9849abf2009-11-25 19:13:192254 GLuint program;
[email protected]558847a2010-03-24 07:02:542255 if (!id_manager()->GetServiceId(client_id, &program)) {
[email protected]b9849abf2009-11-25 19:13:192256 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142257 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192258 }
[email protected]0bfd9882010-02-05 23:02:252259 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2260 if (!info) {
2261 // Program was not linked successfully. (ie, glLinkProgram)
2262 SetGLError(GL_INVALID_OPERATION);
2263 return error::kNoError;
2264 }
[email protected]b9849abf2009-11-25 19:13:192265 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:542266 location_shm_id, location_shm_offset, sizeof(GLint));
2267 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:142268 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192269 }
[email protected]558847a2010-03-24 07:02:542270 // Require the client to init this incase the context is lost and we are no
2271 // longer executing commands.
2272 if (*location != -1) {
2273 return error::kGenericError;
2274 }
[email protected]0bfd9882010-02-05 23:02:252275 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142276 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192277}
2278
[email protected]558847a2010-03-24 07:02:542279error::Error GLES2DecoderImpl::HandleGetAttribLocation(
2280 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
2281 uint32 name_size = c.data_size;
2282 const char* name = GetSharedMemoryAs<const char*>(
2283 c.name_shm_id, c.name_shm_offset, name_size);
2284 if (!name) {
2285 return error::kOutOfBounds;
2286 }
2287 String name_str(name, name_size);
2288 return GetAttribLocationHelper(
2289 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2290}
2291
[email protected]f7a64ee2010-02-01 22:24:142292error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192293 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:542294 uint32 name_size = c.data_size;
2295 const char* name = GetImmediateDataAs<const char*>(
2296 c, name_size, immediate_data_size);
2297 if (!name) {
2298 return error::kOutOfBounds;
2299 }
2300 String name_str(name, name_size);
2301 return GetAttribLocationHelper(
2302 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2303}
2304
2305error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
2306 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
2307 Bucket* bucket = GetBucket(c.name_bucket_id);
2308 if (!bucket) {
2309 return error::kInvalidArguments;
2310 }
2311 std::string name_str;
2312 bucket->GetAsString(&name_str);
2313 return GetAttribLocationHelper(
2314 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2315}
2316
2317error::Error GLES2DecoderImpl::GetUniformLocationHelper(
2318 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
2319 const std::string& name_str) {
[email protected]b9849abf2009-11-25 19:13:192320 GLuint program;
[email protected]558847a2010-03-24 07:02:542321 if (!id_manager()->GetServiceId(client_id, &program)) {
[email protected]b9849abf2009-11-25 19:13:192322 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142323 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192324 }
[email protected]0bfd9882010-02-05 23:02:252325 ProgramManager::ProgramInfo* info = GetProgramInfo(program);
2326 if (!info) {
2327 // Program was not linked successfully. (ie, glLinkProgram)
2328 SetGLError(GL_INVALID_OPERATION);
2329 return error::kNoError;
2330 }
[email protected]b9849abf2009-11-25 19:13:192331 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:542332 location_shm_id, location_shm_offset, sizeof(GLint));
2333 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:142334 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192335 }
[email protected]558847a2010-03-24 07:02:542336 // Require the client to init this incase the context is lost an we are no
2337 // longer executing commands.
2338 if (*location != -1) {
2339 return error::kGenericError;
2340 }
2341 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:142342 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192343}
2344
[email protected]f7a64ee2010-02-01 22:24:142345error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:192346 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:192347 uint32 name_size = c.data_size;
2348 const char* name = GetSharedMemoryAs<const char*>(
2349 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:542350 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:142351 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192352 }
2353 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:542354 return GetUniformLocationHelper(
2355 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:192356}
2357
[email protected]f7a64ee2010-02-01 22:24:142358error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:192359 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:192360 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:302361 const char* name = GetImmediateDataAs<const char*>(
2362 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:542363 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:142364 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192365 }
2366 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:542367 return GetUniformLocationHelper(
2368 c.program, c.location_shm_id, c.location_shm_offset, name_str);
2369}
2370
2371error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
2372 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
2373 Bucket* bucket = GetBucket(c.name_bucket_id);
2374 if (!bucket) {
2375 return error::kInvalidArguments;
2376 }
2377 std::string name_str;
2378 bucket->GetAsString(&name_str);
2379 return GetUniformLocationHelper(
2380 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:192381}
2382
[email protected]ddd968b82010-03-02 00:44:292383error::Error GLES2DecoderImpl::HandleGetString(
2384 uint32 immediate_data_size, const gles2::GetString& c) {
2385 GLenum name = static_cast<GLenum>(c.name);
2386 if (!ValidateGLenumStringType(name)) {
2387 SetGLError(GL_INVALID_ENUM);
2388 return error::kNoError;
2389 }
2390 Bucket* bucket = CreateBucket(c.bucket_id);
2391 bucket->SetFromString(reinterpret_cast<const char*>(glGetString(name)));
2392 return error::kNoError;
2393}
2394
[email protected]0c86dbf2010-03-05 08:14:112395void GLES2DecoderImpl::DoBufferData(
2396 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]3b6ec202010-03-05 05:16:232397 if (!ValidateGLenumBufferTarget(target) ||
2398 !ValidateGLenumBufferUsage(usage)) {
2399 SetGLError(GL_INVALID_ENUM);
[email protected]0c86dbf2010-03-05 08:14:112400 return;
[email protected]3b6ec202010-03-05 05:16:232401 }
2402 if (size < 0) {
2403 SetGLError(GL_INVALID_VALUE);
[email protected]0c86dbf2010-03-05 08:14:112404 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232405 }
2406 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
2407 if (!info) {
2408 SetGLError(GL_INVALID_OPERATION);
[email protected]0c86dbf2010-03-05 08:14:112409 DoBufferData(target, size, data, usage);
[email protected]3b6ec202010-03-05 05:16:232410 }
2411 // Clear the buffer to 0 if no initial data was passed in.
2412 scoped_array<int8> zero;
2413 if (!data) {
2414 zero.reset(new int8[size]);
2415 memset(zero.get(), 0, size);
2416 data = zero.get();
2417 }
2418 CopyRealGLErrorsToWrapper();
2419 glBufferData(target, size, data, usage);
2420 GLenum error = glGetError();
2421 if (error != GL_NO_ERROR) {
2422 SetGLError(error);
2423 } else {
[email protected]0c86dbf2010-03-05 08:14:112424 info->SetSize(size);
2425 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:232426 }
[email protected]0c86dbf2010-03-05 08:14:112427}
2428
2429error::Error GLES2DecoderImpl::HandleBufferData(
2430 uint32 immediate_data_size, const gles2::BufferData& c) {
2431 GLenum target = static_cast<GLenum>(c.target);
2432 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
2433 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
2434 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
2435 GLenum usage = static_cast<GLenum>(c.usage);
2436 const void* data = NULL;
2437 if (data_shm_id != 0 || data_shm_offset != 0) {
2438 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
2439 if (!data) {
2440 return error::kOutOfBounds;
2441 }
2442 }
2443 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:142444 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192445}
2446
[email protected]f7a64ee2010-02-01 22:24:142447error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:192448 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
2449 GLenum target = static_cast<GLenum>(c.target);
2450 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:302451 const void* data = GetImmediateDataAs<const void*>(
2452 c, size, immediate_data_size);
2453 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142454 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:302455 }
[email protected]b9849abf2009-11-25 19:13:192456 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:112457 DoBufferData(target, size, data, usage);
2458 return error::kNoError;
2459}
2460
2461void GLES2DecoderImpl::DoBufferSubData(
2462 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:502463 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472464 if (!info) {
2465 SetGLError(GL_INVALID_OPERATION);
[email protected]a93bb842010-02-16 23:03:472466 }
[email protected]0c86dbf2010-03-05 08:14:112467 if (!info->SetRange(offset, size, data)) {
2468 SetGLError(GL_INVALID_VALUE);
[email protected]07f54fcc2009-12-22 02:46:302469 } else {
[email protected]0c86dbf2010-03-05 08:14:112470 glBufferSubData(target, offset, size, data);
[email protected]07f54fcc2009-12-22 02:46:302471 }
[email protected]b9849abf2009-11-25 19:13:192472}
2473
[email protected]a93bb842010-02-16 23:03:472474error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
2475 GLenum target,
2476 GLint level,
2477 GLenum internal_format,
2478 GLsizei width,
2479 GLsizei height,
2480 GLint border,
2481 GLsizei image_size,
2482 const void* data) {
[email protected]a93bb842010-02-16 23:03:472483 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]86093972010-03-11 00:13:562484 if (!ValidateGLenumTextureTarget(target) ||
2485 !ValidateGLenumCompressedTextureInternalFormat(internal_format)) {
[email protected]a93bb842010-02-16 23:03:472486 SetGLError(GL_INVALID_ENUM);
2487 return error::kNoError;
2488 }
[email protected]3916c97e2010-02-25 03:20:502489 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:472490 border != 0) {
2491 SetGLError(GL_INVALID_VALUE);
2492 return error::kNoError;
2493 }
[email protected]3916c97e2010-02-25 03:20:502494 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472495 if (!info) {
2496 SetGLError(GL_INVALID_OPERATION);
2497 return error::kNoError;
2498 }
2499 scoped_array<int8> zero;
2500 if (!data) {
2501 zero.reset(new int8[image_size]);
2502 memset(zero.get(), 0, image_size);
2503 data = zero.get();
2504 }
2505 info->SetLevelInfo(
2506 target, level, internal_format, width, height, 1, border, 0, 0);
2507 glCompressedTexImage2D(
2508 target, level, internal_format, width, height, border, image_size, data);
2509 return error::kNoError;
2510}
2511
[email protected]f7a64ee2010-02-01 22:24:142512error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192513 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
2514 GLenum target = static_cast<GLenum>(c.target);
2515 GLint level = static_cast<GLint>(c.level);
2516 GLenum internal_format = static_cast<GLenum>(c.internalformat);
2517 GLsizei width = static_cast<GLsizei>(c.width);
2518 GLsizei height = static_cast<GLsizei>(c.height);
2519 GLint border = static_cast<GLint>(c.border);
2520 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
2521 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
2522 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
2523 const void* data = NULL;
2524 if (data_shm_id != 0 || data_shm_offset != 0) {
2525 data = GetSharedMemoryAs<const void*>(
2526 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:462527 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142528 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192529 }
2530 }
[email protected]a93bb842010-02-16 23:03:472531 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192532 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:192533}
2534
[email protected]f7a64ee2010-02-01 22:24:142535error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:192536 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
2537 GLenum target = static_cast<GLenum>(c.target);
2538 GLint level = static_cast<GLint>(c.level);
2539 GLenum internal_format = static_cast<GLenum>(c.internalformat);
2540 GLsizei width = static_cast<GLsizei>(c.width);
2541 GLsizei height = static_cast<GLsizei>(c.height);
2542 GLint border = static_cast<GLint>(c.border);
2543 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:302544 const void* data = GetImmediateDataAs<const void*>(
2545 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462546 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:142547 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462548 }
[email protected]a93bb842010-02-16 23:03:472549 return DoCompressedTexImage2D(
2550 target, level, internal_format, width, height, border, image_size, data);
2551}
2552
[email protected]a93bb842010-02-16 23:03:472553error::Error GLES2DecoderImpl::DoTexImage2D(
2554 GLenum target,
2555 GLint level,
2556 GLenum internal_format,
2557 GLsizei width,
2558 GLsizei height,
2559 GLint border,
2560 GLenum format,
2561 GLenum type,
2562 const void* pixels,
2563 uint32 pixels_size) {
2564 if (!ValidateGLenumTextureTarget(target) ||
2565 !ValidateGLenumTextureFormat(internal_format) ||
2566 !ValidateGLenumTextureFormat(format) ||
2567 !ValidateGLenumPixelType(type)) {
[email protected]8bf5a3e2010-01-29 04:21:362568 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:142569 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192570 }
[email protected]3916c97e2010-02-25 03:20:502571 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:472572 border != 0) {
2573 SetGLError(GL_INVALID_VALUE);
2574 return error::kNoError;
2575 }
[email protected]3916c97e2010-02-25 03:20:502576 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:472577 if (!info) {
2578 SetGLError(GL_INVALID_OPERATION);
2579 return error::kNoError;
2580 }
2581 scoped_array<int8> zero;
2582 if (!pixels) {
2583 zero.reset(new int8[pixels_size]);
2584 memset(zero.get(), 0, pixels_size);
2585 pixels = zero.get();
2586 }
2587 info->SetLevelInfo(
2588 target, level, internal_format, width, height, 1, border, format, type);
2589 glTexImage2D(
2590 target, level, internal_format, width, height, border, format, type,
2591 pixels);
[email protected]f7a64ee2010-02-01 22:24:142592 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192593}
2594
[email protected]f7a64ee2010-02-01 22:24:142595error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192596 uint32 immediate_data_size, const gles2::TexImage2D& c) {
2597 GLenum target = static_cast<GLenum>(c.target);
2598 GLint level = static_cast<GLint>(c.level);
2599 GLint internal_format = static_cast<GLint>(c.internalformat);
2600 GLsizei width = static_cast<GLsizei>(c.width);
2601 GLsizei height = static_cast<GLsizei>(c.height);
2602 GLint border = static_cast<GLint>(c.border);
2603 GLenum format = static_cast<GLenum>(c.format);
2604 GLenum type = static_cast<GLenum>(c.type);
2605 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
2606 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:182607 uint32 pixels_size;
2608 if (!GLES2Util::ComputeImageDataSize(
2609 width, height, format, type, unpack_alignment_, &pixels_size)) {
2610 return error::kOutOfBounds;
2611 }
[email protected]b9849abf2009-11-25 19:13:192612 const void* pixels = NULL;
2613 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
2614 pixels = GetSharedMemoryAs<const void*>(
2615 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:462616 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:142617 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:192618 }
2619 }
[email protected]a93bb842010-02-16 23:03:472620 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:192621 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:472622 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:192623}
2624
[email protected]f7a64ee2010-02-01 22:24:142625error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:192626 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
2627 GLenum target = static_cast<GLenum>(c.target);
2628 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:462629 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:192630 GLsizei width = static_cast<GLsizei>(c.width);
2631 GLsizei height = static_cast<GLsizei>(c.height);
2632 GLint border = static_cast<GLint>(c.border);
2633 GLenum format = static_cast<GLenum>(c.format);
2634 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:182635 uint32 size;
2636 if (!GLES2Util::ComputeImageDataSize(
2637 width, height, format, type, unpack_alignment_, &size)) {
2638 return error::kOutOfBounds;
2639 }
[email protected]07f54fcc2009-12-22 02:46:302640 const void* pixels = GetImmediateDataAs<const void*>(
2641 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:462642 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:142643 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:462644 }
[email protected]a93bb842010-02-16 23:03:472645 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:462646 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:472647 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:142648 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322649}
2650
[email protected]f7a64ee2010-02-01 22:24:142651error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:192652 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:362653 GLuint index = static_cast<GLuint>(c.index);
2654 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:252655 typedef gles2::GetVertexAttribPointerv::Result Result;
2656 Result* result = GetSharedMemoryAs<Result*>(
2657 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:362658 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:142659 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:362660 }
[email protected]07d0cc82010-02-17 04:51:402661 // Check that the client initialized the result.
2662 if (result->size != 0) {
2663 return error::kInvalidArguments;
2664 }
[email protected]8bf5a3e2010-01-29 04:21:362665 if (!ValidateGLenumVertexPointer(pname)) {
2666 SetGLError(GL_INVALID_ENUM);
[email protected]f7a64ee2010-02-01 22:24:142667 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:362668 }
[email protected]3916c97e2010-02-25 03:20:502669 if (index >= group_->max_vertex_attribs()) {
[email protected]8bf5a3e2010-01-29 04:21:362670 SetGLError(GL_INVALID_VALUE);
[email protected]f7a64ee2010-02-01 22:24:142671 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:362672 }
[email protected]0bfd9882010-02-05 23:02:252673 result->SetNumResults(1);
2674 *result->GetData() = vertex_attrib_infos_[index].offset();
[email protected]f7a64ee2010-02-01 22:24:142675 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322676}
2677
[email protected]f7b85372010-02-03 01:11:372678bool GLES2DecoderImpl::GetUniformSetup(
2679 GLuint program, GLint location,
2680 uint32 shm_id, uint32 shm_offset,
[email protected]0bfd9882010-02-05 23:02:252681 error::Error* error, GLuint* service_id, void** result_pointer) {
[email protected]f7b85372010-02-03 01:11:372682 *error = error::kNoError;
2683 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:252684 SizedResult<GLint>* result;
2685 result = GetSharedMemoryAs<SizedResult<GLint>*>(
2686 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
2687 if (!result) {
[email protected]f7b85372010-02-03 01:11:372688 *error = error::kOutOfBounds;
2689 return false;
2690 }
[email protected]0bfd9882010-02-05 23:02:252691 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:372692 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:252693 result->SetNumResults(0);
[email protected]3916c97e2010-02-25 03:20:502694 if (!id_manager()->GetServiceId(program, service_id)) {
[email protected]f7b85372010-02-03 01:11:372695 SetGLError(GL_INVALID_VALUE);
2696 return error::kNoError;
2697 }
2698 ProgramManager::ProgramInfo* info = GetProgramInfo(*service_id);
2699 if (!info) {
2700 // Program was not linked successfully. (ie, glLinkProgram)
2701 SetGLError(GL_INVALID_OPERATION);
2702 return false;
2703 }
[email protected]0bfd9882010-02-05 23:02:252704 GLenum type;
2705 if (!info->GetUniformTypeByLocation(location, &type)) {
[email protected]f7b85372010-02-03 01:11:372706 // No such location.
2707 SetGLError(GL_INVALID_OPERATION);
2708 return false;
2709 }
[email protected]3916c97e2010-02-25 03:20:502710 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:372711 if (size == 0) {
2712 SetGLError(GL_INVALID_OPERATION);
2713 return false;
2714 }
[email protected]0bfd9882010-02-05 23:02:252715 result = GetSharedMemoryAs<SizedResult<GLint>*>(
2716 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
2717 if (!result) {
[email protected]f7b85372010-02-03 01:11:372718 *error = error::kOutOfBounds;
2719 return false;
2720 }
[email protected]0bfd9882010-02-05 23:02:252721 result->size = size;
[email protected]f7b85372010-02-03 01:11:372722 return true;
2723}
2724
[email protected]f7a64ee2010-02-01 22:24:142725error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:192726 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:372727 GLuint program = c.program;
2728 GLint location = c.location;
2729 GLuint service_id;
2730 Error error;
[email protected]0bfd9882010-02-05 23:02:252731 void* result;
[email protected]f7b85372010-02-03 01:11:372732 if (GetUniformSetup(
2733 program, location, c.params_shm_id, c.params_shm_offset,
2734 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:252735 glGetUniformiv(
2736 service_id, location,
2737 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:372738 }
2739 return error;
[email protected]96449d2c2009-11-25 00:01:322740}
2741
[email protected]f7a64ee2010-02-01 22:24:142742error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:192743 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:372744 GLuint program = c.program;
2745 GLint location = c.location;
2746 GLuint service_id;
2747 Error error;
[email protected]0bfd9882010-02-05 23:02:252748 void* result;
2749 typedef gles2::GetUniformfv::Result Result;
[email protected]f7b85372010-02-03 01:11:372750 if (GetUniformSetup(
2751 program, location, c.params_shm_id, c.params_shm_offset,
2752 &error, &service_id, &result)) {
[email protected]0bfd9882010-02-05 23:02:252753 glGetUniformfv(
2754 service_id,
2755 location,
2756 static_cast<gles2::GetUniformfv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:372757 }
2758 return error;
[email protected]96449d2c2009-11-25 00:01:322759}
2760
[email protected]f7a64ee2010-02-01 22:24:142761error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:192762 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:252763 GLenum shader_type = static_cast<GLenum>(c.shadertype);
2764 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
2765 typedef gles2::GetShaderPrecisionFormat::Result Result;
2766 Result* result = GetSharedMemoryAs<Result*>(
2767 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2768 if (!result) {
2769 return error::kOutOfBounds;
2770 }
[email protected]07d0cc82010-02-17 04:51:402771 // Check that the client initialized the result.
2772 if (result->success != 0) {
2773 return error::kInvalidArguments;
2774 }
[email protected]0bfd9882010-02-05 23:02:252775 if (!ValidateGLenumShaderType(shader_type) ||
2776 !ValidateGLenumShaderPrecision(precision_type)) {
[email protected]0bfd9882010-02-05 23:02:252777 SetGLError(GL_INVALID_ENUM);
2778 } else {
2779 result->success = 1; // true
2780 switch (precision_type) {
2781 case GL_LOW_INT:
2782 case GL_MEDIUM_INT:
2783 case GL_HIGH_INT:
2784 result->min_range = -31;
2785 result->max_range = 31;
2786 result->precision = 0;
2787 case GL_LOW_FLOAT:
2788 case GL_MEDIUM_FLOAT:
2789 case GL_HIGH_FLOAT:
2790 result->min_range = -62;
2791 result->max_range = 62;
2792 result->precision = -16;
2793 break;
2794 default:
2795 NOTREACHED();
2796 break;
2797 }
2798 }
[email protected]f7a64ee2010-02-01 22:24:142799 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322800}
2801
[email protected]f7a64ee2010-02-01 22:24:142802error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:192803 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:252804 GLuint service_id;
2805 uint32 result_size = c.result_size;
[email protected]3916c97e2010-02-25 03:20:502806 if (!id_manager()->GetServiceId(c.program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252807 SetGLError(GL_INVALID_VALUE);
2808 return error::kNoError;
2809 }
2810 typedef gles2::GetAttachedShaders::Result Result;
2811 uint32 max_count = Result::ComputeMaxResults(result_size);
2812 Result* result = GetSharedMemoryAs<Result*>(
2813 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
2814 if (!result) {
2815 return error::kOutOfBounds;
2816 }
[email protected]07d0cc82010-02-17 04:51:402817 // Check that the client initialized the result.
2818 if (result->size != 0) {
2819 return error::kInvalidArguments;
2820 }
[email protected]0bfd9882010-02-05 23:02:252821 GLsizei count = 0;
2822 glGetAttachedShaders(service_id, max_count, &count, result->GetData());
2823 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]3916c97e2010-02-25 03:20:502824 if (!id_manager()->GetClientId(result->GetData()[ii],
[email protected]0bfd9882010-02-05 23:02:252825 &result->GetData()[ii])) {
2826 NOTREACHED();
2827 return error::kGenericError;
2828 }
2829 }
2830 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:142831 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322832}
2833
[email protected]f7a64ee2010-02-01 22:24:142834error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:192835 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:252836 GLuint program = c.program;
2837 GLuint index = c.index;
2838 uint32 name_bucket_id = c.name_bucket_id;
2839 GLuint service_id;
2840 typedef gles2::GetActiveUniform::Result Result;
2841 Result* result = GetSharedMemoryAs<Result*>(
2842 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2843 if (!result) {
2844 return error::kOutOfBounds;
2845 }
[email protected]07d0cc82010-02-17 04:51:402846 // Check that the client initialized the result.
2847 if (result->success != 0) {
2848 return error::kInvalidArguments;
2849 }
[email protected]3916c97e2010-02-25 03:20:502850 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252851 SetGLError(GL_INVALID_VALUE);
2852 return error::kNoError;
2853 }
2854 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
2855 if (!info) {
2856 // Program was not linked successfully. (ie, glLinkProgram)
2857 SetGLError(GL_INVALID_OPERATION);
2858 return error::kNoError;
2859 }
2860 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
2861 info->GetUniformInfo(index);
2862 if (!uniform_info) {
2863 SetGLError(GL_INVALID_VALUE);
2864 return error::kNoError;
2865 }
2866 result->success = 1; // true.
2867 result->size = uniform_info->size;
2868 result->type = uniform_info->type;
2869 Bucket* bucket = CreateBucket(name_bucket_id);
2870 bucket->SetFromString(uniform_info->name);
[email protected]f7a64ee2010-02-01 22:24:142871 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322872}
2873
[email protected]f7a64ee2010-02-01 22:24:142874error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:192875 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:252876 GLuint program = c.program;
2877 GLuint index = c.index;
2878 uint32 name_bucket_id = c.name_bucket_id;
2879 GLuint service_id;
2880 typedef gles2::GetActiveAttrib::Result Result;
2881 Result* result = GetSharedMemoryAs<Result*>(
2882 c.result_shm_id, c.result_shm_offset, sizeof(*result));
2883 if (!result) {
2884 return error::kOutOfBounds;
2885 }
[email protected]07d0cc82010-02-17 04:51:402886 // Check that the client initialized the result.
2887 if (result->success != 0) {
2888 return error::kInvalidArguments;
2889 }
[email protected]3916c97e2010-02-25 03:20:502890 if (!id_manager()->GetServiceId(program, &service_id)) {
[email protected]0bfd9882010-02-05 23:02:252891 SetGLError(GL_INVALID_VALUE);
2892 return error::kNoError;
2893 }
2894 ProgramManager::ProgramInfo* info = GetProgramInfo(service_id);
2895 if (!info) {
2896 // Program was not linked successfully. (ie, glLinkProgram)
2897 SetGLError(GL_INVALID_OPERATION);
2898 return error::kNoError;
2899 }
2900 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
2901 info->GetAttribInfo(index);
2902 if (!attrib_info) {
2903 SetGLError(GL_INVALID_VALUE);
2904 return error::kNoError;
2905 }
2906 result->success = 1; // true.
2907 result->size = attrib_info->size;
2908 result->type = attrib_info->type;
2909 Bucket* bucket = CreateBucket(name_bucket_id);
2910 bucket->SetFromString(attrib_info->name);
[email protected]f7a64ee2010-02-01 22:24:142911 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:322912}
2913
2914// Include the auto-generated part of this file. We split this because it means
2915// we can easily edit the non-auto generated parts right here in this file
2916// instead of having to edit some template or the code generator.
2917#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
2918
2919} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:252920} // namespace gpu