Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blobff0a04f74cd9a4a81c26171d1c248bc7857d6951
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
7 #include <stdio.h>
9 #include <algorithm>
10 #include <list>
11 #include <map>
12 #include <stack>
13 #include <string>
14 #include <vector>
16 #include "base/at_exit.h"
17 #include "base/bind.h"
18 #include "base/callback_helpers.h"
19 #include "base/command_line.h"
20 #include "base/debug/trace_event.h"
21 #include "base/debug/trace_event_synthetic_delay.h"
22 #include "base/float_util.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "base/numerics/safe_math.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_split.h"
27 #include "build/build_config.h"
28 #define GLES2_GPU_SERVICE 1
29 #include "gpu/command_buffer/common/debug_marker_manager.h"
30 #include "gpu/command_buffer/common/gles2_cmd_format.h"
31 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
32 #include "gpu/command_buffer/common/id_allocator.h"
33 #include "gpu/command_buffer/common/mailbox.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
36 #include "gpu/command_buffer/service/buffer_manager.h"
37 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
38 #include "gpu/command_buffer/service/context_group.h"
39 #include "gpu/command_buffer/service/context_state.h"
40 #include "gpu/command_buffer/service/error_state.h"
41 #include "gpu/command_buffer/service/feature_info.h"
42 #include "gpu/command_buffer/service/framebuffer_manager.h"
43 #include "gpu/command_buffer/service/gl_utils.h"
44 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
45 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
46 #include "gpu/command_buffer/service/gpu_state_tracer.h"
47 #include "gpu/command_buffer/service/gpu_switches.h"
48 #include "gpu/command_buffer/service/gpu_tracer.h"
49 #include "gpu/command_buffer/service/image_manager.h"
50 #include "gpu/command_buffer/service/mailbox_manager.h"
51 #include "gpu/command_buffer/service/memory_tracking.h"
52 #include "gpu/command_buffer/service/program_manager.h"
53 #include "gpu/command_buffer/service/query_manager.h"
54 #include "gpu/command_buffer/service/renderbuffer_manager.h"
55 #include "gpu/command_buffer/service/shader_manager.h"
56 #include "gpu/command_buffer/service/shader_translator.h"
57 #include "gpu/command_buffer/service/shader_translator_cache.h"
58 #include "gpu/command_buffer/service/texture_manager.h"
59 #include "gpu/command_buffer/service/vertex_array_manager.h"
60 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
61 #include "third_party/smhasher/src/City.h"
62 #include "ui/gl/gl_fence.h"
63 #include "ui/gl/gl_image.h"
64 #include "ui/gl/gl_implementation.h"
65 #include "ui/gl/gl_surface.h"
67 #if defined(OS_MACOSX)
68 #include <IOSurface/IOSurfaceAPI.h>
69 // Note that this must be included after gl_bindings.h to avoid conflicts.
70 #include <OpenGL/CGLIOSurface.h>
71 #endif
73 #if defined(OS_WIN)
74 #include "base/win/win_util.h"
75 #endif
77 namespace gpu {
78 namespace gles2 {
80 namespace {
82 static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
83 static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
84 static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
85 static const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
87 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
88 khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
89 return static_cast<khronos_uint64_t>(
90 CityHash64(name, static_cast<size_t>(len)));
92 #endif
94 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
95 GLint rangeMax,
96 GLint precision) {
97 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
100 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
101 GLenum precision_type,
102 GLint *range, GLint *precision) {
103 switch (precision_type) {
104 case GL_LOW_INT:
105 case GL_MEDIUM_INT:
106 case GL_HIGH_INT:
107 // These values are for a 32-bit twos-complement integer format.
108 range[0] = 31;
109 range[1] = 30;
110 *precision = 0;
111 break;
112 case GL_LOW_FLOAT:
113 case GL_MEDIUM_FLOAT:
114 case GL_HIGH_FLOAT:
115 // These values are for an IEEE single-precision floating-point format.
116 range[0] = 127;
117 range[1] = 127;
118 *precision = 23;
119 break;
120 default:
121 NOTREACHED();
122 break;
125 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
126 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
127 // This function is sometimes defined even though it's really just
128 // a stub, so we need to set range and precision as if it weren't
129 // defined before calling it.
130 // On Mac OS with some GPUs, calling this generates a
131 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
132 // platforms.
133 glGetShaderPrecisionFormat(shader_type, precision_type,
134 range, precision);
136 // TODO(brianderson): Make the following official workarounds.
138 // Some drivers have bugs where they report the ranges as a negative number.
139 // Taking the absolute value here shouldn't hurt because negative numbers
140 // aren't expected anyway.
141 range[0] = abs(range[0]);
142 range[1] = abs(range[1]);
144 // If the driver reports a precision for highp float that isn't actually
145 // highp, don't pretend like it's supported because shader compilation will
146 // fail anyway.
147 if (precision_type == GL_HIGH_FLOAT &&
148 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
149 range[0] = 0;
150 range[1] = 0;
151 *precision = 0;
156 static gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
157 switch (plane_transform) {
158 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
159 return gfx::OVERLAY_TRANSFORM_NONE;
160 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
161 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
162 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
163 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
164 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
165 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
166 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
167 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
168 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
169 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
170 default:
171 return gfx::OVERLAY_TRANSFORM_INVALID;
175 } // namespace
177 class GLES2DecoderImpl;
179 // Local versions of the SET_GL_ERROR macros
180 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
181 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
182 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
183 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
184 function_name, value, label)
185 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
186 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
187 function_name, pname)
188 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
189 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
190 function_name)
191 #define LOCAL_PEEK_GL_ERROR(function_name) \
192 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
193 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
194 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
195 #define LOCAL_PERFORMANCE_WARNING(msg) \
196 PerformanceWarning(__FILE__, __LINE__, msg)
197 #define LOCAL_RENDER_WARNING(msg) \
198 RenderWarning(__FILE__, __LINE__, msg)
200 // Check that certain assumptions the code makes are true. There are places in
201 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
202 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
203 // a few others) are 32bits. If they are not 32bits the code will have to change
204 // to call those GL functions with service side memory and then copy the results
205 // to shared memory, converting the sizes.
206 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
207 GLint_not_same_size_as_uint32);
208 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
209 GLint_not_same_size_as_uint32);
210 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
211 GLfloat_not_same_size_as_float);
213 // TODO(kbr): the use of this anonymous namespace core dumps the
214 // linker on Mac OS X 10.6 when the symbol ordering file is used
215 // namespace {
217 // Returns the address of the first byte after a struct.
218 template <typename T>
219 const void* AddressAfterStruct(const T& pod) {
220 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
223 // Returns the address of the frst byte after the struct or NULL if size >
224 // immediate_data_size.
225 template <typename RETURN_TYPE, typename COMMAND_TYPE>
226 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
227 uint32 size,
228 uint32 immediate_data_size) {
229 return (size <= immediate_data_size) ?
230 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
231 NULL;
234 // Computes the data size for certain gl commands like glUniform.
235 bool ComputeDataSize(
236 GLuint count,
237 size_t size,
238 unsigned int elements_per_unit,
239 uint32* dst) {
240 uint32 value;
241 if (!SafeMultiplyUint32(count, size, &value)) {
242 return false;
244 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
245 return false;
247 *dst = value;
248 return true;
251 // A struct to hold info about each command.
252 struct CommandInfo {
253 uint8 arg_flags; // How to handle the arguments for this command
254 uint8 cmd_flags; // How to handle this command
255 uint16 arg_count; // How many arguments are expected for this command.
258 // cmds::name::cmd_flags,
259 // A table of CommandInfo for all the commands.
260 const CommandInfo g_command_info[] = {
261 #define GLES2_CMD_OP(name) { \
262 cmds::name::kArgFlags, \
263 cmds::name::cmd_flags, \
264 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */
266 GLES2_COMMAND_LIST(GLES2_CMD_OP)
268 #undef GLES2_CMD_OP
271 // Return true if a character belongs to the ASCII subset as defined in
272 // GLSL ES 1.0 spec section 3.1.
273 static bool CharacterIsValidForGLES(unsigned char c) {
274 // Printing characters are valid except " $ ` @ \ ' DEL.
275 if (c >= 32 && c <= 126 &&
276 c != '"' &&
277 c != '$' &&
278 c != '`' &&
279 c != '@' &&
280 c != '\\' &&
281 c != '\'') {
282 return true;
284 // Horizontal tab, line feed, vertical tab, form feed, carriage return
285 // are also valid.
286 if (c >= 9 && c <= 13) {
287 return true;
290 return false;
293 static bool StringIsValidForGLES(const char* str) {
294 for (; *str; ++str) {
295 if (!CharacterIsValidForGLES(*str)) {
296 return false;
299 return true;
302 // This class prevents any GL errors that occur when it is in scope from
303 // being reported to the client.
304 class ScopedGLErrorSuppressor {
305 public:
306 explicit ScopedGLErrorSuppressor(
307 const char* function_name, ErrorState* error_state);
308 ~ScopedGLErrorSuppressor();
309 private:
310 const char* function_name_;
311 ErrorState* error_state_;
312 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
315 // Temporarily changes a decoder's bound texture and restore it when this
316 // object goes out of scope. Also temporarily switches to using active texture
317 // unit zero in case the client has changed that to something invalid.
318 class ScopedTextureBinder {
319 public:
320 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
321 ~ScopedTextureBinder();
323 private:
324 ContextState* state_;
325 GLenum target_;
326 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
329 // Temporarily changes a decoder's bound render buffer and restore it when this
330 // object goes out of scope.
331 class ScopedRenderBufferBinder {
332 public:
333 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
334 ~ScopedRenderBufferBinder();
336 private:
337 ContextState* state_;
338 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
341 // Temporarily changes a decoder's bound frame buffer and restore it when this
342 // object goes out of scope.
343 class ScopedFrameBufferBinder {
344 public:
345 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
346 ~ScopedFrameBufferBinder();
348 private:
349 GLES2DecoderImpl* decoder_;
350 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
353 // Temporarily changes a decoder's bound frame buffer to a resolved version of
354 // the multisampled offscreen render buffer if that buffer is multisampled, and,
355 // if it is bound or enforce_internal_framebuffer is true. If internal is
356 // true, the resolved framebuffer is not visible to the parent.
357 class ScopedResolvedFrameBufferBinder {
358 public:
359 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
360 bool enforce_internal_framebuffer,
361 bool internal);
362 ~ScopedResolvedFrameBufferBinder();
364 private:
365 GLES2DecoderImpl* decoder_;
366 bool resolve_and_bind_;
367 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
370 class ScopedModifyPixels {
371 public:
372 explicit ScopedModifyPixels(TextureRef* ref);
373 ~ScopedModifyPixels();
375 private:
376 TextureRef* ref_;
379 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
380 if (ref_)
381 ref_->texture()->OnWillModifyPixels();
384 ScopedModifyPixels::~ScopedModifyPixels() {
385 if (ref_)
386 ref_->texture()->OnDidModifyPixels();
389 class ScopedRenderTo {
390 public:
391 explicit ScopedRenderTo(Framebuffer* framebuffer);
392 ~ScopedRenderTo();
394 private:
395 const Framebuffer* framebuffer_;
398 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
399 : framebuffer_(framebuffer) {
400 if (framebuffer)
401 framebuffer_->OnWillRenderTo();
404 ScopedRenderTo::~ScopedRenderTo() {
405 if (framebuffer_)
406 framebuffer_->OnDidRenderTo();
409 // Encapsulates an OpenGL texture.
410 class BackTexture {
411 public:
412 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
413 ~BackTexture();
415 // Create a new render texture.
416 void Create();
418 // Set the initial size and format of a render texture or resize it.
419 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
421 // Copy the contents of the currently bound frame buffer.
422 void Copy(const gfx::Size& size, GLenum format);
424 // Destroy the render texture. This must be explicitly called before
425 // destroying this object.
426 void Destroy();
428 // Invalidate the texture. This can be used when a context is lost and it is
429 // not possible to make it current in order to free the resource.
430 void Invalidate();
432 GLuint id() const {
433 return id_;
436 gfx::Size size() const {
437 return size_;
440 private:
441 MemoryTypeTracker memory_tracker_;
442 ContextState* state_;
443 size_t bytes_allocated_;
444 GLuint id_;
445 gfx::Size size_;
446 DISALLOW_COPY_AND_ASSIGN(BackTexture);
449 // Encapsulates an OpenGL render buffer of any format.
450 class BackRenderbuffer {
451 public:
452 explicit BackRenderbuffer(
453 RenderbufferManager* renderbuffer_manager,
454 MemoryTracker* memory_tracker,
455 ContextState* state);
456 ~BackRenderbuffer();
458 // Create a new render buffer.
459 void Create();
461 // Set the initial size and format of a render buffer or resize it.
462 bool AllocateStorage(const FeatureInfo* feature_info,
463 const gfx::Size& size,
464 GLenum format,
465 GLsizei samples);
467 // Destroy the render buffer. This must be explicitly called before destroying
468 // this object.
469 void Destroy();
471 // Invalidate the render buffer. This can be used when a context is lost and
472 // it is not possible to make it current in order to free the resource.
473 void Invalidate();
475 GLuint id() const {
476 return id_;
479 private:
480 RenderbufferManager* renderbuffer_manager_;
481 MemoryTypeTracker memory_tracker_;
482 ContextState* state_;
483 size_t bytes_allocated_;
484 GLuint id_;
485 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
488 // Encapsulates an OpenGL frame buffer.
489 class BackFramebuffer {
490 public:
491 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
492 ~BackFramebuffer();
494 // Create a new frame buffer.
495 void Create();
497 // Attach a color render buffer to a frame buffer.
498 void AttachRenderTexture(BackTexture* texture);
500 // Attach a render buffer to a frame buffer. Note that this unbinds any
501 // currently bound frame buffer.
502 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
504 // Destroy the frame buffer. This must be explicitly called before destroying
505 // this object.
506 void Destroy();
508 // Invalidate the frame buffer. This can be used when a context is lost and it
509 // is not possible to make it current in order to free the resource.
510 void Invalidate();
512 // See glCheckFramebufferStatusEXT.
513 GLenum CheckStatus();
515 GLuint id() const {
516 return id_;
519 private:
520 GLES2DecoderImpl* decoder_;
521 GLuint id_;
522 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
525 struct FenceCallback {
526 explicit FenceCallback()
527 : fence(gfx::GLFence::Create()) {
528 DCHECK(fence);
530 std::vector<base::Closure> callbacks;
531 scoped_ptr<gfx::GLFence> fence;
534 class AsyncUploadTokenCompletionObserver
535 : public AsyncPixelTransferCompletionObserver {
536 public:
537 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
538 : async_upload_token_(async_upload_token) {
541 virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE {
542 DCHECK(mem_params.buffer());
543 void* data = mem_params.GetDataAddress();
544 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
545 sync->SetAsyncUploadToken(async_upload_token_);
548 private:
549 virtual ~AsyncUploadTokenCompletionObserver() {
552 uint32 async_upload_token_;
554 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
557 // } // anonymous namespace.
559 // static
560 const unsigned int GLES2Decoder::kDefaultStencilMask =
561 static_cast<unsigned int>(-1);
563 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
564 uint32* service_texture_id) {
565 return false;
568 GLES2Decoder::GLES2Decoder()
569 : initialized_(false),
570 debug_(false),
571 log_commands_(false) {
574 GLES2Decoder::~GLES2Decoder() {
577 void GLES2Decoder::BeginDecoding() {}
579 void GLES2Decoder::EndDecoding() {}
581 // This class implements GLES2Decoder so we don't have to expose all the GLES2
582 // cmd stuff to outside this class.
583 class GLES2DecoderImpl : public GLES2Decoder,
584 public FramebufferManager::TextureDetachObserver,
585 public ErrorStateClient {
586 public:
587 explicit GLES2DecoderImpl(ContextGroup* group);
588 virtual ~GLES2DecoderImpl();
590 // Overridden from AsyncAPIInterface.
591 virtual Error DoCommand(unsigned int command,
592 unsigned int arg_count,
593 const void* args) OVERRIDE;
595 // Overridden from AsyncAPIInterface.
596 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
598 // Overridden from GLES2Decoder.
599 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
600 const scoped_refptr<gfx::GLContext>& context,
601 bool offscreen,
602 const gfx::Size& size,
603 const DisallowedFeatures& disallowed_features,
604 const std::vector<int32>& attribs) OVERRIDE;
605 virtual void Destroy(bool have_context) OVERRIDE;
606 virtual void SetSurface(
607 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
608 virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
609 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
610 void UpdateParentTextureInfo();
611 virtual bool MakeCurrent() OVERRIDE;
612 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
613 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
614 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
615 virtual Capabilities GetCapabilities() OVERRIDE;
616 virtual void RestoreState(const ContextState* prev_state) OVERRIDE;
618 virtual void RestoreActiveTexture() const OVERRIDE {
619 state_.RestoreActiveTexture();
621 virtual void RestoreAllTextureUnitBindings(
622 const ContextState* prev_state) const OVERRIDE {
623 state_.RestoreAllTextureUnitBindings(prev_state);
625 virtual void RestoreActiveTextureUnitBinding(
626 unsigned int target) const OVERRIDE {
627 state_.RestoreActiveTextureUnitBinding(target);
629 virtual void RestoreBufferBindings() const OVERRIDE {
630 state_.RestoreBufferBindings();
632 virtual void RestoreGlobalState() const OVERRIDE {
633 state_.RestoreGlobalState(NULL);
635 virtual void RestoreProgramBindings() const OVERRIDE {
636 state_.RestoreProgramBindings();
638 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
639 state_.RestoreTextureUnitBindings(unit, NULL);
641 virtual void RestoreFramebufferBindings() const OVERRIDE;
642 virtual void RestoreRenderbufferBindings() OVERRIDE;
643 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
645 virtual void ClearAllAttributes() const OVERRIDE;
646 virtual void RestoreAllAttributes() const OVERRIDE;
648 virtual QueryManager* GetQueryManager() OVERRIDE {
649 return query_manager_.get();
651 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
652 return vertex_array_manager_.get();
654 virtual ImageManager* GetImageManager() OVERRIDE {
655 return image_manager_.get();
657 virtual bool ProcessPendingQueries() OVERRIDE;
658 virtual bool HasMoreIdleWork() OVERRIDE;
659 virtual void PerformIdleWork() OVERRIDE;
661 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
663 virtual void SetResizeCallback(
664 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
666 virtual Logger* GetLogger() OVERRIDE;
668 virtual void BeginDecoding() OVERRIDE;
669 virtual void EndDecoding() OVERRIDE;
671 virtual ErrorState* GetErrorState() OVERRIDE;
672 virtual const ContextState* GetContextState() OVERRIDE { return &state_; }
674 virtual void SetShaderCacheCallback(
675 const ShaderCacheCallback& callback) OVERRIDE;
676 virtual void SetWaitSyncPointCallback(
677 const WaitSyncPointCallback& callback) OVERRIDE;
679 virtual AsyncPixelTransferManager*
680 GetAsyncPixelTransferManager() OVERRIDE;
681 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
682 virtual void SetAsyncPixelTransferManagerForTest(
683 AsyncPixelTransferManager* manager) OVERRIDE;
684 virtual void SetIgnoreCachedStateForTest(bool ignore) OVERRIDE;
685 void ProcessFinishedAsyncTransfers();
687 virtual bool GetServiceTextureId(uint32 client_texture_id,
688 uint32* service_texture_id) OVERRIDE;
690 virtual uint32 GetTextureUploadCount() OVERRIDE;
691 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
692 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
693 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
695 // Restores the current state to the user's settings.
696 void RestoreCurrentFramebufferBindings();
698 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
699 void ApplyDirtyState();
701 // These check the state of the currently bound framebuffer or the
702 // backbuffer if no framebuffer is bound.
703 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
704 // check with all attached and enabled color attachments.
705 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
706 bool BoundFramebufferHasDepthAttachment();
707 bool BoundFramebufferHasStencilAttachment();
709 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
711 // Overridden from FramebufferManager::TextureDetachObserver:
712 virtual void OnTextureRefDetachedFromFramebuffer(
713 TextureRef* texture) OVERRIDE;
715 // Overriden from ErrorStateClient.
716 virtual void OnOutOfMemoryError() OVERRIDE;
718 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
719 void EnsureRenderbufferBound();
721 // Helpers to facilitate calling into compatible extensions.
722 static void RenderbufferStorageMultisampleHelper(
723 const FeatureInfo* feature_info,
724 GLenum target,
725 GLsizei samples,
726 GLenum internal_format,
727 GLsizei width,
728 GLsizei height);
730 void BlitFramebufferHelper(GLint srcX0,
731 GLint srcY0,
732 GLint srcX1,
733 GLint srcY1,
734 GLint dstX0,
735 GLint dstY0,
736 GLint dstX1,
737 GLint dstY1,
738 GLbitfield mask,
739 GLenum filter);
741 private:
742 friend class ScopedFrameBufferBinder;
743 friend class ScopedResolvedFrameBufferBinder;
744 friend class BackFramebuffer;
746 // Initialize or re-initialize the shader translator.
747 bool InitializeShaderTranslator();
749 void UpdateCapabilities();
751 // Helpers for the glGen and glDelete functions.
752 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
753 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
754 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
755 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
756 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
757 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
758 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
759 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
760 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
761 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
762 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
763 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
765 // Helper for async upload token completion notification callback.
766 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
767 uint32 sync_data_shm_id,
768 uint32 sync_data_shm_offset);
772 // Workarounds
773 void OnFboChanged() const;
774 void OnUseFramebuffer() const;
776 // TODO(gman): Cache these pointers?
777 BufferManager* buffer_manager() {
778 return group_->buffer_manager();
781 RenderbufferManager* renderbuffer_manager() {
782 return group_->renderbuffer_manager();
785 FramebufferManager* framebuffer_manager() {
786 return group_->framebuffer_manager();
789 ProgramManager* program_manager() {
790 return group_->program_manager();
793 ShaderManager* shader_manager() {
794 return group_->shader_manager();
797 ShaderTranslatorCache* shader_translator_cache() {
798 return group_->shader_translator_cache();
801 const TextureManager* texture_manager() const {
802 return group_->texture_manager();
805 TextureManager* texture_manager() {
806 return group_->texture_manager();
809 MailboxManager* mailbox_manager() {
810 return group_->mailbox_manager();
813 ImageManager* image_manager() { return image_manager_.get(); }
815 VertexArrayManager* vertex_array_manager() {
816 return vertex_array_manager_.get();
819 MemoryTracker* memory_tracker() {
820 return group_->memory_tracker();
823 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
824 MemoryTracker* tracker = memory_tracker();
825 if (tracker) {
826 return tracker->EnsureGPUMemoryAvailable(estimated_size);
828 return true;
831 bool IsOffscreenBufferMultisampled() const {
832 return offscreen_target_samples_ > 1;
835 // Creates a Texture for the given texture.
836 TextureRef* CreateTexture(
837 GLuint client_id, GLuint service_id) {
838 return texture_manager()->CreateTexture(client_id, service_id);
841 // Gets the texture info for the given texture. Returns NULL if none exists.
842 TextureRef* GetTexture(GLuint client_id) const {
843 return texture_manager()->GetTexture(client_id);
846 // Deletes the texture info for the given texture.
847 void RemoveTexture(GLuint client_id) {
848 texture_manager()->RemoveTexture(client_id);
851 // Get the size (in pixels) of the currently bound frame buffer (either FBO
852 // or regular back buffer).
853 gfx::Size GetBoundReadFrameBufferSize();
855 // Get the format of the currently bound frame buffer (either FBO or regular
856 // back buffer)
857 GLenum GetBoundReadFrameBufferTextureType();
858 GLenum GetBoundReadFrameBufferInternalFormat();
859 GLenum GetBoundDrawFrameBufferInternalFormat();
861 // Wrapper for CompressedTexImage2D commands.
862 error::Error DoCompressedTexImage2D(
863 GLenum target,
864 GLint level,
865 GLenum internal_format,
866 GLsizei width,
867 GLsizei height,
868 GLint border,
869 GLsizei image_size,
870 const void* data);
872 // Wrapper for CompressedTexSubImage2D.
873 void DoCompressedTexSubImage2D(
874 GLenum target,
875 GLint level,
876 GLint xoffset,
877 GLint yoffset,
878 GLsizei width,
879 GLsizei height,
880 GLenum format,
881 GLsizei imageSize,
882 const void * data);
884 // Wrapper for CopyTexImage2D.
885 void DoCopyTexImage2D(
886 GLenum target,
887 GLint level,
888 GLenum internal_format,
889 GLint x,
890 GLint y,
891 GLsizei width,
892 GLsizei height,
893 GLint border);
895 // Wrapper for SwapBuffers.
896 void DoSwapBuffers();
898 // Wrapper for CopyTexSubImage2D.
899 void DoCopyTexSubImage2D(
900 GLenum target,
901 GLint level,
902 GLint xoffset,
903 GLint yoffset,
904 GLint x,
905 GLint y,
906 GLsizei width,
907 GLsizei height);
909 // Validation for TexSubImage2D.
910 bool ValidateTexSubImage2D(
911 error::Error* error,
912 const char* function_name,
913 GLenum target,
914 GLint level,
915 GLint xoffset,
916 GLint yoffset,
917 GLsizei width,
918 GLsizei height,
919 GLenum format,
920 GLenum type,
921 const void * data);
923 // Wrapper for TexSubImage2D.
924 error::Error DoTexSubImage2D(
925 GLenum target,
926 GLint level,
927 GLint xoffset,
928 GLint yoffset,
929 GLsizei width,
930 GLsizei height,
931 GLenum format,
932 GLenum type,
933 const void * data);
935 // Extra validation for async tex(Sub)Image2D.
936 bool ValidateAsyncTransfer(
937 const char* function_name,
938 TextureRef* texture_ref,
939 GLenum target,
940 GLint level,
941 const void * data);
943 // Wrapper for TexImageIOSurface2DCHROMIUM.
944 void DoTexImageIOSurface2DCHROMIUM(
945 GLenum target,
946 GLsizei width,
947 GLsizei height,
948 GLuint io_surface_id,
949 GLuint plane);
951 void DoCopyTextureCHROMIUM(
952 GLenum target,
953 GLuint source_id,
954 GLuint target_id,
955 GLint level,
956 GLenum internal_format,
957 GLenum dest_type);
959 // Wrapper for TexStorage2DEXT.
960 void DoTexStorage2DEXT(
961 GLenum target,
962 GLint levels,
963 GLenum internal_format,
964 GLsizei width,
965 GLsizei height);
967 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
968 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
969 const GLbyte* key);
970 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
971 GLenum target, const GLbyte* data);
973 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
974 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
975 GLuint client_id);
977 void DoBindTexImage2DCHROMIUM(
978 GLenum target,
979 GLint image_id);
980 void DoReleaseTexImage2DCHROMIUM(
981 GLenum target,
982 GLint image_id);
984 void DoTraceEndCHROMIUM(void);
986 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
988 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
990 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
991 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
993 // Creates a Program for the given program.
994 Program* CreateProgram(
995 GLuint client_id, GLuint service_id) {
996 return program_manager()->CreateProgram(client_id, service_id);
999 // Gets the program info for the given program. Returns NULL if none exists.
1000 Program* GetProgram(GLuint client_id) {
1001 return program_manager()->GetProgram(client_id);
1004 #if defined(NDEBUG)
1005 void LogClientServiceMapping(
1006 const char* /* function_name */,
1007 GLuint /* client_id */,
1008 GLuint /* service_id */) {
1010 template<typename T>
1011 void LogClientServiceForInfo(
1012 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1014 #else
1015 void LogClientServiceMapping(
1016 const char* function_name, GLuint client_id, GLuint service_id) {
1017 if (service_logging_) {
1018 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1019 << ": client_id = " << client_id
1020 << ", service_id = " << service_id;
1023 template<typename T>
1024 void LogClientServiceForInfo(
1025 T* info, GLuint client_id, const char* function_name) {
1026 if (info) {
1027 LogClientServiceMapping(function_name, client_id, info->service_id());
1030 #endif
1032 // Gets the program info for the given program. If it's not a program
1033 // generates a GL error. Returns NULL if not program.
1034 Program* GetProgramInfoNotShader(
1035 GLuint client_id, const char* function_name) {
1036 Program* program = GetProgram(client_id);
1037 if (!program) {
1038 if (GetShader(client_id)) {
1039 LOCAL_SET_GL_ERROR(
1040 GL_INVALID_OPERATION, function_name, "shader passed for program");
1041 } else {
1042 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1045 LogClientServiceForInfo(program, client_id, function_name);
1046 return program;
1050 // Creates a Shader for the given shader.
1051 Shader* CreateShader(
1052 GLuint client_id,
1053 GLuint service_id,
1054 GLenum shader_type) {
1055 return shader_manager()->CreateShader(
1056 client_id, service_id, shader_type);
1059 // Gets the shader info for the given shader. Returns NULL if none exists.
1060 Shader* GetShader(GLuint client_id) {
1061 return shader_manager()->GetShader(client_id);
1064 // Gets the shader info for the given shader. If it's not a shader generates a
1065 // GL error. Returns NULL if not shader.
1066 Shader* GetShaderInfoNotProgram(
1067 GLuint client_id, const char* function_name) {
1068 Shader* shader = GetShader(client_id);
1069 if (!shader) {
1070 if (GetProgram(client_id)) {
1071 LOCAL_SET_GL_ERROR(
1072 GL_INVALID_OPERATION, function_name, "program passed for shader");
1073 } else {
1074 LOCAL_SET_GL_ERROR(
1075 GL_INVALID_VALUE, function_name, "unknown shader");
1078 LogClientServiceForInfo(shader, client_id, function_name);
1079 return shader;
1082 // Creates a buffer info for the given buffer.
1083 void CreateBuffer(GLuint client_id, GLuint service_id) {
1084 return buffer_manager()->CreateBuffer(client_id, service_id);
1087 // Gets the buffer info for the given buffer.
1088 Buffer* GetBuffer(GLuint client_id) {
1089 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1090 return buffer;
1093 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1094 // on glDeleteBuffers so we can make sure the user does not try to render
1095 // with deleted buffers.
1096 void RemoveBuffer(GLuint client_id);
1098 // Creates a framebuffer info for the given framebuffer.
1099 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1100 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1103 // Gets the framebuffer info for the given framebuffer.
1104 Framebuffer* GetFramebuffer(GLuint client_id) {
1105 return framebuffer_manager()->GetFramebuffer(client_id);
1108 // Removes the framebuffer info for the given framebuffer.
1109 void RemoveFramebuffer(GLuint client_id) {
1110 framebuffer_manager()->RemoveFramebuffer(client_id);
1113 // Creates a renderbuffer info for the given renderbuffer.
1114 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1115 return renderbuffer_manager()->CreateRenderbuffer(
1116 client_id, service_id);
1119 // Gets the renderbuffer info for the given renderbuffer.
1120 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1121 return renderbuffer_manager()->GetRenderbuffer(client_id);
1124 // Removes the renderbuffer info for the given renderbuffer.
1125 void RemoveRenderbuffer(GLuint client_id) {
1126 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1129 // Gets the vertex attrib manager for the given vertex array.
1130 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1131 VertexAttribManager* info =
1132 vertex_array_manager()->GetVertexAttribManager(client_id);
1133 return info;
1136 // Removes the vertex attrib manager for the given vertex array.
1137 void RemoveVertexAttribManager(GLuint client_id) {
1138 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1141 // Creates a vertex attrib manager for the given vertex array.
1142 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1143 GLuint client_id,
1144 GLuint service_id,
1145 bool client_visible) {
1146 return vertex_array_manager()->CreateVertexAttribManager(
1147 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1150 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1151 void DoBindUniformLocationCHROMIUM(
1152 GLuint client_id, GLint location, const char* name);
1154 error::Error GetAttribLocationHelper(
1155 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1156 const std::string& name_str);
1158 error::Error GetUniformLocationHelper(
1159 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1160 const std::string& name_str);
1162 // Helper for glShaderSource.
1163 error::Error ShaderSourceHelper(
1164 GLuint client_id, const char* data, uint32 data_size);
1166 // Clear any textures used by the current program.
1167 bool ClearUnclearedTextures();
1169 // Clears any uncleared attachments attached to the given frame buffer.
1170 // Returns false if there was a generated GL error.
1171 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1173 // overridden from GLES2Decoder
1174 virtual bool ClearLevel(unsigned service_id,
1175 unsigned bind_target,
1176 unsigned target,
1177 int level,
1178 unsigned internal_format,
1179 unsigned format,
1180 unsigned type,
1181 int width,
1182 int height,
1183 bool is_texture_immutable) OVERRIDE;
1185 // Restore all GL state that affects clearing.
1186 void RestoreClearState();
1188 // Remembers the state of some capabilities.
1189 // Returns: true if glEnable/glDisable should actually be called.
1190 bool SetCapabilityState(GLenum cap, bool enabled);
1192 // Check that the currently bound framebuffers are valid.
1193 // Generates GL error if not.
1194 bool CheckBoundFramebuffersValid(const char* func_name);
1196 // Check that the currently bound read framebuffer has a color image
1197 // attached. Generates GL error if not.
1198 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1200 // Check if a framebuffer meets our requirements.
1201 bool CheckFramebufferValid(
1202 Framebuffer* framebuffer,
1203 GLenum target,
1204 const char* func_name);
1206 // Checks if the current program exists and is valid. If not generates the
1207 // appropriate GL error. Returns true if the current program is in a usable
1208 // state.
1209 bool CheckCurrentProgram(const char* function_name);
1211 // Checks if the current program exists and is valid and that location is not
1212 // -1. If the current program is not valid generates the appropriate GL
1213 // error. Returns true if the current program is in a usable state and
1214 // location is not -1.
1215 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1217 // Gets the type of a uniform for a location in the current program. Sets GL
1218 // errors if the current program is not valid. Returns true if the current
1219 // program is valid and the location exists. Adjusts count so it
1220 // does not overflow the uniform.
1221 bool PrepForSetUniformByLocation(GLint fake_location,
1222 const char* function_name,
1223 Program::UniformApiType api_type,
1224 GLint* real_location,
1225 GLenum* type,
1226 GLsizei* count);
1228 // Gets the service id for any simulated backbuffer fbo.
1229 GLuint GetBackbufferServiceId() const;
1231 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1232 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1234 // Helper for glGetVertexAttrib
1235 void GetVertexAttribHelper(
1236 const VertexAttrib* attrib, GLenum pname, GLint* param);
1238 // Wrapper for glCreateProgram
1239 bool CreateProgramHelper(GLuint client_id);
1241 // Wrapper for glCreateShader
1242 bool CreateShaderHelper(GLenum type, GLuint client_id);
1244 // Wrapper for glActiveTexture
1245 void DoActiveTexture(GLenum texture_unit);
1247 // Wrapper for glAttachShader
1248 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1250 // Wrapper for glBindBuffer since we need to track the current targets.
1251 void DoBindBuffer(GLenum target, GLuint buffer);
1253 // Wrapper for glBindFramebuffer since we need to track the current targets.
1254 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1256 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1257 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1259 // Wrapper for glBindTexture since we need to track the current targets.
1260 void DoBindTexture(GLenum target, GLuint texture);
1262 // Wrapper for glBindVertexArrayOES
1263 void DoBindVertexArrayOES(GLuint array);
1264 void EmulateVertexArrayState();
1266 // Wrapper for glBlitFramebufferCHROMIUM.
1267 void DoBlitFramebufferCHROMIUM(
1268 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1269 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1270 GLbitfield mask, GLenum filter);
1272 // Wrapper for glBufferSubData.
1273 void DoBufferSubData(
1274 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1276 // Wrapper for glCheckFramebufferStatus
1277 GLenum DoCheckFramebufferStatus(GLenum target);
1279 // Wrapper for glClear
1280 error::Error DoClear(GLbitfield mask);
1282 // Wrappers for various state.
1283 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1284 void DoSampleCoverage(GLclampf value, GLboolean invert);
1286 // Wrapper for glCompileShader.
1287 void DoCompileShader(GLuint shader);
1289 // Helper for DeleteSharedIdsCHROMIUM commands.
1290 void DoDeleteSharedIdsCHROMIUM(
1291 GLuint namespace_id, GLsizei n, const GLuint* ids);
1293 // Wrapper for glDetachShader
1294 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1296 // Wrapper for glDisable
1297 void DoDisable(GLenum cap);
1299 // Wrapper for glDisableVertexAttribArray.
1300 void DoDisableVertexAttribArray(GLuint index);
1302 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1303 // attachments.
1304 void DoDiscardFramebufferEXT(GLenum target,
1305 GLsizei numAttachments,
1306 const GLenum* attachments);
1308 // Wrapper for glEnable
1309 void DoEnable(GLenum cap);
1311 // Wrapper for glEnableVertexAttribArray.
1312 void DoEnableVertexAttribArray(GLuint index);
1314 // Wrapper for glFinish.
1315 void DoFinish();
1317 // Wrapper for glFlush.
1318 void DoFlush();
1320 // Wrapper for glFramebufferRenderbufffer.
1321 void DoFramebufferRenderbuffer(
1322 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1323 GLuint renderbuffer);
1325 // Wrapper for glFramebufferTexture2D.
1326 void DoFramebufferTexture2D(
1327 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1328 GLint level);
1330 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1331 void DoFramebufferTexture2DMultisample(
1332 GLenum target, GLenum attachment, GLenum textarget,
1333 GLuint texture, GLint level, GLsizei samples);
1335 // Common implementation for both DoFramebufferTexture2D wrappers.
1336 void DoFramebufferTexture2DCommon(const char* name,
1337 GLenum target, GLenum attachment, GLenum textarget,
1338 GLuint texture, GLint level, GLsizei samples);
1340 // Wrapper for glGenerateMipmap
1341 void DoGenerateMipmap(GLenum target);
1343 // Helper for GenSharedIdsCHROMIUM commands.
1344 void DoGenSharedIdsCHROMIUM(
1345 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1347 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1348 // to account for different pname values defined in different extension
1349 // variants.
1350 GLenum AdjustGetPname(GLenum pname);
1352 // Wrapper for DoGetBooleanv.
1353 void DoGetBooleanv(GLenum pname, GLboolean* params);
1355 // Wrapper for DoGetFloatv.
1356 void DoGetFloatv(GLenum pname, GLfloat* params);
1358 // Wrapper for glGetFramebufferAttachmentParameteriv.
1359 void DoGetFramebufferAttachmentParameteriv(
1360 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1362 // Wrapper for glGetIntegerv.
1363 void DoGetIntegerv(GLenum pname, GLint* params);
1365 // Gets the max value in a range in a buffer.
1366 GLuint DoGetMaxValueInBufferCHROMIUM(
1367 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1369 // Wrapper for glGetBufferParameteriv.
1370 void DoGetBufferParameteriv(
1371 GLenum target, GLenum pname, GLint* params);
1373 // Wrapper for glGetProgramiv.
1374 void DoGetProgramiv(
1375 GLuint program_id, GLenum pname, GLint* params);
1377 // Wrapper for glRenderbufferParameteriv.
1378 void DoGetRenderbufferParameteriv(
1379 GLenum target, GLenum pname, GLint* params);
1381 // Wrapper for glGetShaderiv
1382 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1384 // Wrappers for glGetTexParameter.
1385 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1386 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1387 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1389 // Wrappers for glGetVertexAttrib.
1390 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1391 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1393 // Wrappers for glIsXXX functions.
1394 bool DoIsEnabled(GLenum cap);
1395 bool DoIsBuffer(GLuint client_id);
1396 bool DoIsFramebuffer(GLuint client_id);
1397 bool DoIsProgram(GLuint client_id);
1398 bool DoIsRenderbuffer(GLuint client_id);
1399 bool DoIsShader(GLuint client_id);
1400 bool DoIsTexture(GLuint client_id);
1401 bool DoIsVertexArrayOES(GLuint client_id);
1403 // Wrapper for glLinkProgram
1404 void DoLinkProgram(GLuint program);
1406 // Helper for RegisterSharedIdsCHROMIUM.
1407 void DoRegisterSharedIdsCHROMIUM(
1408 GLuint namespace_id, GLsizei n, const GLuint* ids);
1410 // Wrapper for glRenderbufferStorage.
1411 void DoRenderbufferStorage(
1412 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1414 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1415 void DoRenderbufferStorageMultisampleCHROMIUM(
1416 GLenum target, GLsizei samples, GLenum internalformat,
1417 GLsizei width, GLsizei height);
1419 // Handler for glRenderbufferStorageMultisampleEXT
1420 // (multisampled_render_to_texture).
1421 void DoRenderbufferStorageMultisampleEXT(
1422 GLenum target, GLsizei samples, GLenum internalformat,
1423 GLsizei width, GLsizei height);
1425 // Common validation for multisample extensions.
1426 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1427 GLenum internalformat,
1428 GLsizei width,
1429 GLsizei height);
1431 // Verifies that the currently bound multisample renderbuffer is valid
1432 // Very slow! Only done on platforms with driver bugs that return invalid
1433 // buffers under memory pressure
1434 bool VerifyMultisampleRenderbufferIntegrity(
1435 GLuint renderbuffer, GLenum format);
1437 // Wrapper for glReleaseShaderCompiler.
1438 void DoReleaseShaderCompiler() { }
1440 // Wrappers for glTexParameter functions.
1441 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1442 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1443 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1444 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1446 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1447 // spec only these 2 functions can be used to set sampler uniforms.
1448 void DoUniform1i(GLint fake_location, GLint v0);
1449 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1450 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1451 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1452 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1454 // Wrappers for glUniformfv because some drivers don't correctly accept
1455 // bool uniforms.
1456 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1457 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1458 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1459 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1461 void DoUniformMatrix2fv(
1462 GLint fake_location, GLsizei count, GLboolean transpose,
1463 const GLfloat* value);
1464 void DoUniformMatrix3fv(
1465 GLint fake_location, GLsizei count, GLboolean transpose,
1466 const GLfloat* value);
1467 void DoUniformMatrix4fv(
1468 GLint fake_location, GLsizei count, GLboolean transpose,
1469 const GLfloat* value);
1471 bool SetVertexAttribValue(
1472 const char* function_name, GLuint index, const GLfloat* value);
1474 // Wrappers for glVertexAttrib??
1475 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1476 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1477 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1478 void DoVertexAttrib4f(
1479 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1480 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1481 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1482 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1483 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1485 // Wrapper for glViewport
1486 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1488 // Wrapper for glUseProgram
1489 void DoUseProgram(GLuint program);
1491 // Wrapper for glValidateProgram.
1492 void DoValidateProgram(GLuint program_client_id);
1494 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1495 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1496 void DoPopGroupMarkerEXT(void);
1498 // Gets the number of values that will be returned by glGetXXX. Returns
1499 // false if pname is unknown.
1500 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1502 // Checks if the current program and vertex attributes are valid for drawing.
1503 bool IsDrawValid(
1504 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1505 GLsizei primcount);
1507 // Returns true if successful, simulated will be true if attrib0 was
1508 // simulated.
1509 bool SimulateAttrib0(
1510 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1511 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1513 // If an image is bound to texture, this will call Will/DidUseTexImage
1514 // if needed.
1515 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1516 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1518 // Returns false if textures were replaced.
1519 bool PrepareTexturesForRender();
1520 void RestoreStateForTextures();
1522 // Returns true if GL_FIXED attribs were simulated.
1523 bool SimulateFixedAttribs(
1524 const char* function_name,
1525 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1526 void RestoreStateForSimulatedFixedAttribs();
1528 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1529 // cases (primcount is always 1 for non-instanced).
1530 error::Error DoDrawArrays(
1531 const char* function_name,
1532 bool instanced, GLenum mode, GLint first, GLsizei count,
1533 GLsizei primcount);
1534 error::Error DoDrawElements(
1535 const char* function_name,
1536 bool instanced, GLenum mode, GLsizei count, GLenum type,
1537 int32 offset, GLsizei primcount);
1539 GLenum GetBindTargetForSamplerType(GLenum type) {
1540 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1541 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1542 switch (type) {
1543 case GL_SAMPLER_2D:
1544 return GL_TEXTURE_2D;
1545 case GL_SAMPLER_CUBE:
1546 return GL_TEXTURE_CUBE_MAP;
1547 case GL_SAMPLER_EXTERNAL_OES:
1548 return GL_TEXTURE_EXTERNAL_OES;
1549 case GL_SAMPLER_2D_RECT_ARB:
1550 return GL_TEXTURE_RECTANGLE_ARB;
1553 NOTREACHED();
1554 return 0;
1557 // Gets the framebuffer info for a particular target.
1558 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1559 Framebuffer* framebuffer = NULL;
1560 switch (target) {
1561 case GL_FRAMEBUFFER:
1562 case GL_DRAW_FRAMEBUFFER_EXT:
1563 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1564 break;
1565 case GL_READ_FRAMEBUFFER_EXT:
1566 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1567 break;
1568 default:
1569 NOTREACHED();
1570 break;
1572 return framebuffer;
1575 Renderbuffer* GetRenderbufferInfoForTarget(
1576 GLenum target) {
1577 Renderbuffer* renderbuffer = NULL;
1578 switch (target) {
1579 case GL_RENDERBUFFER:
1580 renderbuffer = state_.bound_renderbuffer.get();
1581 break;
1582 default:
1583 NOTREACHED();
1584 break;
1586 return renderbuffer;
1589 // Validates the program and location for a glGetUniform call and returns
1590 // a SizeResult setup to receive the result. Returns true if glGetUniform
1591 // should be called.
1592 bool GetUniformSetup(
1593 GLuint program, GLint fake_location,
1594 uint32 shm_id, uint32 shm_offset,
1595 error::Error* error, GLint* real_location, GLuint* service_id,
1596 void** result, GLenum* result_type);
1598 virtual bool WasContextLost() OVERRIDE;
1599 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1600 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1602 #if defined(OS_MACOSX)
1603 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1604 #endif
1606 bool ValidateCompressedTexDimensions(
1607 const char* function_name,
1608 GLint level, GLsizei width, GLsizei height, GLenum format);
1609 bool ValidateCompressedTexFuncData(
1610 const char* function_name,
1611 GLsizei width, GLsizei height, GLenum format, size_t size);
1612 bool ValidateCompressedTexSubDimensions(
1613 const char* function_name,
1614 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1615 GLsizei width, GLsizei height, GLenum format,
1616 Texture* texture);
1618 void RenderWarning(const char* filename, int line, const std::string& msg);
1619 void PerformanceWarning(
1620 const char* filename, int line, const std::string& msg);
1622 const FeatureInfo::FeatureFlags& features() const {
1623 return feature_info_->feature_flags();
1626 const FeatureInfo::Workarounds& workarounds() const {
1627 return feature_info_->workarounds();
1630 bool ShouldDeferDraws() {
1631 return !offscreen_target_frame_buffer_.get() &&
1632 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1633 surface_->DeferDraws();
1636 bool ShouldDeferReads() {
1637 return !offscreen_target_frame_buffer_.get() &&
1638 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1639 surface_->DeferDraws();
1642 error::Error WillAccessBoundFramebufferForDraw() {
1643 if (ShouldDeferDraws())
1644 return error::kDeferCommandUntilLater;
1645 if (!offscreen_target_frame_buffer_.get() &&
1646 !framebuffer_state_.bound_draw_framebuffer.get() &&
1647 !surface_->SetBackbufferAllocation(true))
1648 return error::kLostContext;
1649 return error::kNoError;
1652 error::Error WillAccessBoundFramebufferForRead() {
1653 if (ShouldDeferReads())
1654 return error::kDeferCommandUntilLater;
1655 if (!offscreen_target_frame_buffer_.get() &&
1656 !framebuffer_state_.bound_read_framebuffer.get() &&
1657 !surface_->SetBackbufferAllocation(true))
1658 return error::kLostContext;
1659 return error::kNoError;
1662 void ProcessPendingReadPixels();
1663 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1665 // Generate a member function prototype for each command in an automated and
1666 // typesafe way.
1667 #define GLES2_CMD_OP(name) \
1668 Error Handle ## name( \
1669 uint32 immediate_data_size, \
1670 const cmds::name& args); \
1672 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1674 #undef GLES2_CMD_OP
1676 // The GL context this decoder renders to on behalf of the client.
1677 scoped_refptr<gfx::GLSurface> surface_;
1678 scoped_refptr<gfx::GLContext> context_;
1680 // The ContextGroup for this decoder uses to track resources.
1681 scoped_refptr<ContextGroup> group_;
1683 DebugMarkerManager debug_marker_manager_;
1684 Logger logger_;
1686 // All the state for this context.
1687 ContextState state_;
1689 // Current width and height of the offscreen frame buffer.
1690 gfx::Size offscreen_size_;
1692 // Util to help with GL.
1693 GLES2Util util_;
1695 // unpack flip y as last set by glPixelStorei
1696 bool unpack_flip_y_;
1698 // unpack (un)premultiply alpha as last set by glPixelStorei
1699 bool unpack_premultiply_alpha_;
1700 bool unpack_unpremultiply_alpha_;
1702 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1703 GLuint attrib_0_buffer_id_;
1705 // The value currently in attrib_0.
1706 Vec4 attrib_0_value_;
1708 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1709 bool attrib_0_buffer_matches_value_;
1711 // The size of attrib 0.
1712 GLsizei attrib_0_size_;
1714 // The buffer used to simulate GL_FIXED attribs.
1715 GLuint fixed_attrib_buffer_id_;
1717 // The size of fiixed attrib buffer.
1718 GLsizei fixed_attrib_buffer_size_;
1720 // The offscreen frame buffer that the client renders to. With EGL, the
1721 // depth and stencil buffers are separate. With regular GL there is a single
1722 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1723 // offscreen_target_stencil_render_buffer_ is unused.
1724 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1725 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1726 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1727 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1728 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1729 GLenum offscreen_target_color_format_;
1730 GLenum offscreen_target_depth_format_;
1731 GLenum offscreen_target_stencil_format_;
1732 GLsizei offscreen_target_samples_;
1733 GLboolean offscreen_target_buffer_preserved_;
1735 // The copy that is saved when SwapBuffers is called.
1736 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1737 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1738 scoped_refptr<TextureRef>
1739 offscreen_saved_color_texture_info_;
1741 // The copy that is used as the destination for multi-sample resolves.
1742 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1743 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1744 GLenum offscreen_saved_color_format_;
1746 scoped_ptr<QueryManager> query_manager_;
1748 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1750 scoped_ptr<ImageManager> image_manager_;
1752 base::Callback<void(gfx::Size, float)> resize_callback_;
1754 WaitSyncPointCallback wait_sync_point_callback_;
1756 ShaderCacheCallback shader_cache_callback_;
1758 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1760 // The format of the back buffer_
1761 GLenum back_buffer_color_format_;
1762 bool back_buffer_has_depth_;
1763 bool back_buffer_has_stencil_;
1765 // Backbuffer attachments that are currently undefined.
1766 uint32 backbuffer_needs_clear_bits_;
1768 // The current decoder error communicates the decoder error through command
1769 // processing functions that do not return the error value. Should be set only
1770 // if not returning an error.
1771 error::Error current_decoder_error_;
1773 bool use_shader_translator_;
1774 scoped_refptr<ShaderTranslator> vertex_translator_;
1775 scoped_refptr<ShaderTranslator> fragment_translator_;
1777 DisallowedFeatures disallowed_features_;
1779 // Cached from ContextGroup
1780 const Validators* validators_;
1781 scoped_refptr<FeatureInfo> feature_info_;
1783 int frame_number_;
1785 bool has_robustness_extension_;
1786 GLenum reset_status_;
1787 bool reset_by_robustness_extension_;
1788 bool supports_post_sub_buffer_;
1790 // These flags are used to override the state of the shared feature_info_
1791 // member. Because the same FeatureInfo instance may be shared among many
1792 // contexts, the assumptions on the availablity of extensions in WebGL
1793 // contexts may be broken. These flags override the shared state to preserve
1794 // WebGL semantics.
1795 bool force_webgl_glsl_validation_;
1796 bool derivatives_explicitly_enabled_;
1797 bool frag_depth_explicitly_enabled_;
1798 bool draw_buffers_explicitly_enabled_;
1799 bool shader_texture_lod_explicitly_enabled_;
1801 bool compile_shader_always_succeeds_;
1803 // An optional behaviour to lose the context and group when OOM.
1804 bool lose_context_when_out_of_memory_;
1806 // Log extra info.
1807 bool service_logging_;
1809 #if defined(OS_MACOSX)
1810 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1811 TextureToIOSurfaceMap texture_to_io_surface_map_;
1812 #endif
1814 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1816 // Cached values of the currently assigned viewport dimensions.
1817 GLsizei viewport_max_width_;
1818 GLsizei viewport_max_height_;
1820 // Command buffer stats.
1821 base::TimeDelta total_processing_commands_time_;
1823 // States related to each manager.
1824 DecoderTextureState texture_state_;
1825 DecoderFramebufferState framebuffer_state_;
1827 scoped_ptr<GPUTracer> gpu_tracer_;
1828 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1829 int gpu_trace_level_;
1830 bool gpu_trace_commands_;
1832 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1834 // Used to validate multisample renderbuffers if needed
1835 GLuint validation_texture_;
1836 GLuint validation_fbo_multisample_;
1837 GLuint validation_fbo_;
1839 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1842 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1843 const char* function_name, ErrorState* error_state)
1844 : function_name_(function_name),
1845 error_state_(error_state) {
1846 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1849 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1850 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1853 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1854 TextureUnit& info = state->texture_units[0];
1855 GLuint last_id;
1856 scoped_refptr<TextureRef> texture_ref;
1857 switch (target) {
1858 case GL_TEXTURE_2D:
1859 texture_ref = info.bound_texture_2d;
1860 break;
1861 case GL_TEXTURE_CUBE_MAP:
1862 texture_ref = info.bound_texture_cube_map;
1863 break;
1864 case GL_TEXTURE_EXTERNAL_OES:
1865 texture_ref = info.bound_texture_external_oes;
1866 break;
1867 case GL_TEXTURE_RECTANGLE_ARB:
1868 texture_ref = info.bound_texture_rectangle_arb;
1869 break;
1870 default:
1871 NOTREACHED();
1872 break;
1874 if (texture_ref.get()) {
1875 last_id = texture_ref->service_id();
1876 } else {
1877 last_id = 0;
1880 glBindTexture(target, last_id);
1881 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1884 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1885 GLuint id,
1886 GLenum target)
1887 : state_(state),
1888 target_(target) {
1889 ScopedGLErrorSuppressor suppressor(
1890 "ScopedTextureBinder::ctor", state_->GetErrorState());
1892 // TODO(apatrick): Check if there are any other states that need to be reset
1893 // before binding a new texture.
1894 glActiveTexture(GL_TEXTURE0);
1895 glBindTexture(target, id);
1898 ScopedTextureBinder::~ScopedTextureBinder() {
1899 ScopedGLErrorSuppressor suppressor(
1900 "ScopedTextureBinder::dtor", state_->GetErrorState());
1901 RestoreCurrentTextureBindings(state_, target_);
1904 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1905 GLuint id)
1906 : state_(state) {
1907 ScopedGLErrorSuppressor suppressor(
1908 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1909 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1912 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1913 ScopedGLErrorSuppressor suppressor(
1914 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1915 state_->RestoreRenderbufferBindings();
1918 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1919 GLuint id)
1920 : decoder_(decoder) {
1921 ScopedGLErrorSuppressor suppressor(
1922 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1923 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1924 decoder->OnFboChanged();
1927 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1928 ScopedGLErrorSuppressor suppressor(
1929 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1930 decoder_->RestoreCurrentFramebufferBindings();
1933 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1934 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1935 : decoder_(decoder) {
1936 resolve_and_bind_ = (
1937 decoder_->offscreen_target_frame_buffer_.get() &&
1938 decoder_->IsOffscreenBufferMultisampled() &&
1939 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1940 enforce_internal_framebuffer));
1941 if (!resolve_and_bind_)
1942 return;
1944 ScopedGLErrorSuppressor suppressor(
1945 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1946 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1947 decoder_->offscreen_target_frame_buffer_->id());
1948 GLuint targetid;
1949 if (internal) {
1950 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1951 decoder_->offscreen_resolved_frame_buffer_.reset(
1952 new BackFramebuffer(decoder_));
1953 decoder_->offscreen_resolved_frame_buffer_->Create();
1954 decoder_->offscreen_resolved_color_texture_.reset(
1955 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1956 decoder_->offscreen_resolved_color_texture_->Create();
1958 DCHECK(decoder_->offscreen_saved_color_format_);
1959 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1960 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1961 false);
1962 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1963 decoder_->offscreen_resolved_color_texture_.get());
1964 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1965 GL_FRAMEBUFFER_COMPLETE) {
1966 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1967 << "because offscreen resolved FBO was incomplete.";
1968 return;
1971 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1972 } else {
1973 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1975 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1976 const int width = decoder_->offscreen_size_.width();
1977 const int height = decoder_->offscreen_size_.height();
1978 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
1979 decoder->BlitFramebufferHelper(0,
1981 width,
1982 height,
1985 width,
1986 height,
1987 GL_COLOR_BUFFER_BIT,
1988 GL_NEAREST);
1989 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1992 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1993 if (!resolve_and_bind_)
1994 return;
1996 ScopedGLErrorSuppressor suppressor(
1997 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
1998 decoder_->RestoreCurrentFramebufferBindings();
1999 if (decoder_->state_.enable_flags.scissor_test) {
2000 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2004 BackTexture::BackTexture(
2005 MemoryTracker* memory_tracker,
2006 ContextState* state)
2007 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2008 state_(state),
2009 bytes_allocated_(0),
2010 id_(0) {
2013 BackTexture::~BackTexture() {
2014 // This does not destroy the render texture because that would require that
2015 // the associated GL context was current. Just check that it was explicitly
2016 // destroyed.
2017 DCHECK_EQ(id_, 0u);
2020 void BackTexture::Create() {
2021 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2022 state_->GetErrorState());
2023 Destroy();
2024 glGenTextures(1, &id_);
2025 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2026 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2027 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2028 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2029 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2031 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2032 // never called on an offscreen context, no data will ever be uploaded to the
2033 // saved offscreen color texture (it is deferred until to when SwapBuffers
2034 // is called). My idea is that some nvidia drivers might have a bug where
2035 // deleting a texture that has never been populated might cause a
2036 // crash.
2037 glTexImage2D(
2038 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2040 bytes_allocated_ = 16u * 16u * 4u;
2041 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2044 bool BackTexture::AllocateStorage(
2045 const gfx::Size& size, GLenum format, bool zero) {
2046 DCHECK_NE(id_, 0u);
2047 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2048 state_->GetErrorState());
2049 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2050 uint32 image_size = 0;
2051 GLES2Util::ComputeImageDataSizes(
2052 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
2053 NULL, NULL);
2055 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2056 return false;
2059 scoped_ptr<char[]> zero_data;
2060 if (zero) {
2061 zero_data.reset(new char[image_size]);
2062 memset(zero_data.get(), 0, image_size);
2065 glTexImage2D(GL_TEXTURE_2D,
2066 0, // mip level
2067 format,
2068 size.width(),
2069 size.height(),
2070 0, // border
2071 format,
2072 GL_UNSIGNED_BYTE,
2073 zero_data.get());
2075 size_ = size;
2077 bool success = glGetError() == GL_NO_ERROR;
2078 if (success) {
2079 memory_tracker_.TrackMemFree(bytes_allocated_);
2080 bytes_allocated_ = image_size;
2081 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2083 return success;
2086 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2087 DCHECK_NE(id_, 0u);
2088 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2089 state_->GetErrorState());
2090 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2091 glCopyTexImage2D(GL_TEXTURE_2D,
2092 0, // level
2093 format,
2094 0, 0,
2095 size.width(),
2096 size.height(),
2097 0); // border
2100 void BackTexture::Destroy() {
2101 if (id_ != 0) {
2102 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2103 state_->GetErrorState());
2104 glDeleteTextures(1, &id_);
2105 id_ = 0;
2107 memory_tracker_.TrackMemFree(bytes_allocated_);
2108 bytes_allocated_ = 0;
2111 void BackTexture::Invalidate() {
2112 id_ = 0;
2115 BackRenderbuffer::BackRenderbuffer(
2116 RenderbufferManager* renderbuffer_manager,
2117 MemoryTracker* memory_tracker,
2118 ContextState* state)
2119 : renderbuffer_manager_(renderbuffer_manager),
2120 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2121 state_(state),
2122 bytes_allocated_(0),
2123 id_(0) {
2126 BackRenderbuffer::~BackRenderbuffer() {
2127 // This does not destroy the render buffer because that would require that
2128 // the associated GL context was current. Just check that it was explicitly
2129 // destroyed.
2130 DCHECK_EQ(id_, 0u);
2133 void BackRenderbuffer::Create() {
2134 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2135 state_->GetErrorState());
2136 Destroy();
2137 glGenRenderbuffersEXT(1, &id_);
2140 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2141 const gfx::Size& size,
2142 GLenum format,
2143 GLsizei samples) {
2144 ScopedGLErrorSuppressor suppressor(
2145 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2146 ScopedRenderBufferBinder binder(state_, id_);
2148 uint32 estimated_size = 0;
2149 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2150 size.width(), size.height(), samples, format, &estimated_size)) {
2151 return false;
2154 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2155 return false;
2158 if (samples <= 1) {
2159 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2160 format,
2161 size.width(),
2162 size.height());
2163 } else {
2164 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2165 GL_RENDERBUFFER,
2166 samples,
2167 format,
2168 size.width(),
2169 size.height());
2171 bool success = glGetError() == GL_NO_ERROR;
2172 if (success) {
2173 // Mark the previously allocated bytes as free.
2174 memory_tracker_.TrackMemFree(bytes_allocated_);
2175 bytes_allocated_ = estimated_size;
2176 // Track the newly allocated bytes.
2177 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2179 return success;
2182 void BackRenderbuffer::Destroy() {
2183 if (id_ != 0) {
2184 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2185 state_->GetErrorState());
2186 glDeleteRenderbuffersEXT(1, &id_);
2187 id_ = 0;
2189 memory_tracker_.TrackMemFree(bytes_allocated_);
2190 bytes_allocated_ = 0;
2193 void BackRenderbuffer::Invalidate() {
2194 id_ = 0;
2197 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2198 : decoder_(decoder),
2199 id_(0) {
2202 BackFramebuffer::~BackFramebuffer() {
2203 // This does not destroy the frame buffer because that would require that
2204 // the associated GL context was current. Just check that it was explicitly
2205 // destroyed.
2206 DCHECK_EQ(id_, 0u);
2209 void BackFramebuffer::Create() {
2210 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2211 decoder_->GetErrorState());
2212 Destroy();
2213 glGenFramebuffersEXT(1, &id_);
2216 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2217 DCHECK_NE(id_, 0u);
2218 ScopedGLErrorSuppressor suppressor(
2219 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2220 ScopedFrameBufferBinder binder(decoder_, id_);
2221 GLuint attach_id = texture ? texture->id() : 0;
2222 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2223 GL_COLOR_ATTACHMENT0,
2224 GL_TEXTURE_2D,
2225 attach_id,
2229 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2230 BackRenderbuffer* render_buffer) {
2231 DCHECK_NE(id_, 0u);
2232 ScopedGLErrorSuppressor suppressor(
2233 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2234 ScopedFrameBufferBinder binder(decoder_, id_);
2235 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2236 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2237 target,
2238 GL_RENDERBUFFER,
2239 attach_id);
2242 void BackFramebuffer::Destroy() {
2243 if (id_ != 0) {
2244 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2245 decoder_->GetErrorState());
2246 glDeleteFramebuffersEXT(1, &id_);
2247 id_ = 0;
2251 void BackFramebuffer::Invalidate() {
2252 id_ = 0;
2255 GLenum BackFramebuffer::CheckStatus() {
2256 DCHECK_NE(id_, 0u);
2257 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2258 decoder_->GetErrorState());
2259 ScopedFrameBufferBinder binder(decoder_, id_);
2260 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2263 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2264 return new GLES2DecoderImpl(group);
2267 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2268 : GLES2Decoder(),
2269 group_(group),
2270 logger_(&debug_marker_manager_),
2271 state_(group_->feature_info(), this, &logger_),
2272 unpack_flip_y_(false),
2273 unpack_premultiply_alpha_(false),
2274 unpack_unpremultiply_alpha_(false),
2275 attrib_0_buffer_id_(0),
2276 attrib_0_buffer_matches_value_(true),
2277 attrib_0_size_(0),
2278 fixed_attrib_buffer_id_(0),
2279 fixed_attrib_buffer_size_(0),
2280 offscreen_target_color_format_(0),
2281 offscreen_target_depth_format_(0),
2282 offscreen_target_stencil_format_(0),
2283 offscreen_target_samples_(0),
2284 offscreen_target_buffer_preserved_(true),
2285 offscreen_saved_color_format_(0),
2286 back_buffer_color_format_(0),
2287 back_buffer_has_depth_(false),
2288 back_buffer_has_stencil_(false),
2289 backbuffer_needs_clear_bits_(0),
2290 current_decoder_error_(error::kNoError),
2291 use_shader_translator_(true),
2292 validators_(group_->feature_info()->validators()),
2293 feature_info_(group_->feature_info()),
2294 frame_number_(0),
2295 has_robustness_extension_(false),
2296 reset_status_(GL_NO_ERROR),
2297 reset_by_robustness_extension_(false),
2298 supports_post_sub_buffer_(false),
2299 force_webgl_glsl_validation_(false),
2300 derivatives_explicitly_enabled_(false),
2301 frag_depth_explicitly_enabled_(false),
2302 draw_buffers_explicitly_enabled_(false),
2303 shader_texture_lod_explicitly_enabled_(false),
2304 compile_shader_always_succeeds_(false),
2305 lose_context_when_out_of_memory_(false),
2306 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2307 switches::kEnableGPUServiceLoggingGPU)),
2308 viewport_max_width_(0),
2309 viewport_max_height_(0),
2310 texture_state_(group_->feature_info()
2311 ->workarounds()
2312 .texsubimage2d_faster_than_teximage2d),
2313 validation_texture_(0),
2314 validation_fbo_multisample_(0),
2315 validation_fbo_(0) {
2316 DCHECK(group);
2318 attrib_0_value_.v[0] = 0.0f;
2319 attrib_0_value_.v[1] = 0.0f;
2320 attrib_0_value_.v[2] = 0.0f;
2321 attrib_0_value_.v[3] = 1.0f;
2323 // The shader translator is used for WebGL even when running on EGL
2324 // because additional restrictions are needed (like only enabling
2325 // GL_OES_standard_derivatives on demand). It is used for the unit
2326 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2327 // the empty string to CompileShader and this is not a valid shader.
2328 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2329 CommandLine::ForCurrentProcess()->HasSwitch(
2330 switches::kDisableGLSLTranslator)) {
2331 use_shader_translator_ = false;
2335 GLES2DecoderImpl::~GLES2DecoderImpl() {
2338 bool GLES2DecoderImpl::Initialize(
2339 const scoped_refptr<gfx::GLSurface>& surface,
2340 const scoped_refptr<gfx::GLContext>& context,
2341 bool offscreen,
2342 const gfx::Size& size,
2343 const DisallowedFeatures& disallowed_features,
2344 const std::vector<int32>& attribs) {
2345 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2346 DCHECK(context->IsCurrent(surface.get()));
2347 DCHECK(!context_.get());
2349 set_initialized();
2350 gpu_tracer_.reset(new GPUTracer(this));
2351 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2352 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2353 gpu_trace_level_ = 2;
2354 gpu_trace_commands_ = false;
2356 if (CommandLine::ForCurrentProcess()->HasSwitch(
2357 switches::kEnableGPUDebugging)) {
2358 set_debug(true);
2361 if (CommandLine::ForCurrentProcess()->HasSwitch(
2362 switches::kEnableGPUCommandLogging)) {
2363 set_log_commands(true);
2366 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2367 switches::kCompileShaderAlwaysSucceeds);
2370 // Take ownership of the context and surface. The surface can be replaced with
2371 // SetSurface.
2372 context_ = context;
2373 surface_ = surface;
2375 ContextCreationAttribHelper attrib_parser;
2376 if (!attrib_parser.Parse(attribs))
2377 return false;
2379 // Save the loseContextWhenOutOfMemory context creation attribute.
2380 lose_context_when_out_of_memory_ =
2381 attrib_parser.lose_context_when_out_of_memory;
2383 // If the failIfMajorPerformanceCaveat context creation attribute was true
2384 // and we are using a software renderer, fail.
2385 if (attrib_parser.fail_if_major_perf_caveat &&
2386 feature_info_->feature_flags().is_swiftshader) {
2387 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2388 Destroy(true);
2389 return false;
2392 if (!group_->Initialize(this, disallowed_features)) {
2393 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2394 << "failed to initialize.";
2395 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2396 Destroy(true);
2397 return false;
2399 CHECK_GL_ERROR();
2401 disallowed_features_ = disallowed_features;
2403 state_.attrib_values.resize(group_->max_vertex_attribs());
2404 vertex_array_manager_.reset(new VertexArrayManager());
2406 GLuint default_vertex_attrib_service_id = 0;
2407 if (features().native_vertex_array_object) {
2408 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2409 glBindVertexArrayOES(default_vertex_attrib_service_id);
2412 state_.default_vertex_attrib_manager =
2413 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2415 state_.default_vertex_attrib_manager->Initialize(
2416 group_->max_vertex_attribs(),
2417 feature_info_->workarounds().init_vertex_attributes);
2419 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2420 DoBindVertexArrayOES(0);
2422 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2424 image_manager_.reset(new ImageManager);
2426 util_.set_num_compressed_texture_formats(
2427 validators_->compressed_texture_format.GetValues().size());
2429 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2430 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2431 // OpenGL ES 2.0 does not have this issue.
2432 glEnableVertexAttribArray(0);
2434 glGenBuffersARB(1, &attrib_0_buffer_id_);
2435 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2436 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2437 glBindBuffer(GL_ARRAY_BUFFER, 0);
2438 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2440 state_.texture_units.resize(group_->max_texture_units());
2441 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2442 glActiveTexture(GL_TEXTURE0 + tt);
2443 // We want the last bind to be 2D.
2444 TextureRef* ref;
2445 if (features().oes_egl_image_external) {
2446 ref = texture_manager()->GetDefaultTextureInfo(
2447 GL_TEXTURE_EXTERNAL_OES);
2448 state_.texture_units[tt].bound_texture_external_oes = ref;
2449 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2451 if (features().arb_texture_rectangle) {
2452 ref = texture_manager()->GetDefaultTextureInfo(
2453 GL_TEXTURE_RECTANGLE_ARB);
2454 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2455 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2457 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2458 state_.texture_units[tt].bound_texture_cube_map = ref;
2459 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2460 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2461 state_.texture_units[tt].bound_texture_2d = ref;
2462 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2464 glActiveTexture(GL_TEXTURE0);
2465 CHECK_GL_ERROR();
2467 if (offscreen) {
2468 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2469 features().chromium_framebuffer_multisample) {
2470 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2471 // max_sample_count must be initialized to a sane value. If
2472 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2473 GLint max_sample_count = 1;
2474 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2475 offscreen_target_samples_ = std::min(attrib_parser.samples,
2476 max_sample_count);
2477 } else {
2478 offscreen_target_samples_ = 1;
2480 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2482 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2483 const bool rgb8_supported =
2484 context_->HasExtension("GL_OES_rgb8_rgba8");
2485 // The only available default render buffer formats in GLES2 have very
2486 // little precision. Don't enable multisampling unless 8-bit render
2487 // buffer formats are available--instead fall back to 8-bit textures.
2488 if (rgb8_supported && offscreen_target_samples_ > 1) {
2489 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2490 GL_RGBA8 : GL_RGB8;
2491 } else {
2492 offscreen_target_samples_ = 1;
2493 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2494 GL_RGBA : GL_RGB;
2497 // ANGLE only supports packed depth/stencil formats, so use it if it is
2498 // available.
2499 const bool depth24_stencil8_supported =
2500 feature_info_->feature_flags().packed_depth24_stencil8;
2501 VLOG(1) << "GL_OES_packed_depth_stencil "
2502 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2503 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2504 depth24_stencil8_supported) {
2505 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2506 offscreen_target_stencil_format_ = 0;
2507 } else {
2508 // It may be the case that this depth/stencil combination is not
2509 // supported, but this will be checked later by CheckFramebufferStatus.
2510 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2511 GL_DEPTH_COMPONENT16 : 0;
2512 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2513 GL_STENCIL_INDEX8 : 0;
2515 } else {
2516 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2517 GL_RGBA : GL_RGB;
2519 // If depth is requested at all, use the packed depth stencil format if
2520 // it's available, as some desktop GL drivers don't support any non-packed
2521 // formats for depth attachments.
2522 const bool depth24_stencil8_supported =
2523 feature_info_->feature_flags().packed_depth24_stencil8;
2524 VLOG(1) << "GL_EXT_packed_depth_stencil "
2525 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2527 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2528 depth24_stencil8_supported) {
2529 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2530 offscreen_target_stencil_format_ = 0;
2531 } else {
2532 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2533 GL_DEPTH_COMPONENT : 0;
2534 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2535 GL_STENCIL_INDEX : 0;
2539 offscreen_saved_color_format_ = attrib_parser.alpha_size > 0 ?
2540 GL_RGBA : GL_RGB;
2542 // Create the target frame buffer. This is the one that the client renders
2543 // directly to.
2544 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2545 offscreen_target_frame_buffer_->Create();
2546 // Due to GLES2 format limitations, either the color texture (for
2547 // non-multisampling) or the color render buffer (for multisampling) will be
2548 // attached to the offscreen frame buffer. The render buffer has more
2549 // limited formats available to it, but the texture can't do multisampling.
2550 if (IsOffscreenBufferMultisampled()) {
2551 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2552 renderbuffer_manager(), memory_tracker(), &state_));
2553 offscreen_target_color_render_buffer_->Create();
2554 } else {
2555 offscreen_target_color_texture_.reset(new BackTexture(
2556 memory_tracker(), &state_));
2557 offscreen_target_color_texture_->Create();
2559 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2560 renderbuffer_manager(), memory_tracker(), &state_));
2561 offscreen_target_depth_render_buffer_->Create();
2562 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2563 renderbuffer_manager(), memory_tracker(), &state_));
2564 offscreen_target_stencil_render_buffer_->Create();
2566 // Create the saved offscreen texture. The target frame buffer is copied
2567 // here when SwapBuffers is called.
2568 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2569 offscreen_saved_frame_buffer_->Create();
2571 offscreen_saved_color_texture_.reset(new BackTexture(
2572 memory_tracker(), &state_));
2573 offscreen_saved_color_texture_->Create();
2575 // Allocate the render buffers at their initial size and check the status
2576 // of the frame buffers is okay.
2577 if (!ResizeOffscreenFrameBuffer(size)) {
2578 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2579 Destroy(true);
2580 return false;
2583 // Allocate the offscreen saved color texture.
2584 DCHECK(offscreen_saved_color_format_);
2585 offscreen_saved_color_texture_->AllocateStorage(
2586 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2588 offscreen_saved_frame_buffer_->AttachRenderTexture(
2589 offscreen_saved_color_texture_.get());
2590 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2591 GL_FRAMEBUFFER_COMPLETE) {
2592 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2593 Destroy(true);
2594 return false;
2597 // Bind to the new default frame buffer (the offscreen target frame buffer).
2598 // This should now be associated with ID zero.
2599 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2600 } else {
2601 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2602 // These are NOT if the back buffer has these proprorties. They are
2603 // if we want the command buffer to enforce them regardless of what
2604 // the real backbuffer is assuming the real back buffer gives us more than
2605 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2606 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2607 // can't do anything about that.
2609 GLint v = 0;
2610 glGetIntegerv(GL_ALPHA_BITS, &v);
2611 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2612 // user requested RGB then RGB. If the user did not specify a preference
2613 // than use whatever we were given. Same for DEPTH and STENCIL.
2614 back_buffer_color_format_ =
2615 (attrib_parser.alpha_size != 0 && v > 0) ? GL_RGBA : GL_RGB;
2616 glGetIntegerv(GL_DEPTH_BITS, &v);
2617 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && v > 0;
2618 glGetIntegerv(GL_STENCIL_BITS, &v);
2619 back_buffer_has_stencil_ = attrib_parser.stencil_size != 0 && v > 0;
2622 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2623 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2624 // isn't well documented; it was discovered in the Khronos OpenGL ES
2625 // mailing list archives. It also implicitly enables the desktop GL
2626 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2627 // variable in fragment shaders.
2628 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2629 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2630 glEnable(GL_POINT_SPRITE);
2633 has_robustness_extension_ =
2634 context->HasExtension("GL_ARB_robustness") ||
2635 context->HasExtension("GL_EXT_robustness");
2637 if (!InitializeShaderTranslator()) {
2638 return false;
2641 state_.viewport_width = size.width();
2642 state_.viewport_height = size.height();
2644 GLint viewport_params[4] = { 0 };
2645 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2646 viewport_max_width_ = viewport_params[0];
2647 viewport_max_height_ = viewport_params[1];
2649 state_.scissor_width = state_.viewport_width;
2650 state_.scissor_height = state_.viewport_height;
2652 // Set all the default state because some GL drivers get it wrong.
2653 state_.InitCapabilities(NULL);
2654 state_.InitState(NULL);
2655 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2657 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2658 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2659 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2660 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2662 bool call_gl_clear = true;
2663 #if defined(OS_ANDROID)
2664 // Temporary workaround for Android WebView because this clear ignores the
2665 // clip and corrupts that external UI of the App. Not calling glClear is ok
2666 // because the system already clears the buffer before each draw. Proper
2667 // fix might be setting the scissor clip properly before initialize. See
2668 // crbug.com/259023 for details.
2669 call_gl_clear = surface_->GetHandle();
2670 #endif
2671 if (call_gl_clear) {
2672 // Clear the backbuffer.
2673 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2676 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2677 if (feature_info_->workarounds()
2678 .disable_post_sub_buffers_for_onscreen_surfaces &&
2679 !surface->IsOffscreen())
2680 supports_post_sub_buffer_ = false;
2682 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2683 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2686 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2687 context_->SetUnbindFboOnMakeCurrent();
2690 // Only compositor contexts are known to use only the subset of GL
2691 // that can be safely migrated between the iGPU and the dGPU. Mark
2692 // those contexts as safe to forcibly transition between the GPUs.
2693 // http://crbug.com/180876, http://crbug.com/227228
2694 if (!offscreen)
2695 context_->SetSafeToForceGpuSwitch();
2697 async_pixel_transfer_manager_.reset(
2698 AsyncPixelTransferManager::Create(context.get()));
2699 async_pixel_transfer_manager_->Initialize(texture_manager());
2701 framebuffer_manager()->AddObserver(this);
2703 return true;
2706 Capabilities GLES2DecoderImpl::GetCapabilities() {
2707 DCHECK(initialized());
2709 Capabilities caps;
2711 caps.egl_image_external =
2712 feature_info_->feature_flags().oes_egl_image_external;
2713 caps.texture_format_bgra8888 =
2714 feature_info_->feature_flags().ext_texture_format_bgra8888;
2715 caps.texture_format_etc1 =
2716 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2717 caps.texture_format_etc1_npot =
2718 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
2719 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2720 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2721 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2722 caps.discard_framebuffer =
2723 feature_info_->feature_flags().ext_discard_framebuffer;
2724 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
2726 #if defined(OS_MACOSX)
2727 // This is unconditionally true on mac, no need to test for it at runtime.
2728 caps.iosurface = true;
2729 #endif
2731 caps.post_sub_buffer = supports_post_sub_buffer_;
2732 caps.map_image = true;
2734 return caps;
2737 void GLES2DecoderImpl::UpdateCapabilities() {
2738 util_.set_num_compressed_texture_formats(
2739 validators_->compressed_texture_format.GetValues().size());
2740 util_.set_num_shader_binary_formats(
2741 validators_->shader_binary_format.GetValues().size());
2744 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2745 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2747 if (!use_shader_translator_) {
2748 return true;
2750 ShBuiltInResources resources;
2751 ShInitBuiltInResources(&resources);
2752 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2753 resources.MaxVertexUniformVectors =
2754 group_->max_vertex_uniform_vectors();
2755 resources.MaxVaryingVectors = group_->max_varying_vectors();
2756 resources.MaxVertexTextureImageUnits =
2757 group_->max_vertex_texture_image_units();
2758 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2759 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2760 resources.MaxFragmentUniformVectors =
2761 group_->max_fragment_uniform_vectors();
2762 resources.MaxDrawBuffers = group_->max_draw_buffers();
2763 resources.MaxExpressionComplexity = 256;
2764 resources.MaxCallStackDepth = 256;
2766 #if (ANGLE_SH_VERSION >= 110)
2767 GLint range[2] = { 0, 0 };
2768 GLint precision = 0;
2769 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2770 range, &precision);
2771 resources.FragmentPrecisionHigh =
2772 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2773 #endif
2775 if (force_webgl_glsl_validation_) {
2776 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2777 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2778 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2779 if (!draw_buffers_explicitly_enabled_)
2780 resources.MaxDrawBuffers = 1;
2781 #if (ANGLE_SH_VERSION >= 123)
2782 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
2783 #endif
2784 } else {
2785 resources.OES_standard_derivatives =
2786 features().oes_standard_derivatives ? 1 : 0;
2787 resources.ARB_texture_rectangle =
2788 features().arb_texture_rectangle ? 1 : 0;
2789 resources.OES_EGL_image_external =
2790 features().oes_egl_image_external ? 1 : 0;
2791 resources.EXT_draw_buffers =
2792 features().ext_draw_buffers ? 1 : 0;
2793 resources.EXT_frag_depth =
2794 features().ext_frag_depth ? 1 : 0;
2795 #if (ANGLE_SH_VERSION >= 123)
2796 resources.EXT_shader_texture_lod =
2797 features().ext_shader_texture_lod ? 1 : 0;
2798 #endif
2801 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2802 : SH_GLES2_SPEC;
2803 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2804 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2805 resources.HashFunction = &CityHashForAngle;
2806 #else
2807 resources.HashFunction = &CityHash64;
2808 #endif
2809 else
2810 resources.HashFunction = NULL;
2811 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2812 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2813 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2814 int driver_bug_workarounds = 0;
2815 if (workarounds().needs_glsl_built_in_function_emulation)
2816 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2817 if (workarounds().init_gl_position_in_vertex_shader)
2818 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2819 if (workarounds().unfold_short_circuit_as_ternary_operation)
2820 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2821 if (workarounds().init_varyings_without_static_use)
2822 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2823 if (workarounds().unroll_for_loop_with_sampler_array_index)
2824 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2825 if (workarounds().scalarize_vec_and_mat_constructor_args)
2826 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
2827 if (workarounds().regenerate_struct_names)
2828 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
2830 vertex_translator_ = shader_translator_cache()->GetTranslator(
2831 #if (ANGLE_SH_VERSION >= 126)
2832 GL_VERTEX_SHADER,
2833 #else
2834 SH_VERTEX_SHADER,
2835 #endif
2836 shader_spec,
2837 &resources,
2838 implementation_type,
2839 static_cast<ShCompileOptions>(driver_bug_workarounds));
2840 if (!vertex_translator_.get()) {
2841 LOG(ERROR) << "Could not initialize vertex shader translator.";
2842 Destroy(true);
2843 return false;
2846 fragment_translator_ = shader_translator_cache()->GetTranslator(
2847 #if (ANGLE_SH_VERSION >= 126)
2848 GL_FRAGMENT_SHADER,
2849 #else
2850 SH_FRAGMENT_SHADER,
2851 #endif
2852 shader_spec,
2853 &resources,
2854 implementation_type,
2855 static_cast<ShCompileOptions>(driver_bug_workarounds));
2856 if (!fragment_translator_.get()) {
2857 LOG(ERROR) << "Could not initialize fragment shader translator.";
2858 Destroy(true);
2859 return false;
2861 return true;
2864 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2865 for (GLsizei ii = 0; ii < n; ++ii) {
2866 if (GetBuffer(client_ids[ii])) {
2867 return false;
2870 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2871 glGenBuffersARB(n, service_ids.get());
2872 for (GLsizei ii = 0; ii < n; ++ii) {
2873 CreateBuffer(client_ids[ii], service_ids[ii]);
2875 return true;
2878 bool GLES2DecoderImpl::GenFramebuffersHelper(
2879 GLsizei n, const GLuint* client_ids) {
2880 for (GLsizei ii = 0; ii < n; ++ii) {
2881 if (GetFramebuffer(client_ids[ii])) {
2882 return false;
2885 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2886 glGenFramebuffersEXT(n, service_ids.get());
2887 for (GLsizei ii = 0; ii < n; ++ii) {
2888 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2890 return true;
2893 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2894 GLsizei n, const GLuint* client_ids) {
2895 for (GLsizei ii = 0; ii < n; ++ii) {
2896 if (GetRenderbuffer(client_ids[ii])) {
2897 return false;
2900 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2901 glGenRenderbuffersEXT(n, service_ids.get());
2902 for (GLsizei ii = 0; ii < n; ++ii) {
2903 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2905 return true;
2908 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2909 for (GLsizei ii = 0; ii < n; ++ii) {
2910 if (GetTexture(client_ids[ii])) {
2911 return false;
2914 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2915 glGenTextures(n, service_ids.get());
2916 for (GLsizei ii = 0; ii < n; ++ii) {
2917 CreateTexture(client_ids[ii], service_ids[ii]);
2919 return true;
2922 void GLES2DecoderImpl::DeleteBuffersHelper(
2923 GLsizei n, const GLuint* client_ids) {
2924 for (GLsizei ii = 0; ii < n; ++ii) {
2925 Buffer* buffer = GetBuffer(client_ids[ii]);
2926 if (buffer && !buffer->IsDeleted()) {
2927 state_.vertex_attrib_manager->Unbind(buffer);
2928 if (state_.bound_array_buffer.get() == buffer) {
2929 state_.bound_array_buffer = NULL;
2931 RemoveBuffer(client_ids[ii]);
2936 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2937 GLsizei n, const GLuint* client_ids) {
2938 bool supports_separate_framebuffer_binds =
2939 features().chromium_framebuffer_multisample;
2941 for (GLsizei ii = 0; ii < n; ++ii) {
2942 Framebuffer* framebuffer =
2943 GetFramebuffer(client_ids[ii]);
2944 if (framebuffer && !framebuffer->IsDeleted()) {
2945 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2946 framebuffer_state_.bound_draw_framebuffer = NULL;
2947 framebuffer_state_.clear_state_dirty = true;
2948 GLenum target = supports_separate_framebuffer_binds ?
2949 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2950 glBindFramebufferEXT(target, GetBackbufferServiceId());
2952 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2953 framebuffer_state_.bound_read_framebuffer = NULL;
2954 GLenum target = supports_separate_framebuffer_binds ?
2955 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2956 glBindFramebufferEXT(target, GetBackbufferServiceId());
2958 OnFboChanged();
2959 RemoveFramebuffer(client_ids[ii]);
2964 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2965 GLsizei n, const GLuint* client_ids) {
2966 bool supports_separate_framebuffer_binds =
2967 features().chromium_framebuffer_multisample;
2968 for (GLsizei ii = 0; ii < n; ++ii) {
2969 Renderbuffer* renderbuffer =
2970 GetRenderbuffer(client_ids[ii]);
2971 if (renderbuffer && !renderbuffer->IsDeleted()) {
2972 if (state_.bound_renderbuffer.get() == renderbuffer) {
2973 state_.bound_renderbuffer = NULL;
2975 // Unbind from current framebuffers.
2976 if (supports_separate_framebuffer_binds) {
2977 if (framebuffer_state_.bound_read_framebuffer.get()) {
2978 framebuffer_state_.bound_read_framebuffer
2979 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2981 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2982 framebuffer_state_.bound_draw_framebuffer
2983 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2985 } else {
2986 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2987 framebuffer_state_.bound_draw_framebuffer
2988 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2991 framebuffer_state_.clear_state_dirty = true;
2992 RemoveRenderbuffer(client_ids[ii]);
2997 void GLES2DecoderImpl::DeleteTexturesHelper(
2998 GLsizei n, const GLuint* client_ids) {
2999 bool supports_separate_framebuffer_binds =
3000 features().chromium_framebuffer_multisample;
3001 for (GLsizei ii = 0; ii < n; ++ii) {
3002 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3003 if (texture_ref) {
3004 Texture* texture = texture_ref->texture();
3005 if (texture->IsAttachedToFramebuffer()) {
3006 framebuffer_state_.clear_state_dirty = true;
3008 // Unbind texture_ref from texture_ref units.
3009 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3010 state_.texture_units[jj].Unbind(texture_ref);
3012 // Unbind from current framebuffers.
3013 if (supports_separate_framebuffer_binds) {
3014 if (framebuffer_state_.bound_read_framebuffer.get()) {
3015 framebuffer_state_.bound_read_framebuffer
3016 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3018 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3019 framebuffer_state_.bound_draw_framebuffer
3020 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3022 } else {
3023 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3024 framebuffer_state_.bound_draw_framebuffer
3025 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3028 #if defined(OS_MACOSX)
3029 GLuint service_id = texture->service_id();
3030 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3031 ReleaseIOSurfaceForTexture(service_id);
3033 #endif
3034 RemoveTexture(client_ids[ii]);
3039 // } // anonymous namespace
3041 bool GLES2DecoderImpl::MakeCurrent() {
3042 if (!context_.get())
3043 return false;
3045 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
3046 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3048 // Some D3D drivers cannot recover from device lost in the GPU process
3049 // sandbox. Allow a new GPU process to launch.
3050 if (workarounds().exit_on_context_lost) {
3051 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
3052 << " a D3D device in the Chrome GPU process sandbox.";
3053 #if defined(OS_WIN)
3054 base::win::SetShouldCrashOnProcessDetach(false);
3055 #endif
3056 exit(0);
3059 return false;
3062 ProcessFinishedAsyncTransfers();
3064 // Rebind the FBO if it was unbound by the context.
3065 if (workarounds().unbind_fbo_on_context_switch)
3066 RestoreFramebufferBindings();
3068 framebuffer_state_.clear_state_dirty = true;
3070 return true;
3073 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3074 ProcessPendingReadPixels();
3075 if (engine() && query_manager_.get())
3076 query_manager_->ProcessPendingTransferQueries();
3078 // TODO(epenner): Is there a better place to do this?
3079 // This needs to occur before we execute any batch of commands
3080 // from the client, as the client may have recieved an async
3081 // completion while issuing those commands.
3082 // "DidFlushStart" would be ideal if we had such a callback.
3083 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3086 static void RebindCurrentFramebuffer(
3087 GLenum target,
3088 Framebuffer* framebuffer,
3089 GLuint back_buffer_service_id) {
3090 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3092 if (framebuffer_id == 0) {
3093 framebuffer_id = back_buffer_service_id;
3096 glBindFramebufferEXT(target, framebuffer_id);
3099 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3100 framebuffer_state_.clear_state_dirty = true;
3102 if (!features().chromium_framebuffer_multisample) {
3103 RebindCurrentFramebuffer(
3104 GL_FRAMEBUFFER,
3105 framebuffer_state_.bound_draw_framebuffer.get(),
3106 GetBackbufferServiceId());
3107 } else {
3108 RebindCurrentFramebuffer(
3109 GL_READ_FRAMEBUFFER_EXT,
3110 framebuffer_state_.bound_read_framebuffer.get(),
3111 GetBackbufferServiceId());
3112 RebindCurrentFramebuffer(
3113 GL_DRAW_FRAMEBUFFER_EXT,
3114 framebuffer_state_.bound_draw_framebuffer.get(),
3115 GetBackbufferServiceId());
3117 OnFboChanged();
3120 bool GLES2DecoderImpl::CheckFramebufferValid(
3121 Framebuffer* framebuffer,
3122 GLenum target, const char* func_name) {
3123 if (!framebuffer) {
3124 if (backbuffer_needs_clear_bits_) {
3125 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3126 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3127 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3128 glClearStencil(0);
3129 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3130 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3131 glClearDepth(1.0f);
3132 state_.SetDeviceDepthMask(GL_TRUE);
3133 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3134 bool reset_draw_buffer = false;
3135 if ((backbuffer_needs_clear_bits_ | GL_COLOR_BUFFER_BIT) != 0 &&
3136 group_->draw_buffer() == GL_NONE) {
3137 reset_draw_buffer = true;
3138 GLenum buf = GL_BACK;
3139 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3140 buf = GL_COLOR_ATTACHMENT0;
3141 glDrawBuffersARB(1, &buf);
3143 glClear(backbuffer_needs_clear_bits_);
3144 if (reset_draw_buffer) {
3145 GLenum buf = GL_NONE;
3146 glDrawBuffersARB(1, &buf);
3148 backbuffer_needs_clear_bits_ = 0;
3149 RestoreClearState();
3151 return true;
3154 if (framebuffer_manager()->IsComplete(framebuffer)) {
3155 return true;
3158 GLenum completeness = framebuffer->IsPossiblyComplete();
3159 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3160 LOCAL_SET_GL_ERROR(
3161 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3162 return false;
3165 // Are all the attachments cleared?
3166 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3167 texture_manager()->HaveUnclearedMips()) {
3168 if (!framebuffer->IsCleared()) {
3169 // Can we clear them?
3170 if (framebuffer->GetStatus(texture_manager(), target) !=
3171 GL_FRAMEBUFFER_COMPLETE) {
3172 LOCAL_SET_GL_ERROR(
3173 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3174 "framebuffer incomplete (clear)");
3175 return false;
3177 ClearUnclearedAttachments(target, framebuffer);
3181 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3182 if (framebuffer->GetStatus(texture_manager(), target) !=
3183 GL_FRAMEBUFFER_COMPLETE) {
3184 LOCAL_SET_GL_ERROR(
3185 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3186 "framebuffer incomplete (check)");
3187 return false;
3189 framebuffer_manager()->MarkAsComplete(framebuffer);
3192 // NOTE: At this point we don't know if the framebuffer is complete but
3193 // we DO know that everything that needs to be cleared has been cleared.
3194 return true;
3197 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3198 if (!features().chromium_framebuffer_multisample) {
3199 bool valid = CheckFramebufferValid(
3200 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3201 func_name);
3203 if (valid)
3204 OnUseFramebuffer();
3206 return valid;
3208 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3209 GL_DRAW_FRAMEBUFFER_EXT,
3210 func_name) &&
3211 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3212 GL_READ_FRAMEBUFFER_EXT,
3213 func_name);
3216 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3217 const char* func_name) {
3218 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3219 framebuffer_state_.bound_read_framebuffer.get() :
3220 framebuffer_state_.bound_draw_framebuffer.get();
3221 if (!framebuffer)
3222 return true;
3223 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3224 LOCAL_SET_GL_ERROR(
3225 GL_INVALID_OPERATION, func_name, "no color image attached");
3226 return false;
3228 return true;
3231 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3232 Framebuffer* framebuffer =
3233 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3234 if (framebuffer != NULL) {
3235 const Framebuffer::Attachment* attachment =
3236 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3237 if (attachment) {
3238 return gfx::Size(attachment->width(), attachment->height());
3240 return gfx::Size(0, 0);
3241 } else if (offscreen_target_frame_buffer_.get()) {
3242 return offscreen_size_;
3243 } else {
3244 return surface_->GetSize();
3248 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3249 Framebuffer* framebuffer =
3250 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3251 if (framebuffer != NULL) {
3252 return framebuffer->GetColorAttachmentTextureType();
3253 } else {
3254 return GL_UNSIGNED_BYTE;
3258 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3259 Framebuffer* framebuffer =
3260 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3261 if (framebuffer != NULL) {
3262 return framebuffer->GetColorAttachmentFormat();
3263 } else if (offscreen_target_frame_buffer_.get()) {
3264 return offscreen_target_color_format_;
3265 } else {
3266 return back_buffer_color_format_;
3270 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3271 Framebuffer* framebuffer =
3272 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3273 if (framebuffer != NULL) {
3274 return framebuffer->GetColorAttachmentFormat();
3275 } else if (offscreen_target_frame_buffer_.get()) {
3276 return offscreen_target_color_format_;
3277 } else {
3278 return back_buffer_color_format_;
3282 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3283 if (!offscreen_saved_color_texture_info_.get())
3284 return;
3285 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3286 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3287 texture_manager()->SetLevelInfo(
3288 offscreen_saved_color_texture_info_.get(),
3289 GL_TEXTURE_2D,
3290 0, // level
3291 GL_RGBA,
3292 offscreen_size_.width(),
3293 offscreen_size_.height(),
3294 1, // depth
3295 0, // border
3296 GL_RGBA,
3297 GL_UNSIGNED_BYTE,
3298 true);
3299 texture_manager()->SetParameteri(
3300 "UpdateParentTextureInfo",
3301 GetErrorState(),
3302 offscreen_saved_color_texture_info_.get(),
3303 GL_TEXTURE_MAG_FILTER,
3304 GL_LINEAR);
3305 texture_manager()->SetParameteri(
3306 "UpdateParentTextureInfo",
3307 GetErrorState(),
3308 offscreen_saved_color_texture_info_.get(),
3309 GL_TEXTURE_MIN_FILTER,
3310 GL_LINEAR);
3311 texture_manager()->SetParameteri(
3312 "UpdateParentTextureInfo",
3313 GetErrorState(),
3314 offscreen_saved_color_texture_info_.get(),
3315 GL_TEXTURE_WRAP_S,
3316 GL_CLAMP_TO_EDGE);
3317 texture_manager()->SetParameteri(
3318 "UpdateParentTextureInfo",
3319 GetErrorState(),
3320 offscreen_saved_color_texture_info_.get(),
3321 GL_TEXTURE_WRAP_T,
3322 GL_CLAMP_TO_EDGE);
3323 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3324 &state_, target);
3325 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3328 void GLES2DecoderImpl::SetResizeCallback(
3329 const base::Callback<void(gfx::Size, float)>& callback) {
3330 resize_callback_ = callback;
3333 Logger* GLES2DecoderImpl::GetLogger() {
3334 return &logger_;
3337 void GLES2DecoderImpl::BeginDecoding() {
3338 gpu_tracer_->BeginDecoding();
3339 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3342 void GLES2DecoderImpl::EndDecoding() {
3343 gpu_tracer_->EndDecoding();
3346 ErrorState* GLES2DecoderImpl::GetErrorState() {
3347 return state_.GetErrorState();
3350 void GLES2DecoderImpl::SetShaderCacheCallback(
3351 const ShaderCacheCallback& callback) {
3352 shader_cache_callback_ = callback;
3355 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3356 const WaitSyncPointCallback& callback) {
3357 wait_sync_point_callback_ = callback;
3360 AsyncPixelTransferManager*
3361 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3362 return async_pixel_transfer_manager_.get();
3365 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3366 async_pixel_transfer_manager_.reset();
3369 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3370 AsyncPixelTransferManager* manager) {
3371 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3374 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3375 uint32* service_texture_id) {
3376 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3377 if (texture_ref) {
3378 *service_texture_id = texture_ref->service_id();
3379 return true;
3381 return false;
3384 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3385 return texture_state_.texture_upload_count +
3386 async_pixel_transfer_manager_->GetTextureUploadCount();
3389 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3390 return texture_state_.total_texture_upload_time +
3391 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3394 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3395 return total_processing_commands_time_;
3398 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3399 total_processing_commands_time_ += time;
3402 void GLES2DecoderImpl::Destroy(bool have_context) {
3403 if (!initialized())
3404 return;
3406 DCHECK(!have_context || context_->IsCurrent(NULL));
3408 // Unbind everything.
3409 state_.vertex_attrib_manager = NULL;
3410 state_.default_vertex_attrib_manager = NULL;
3411 state_.texture_units.clear();
3412 state_.bound_array_buffer = NULL;
3413 state_.current_queries.clear();
3414 framebuffer_state_.bound_read_framebuffer = NULL;
3415 framebuffer_state_.bound_draw_framebuffer = NULL;
3416 state_.bound_renderbuffer = NULL;
3418 if (offscreen_saved_color_texture_info_.get()) {
3419 DCHECK(offscreen_target_color_texture_);
3420 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3421 offscreen_saved_color_texture_->id());
3422 offscreen_saved_color_texture_->Invalidate();
3423 offscreen_saved_color_texture_info_ = NULL;
3425 if (have_context) {
3426 if (copy_texture_CHROMIUM_.get()) {
3427 copy_texture_CHROMIUM_->Destroy();
3428 copy_texture_CHROMIUM_.reset();
3431 if (state_.current_program.get()) {
3432 program_manager()->UnuseProgram(shader_manager(),
3433 state_.current_program.get());
3436 if (attrib_0_buffer_id_) {
3437 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3439 if (fixed_attrib_buffer_id_) {
3440 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3443 if (validation_texture_) {
3444 glDeleteTextures(1, &validation_texture_);
3445 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3446 glDeleteFramebuffersEXT(1, &validation_fbo_);
3449 if (offscreen_target_frame_buffer_.get())
3450 offscreen_target_frame_buffer_->Destroy();
3451 if (offscreen_target_color_texture_.get())
3452 offscreen_target_color_texture_->Destroy();
3453 if (offscreen_target_color_render_buffer_.get())
3454 offscreen_target_color_render_buffer_->Destroy();
3455 if (offscreen_target_depth_render_buffer_.get())
3456 offscreen_target_depth_render_buffer_->Destroy();
3457 if (offscreen_target_stencil_render_buffer_.get())
3458 offscreen_target_stencil_render_buffer_->Destroy();
3459 if (offscreen_saved_frame_buffer_.get())
3460 offscreen_saved_frame_buffer_->Destroy();
3461 if (offscreen_saved_color_texture_.get())
3462 offscreen_saved_color_texture_->Destroy();
3463 if (offscreen_resolved_frame_buffer_.get())
3464 offscreen_resolved_frame_buffer_->Destroy();
3465 if (offscreen_resolved_color_texture_.get())
3466 offscreen_resolved_color_texture_->Destroy();
3467 } else {
3468 if (offscreen_target_frame_buffer_.get())
3469 offscreen_target_frame_buffer_->Invalidate();
3470 if (offscreen_target_color_texture_.get())
3471 offscreen_target_color_texture_->Invalidate();
3472 if (offscreen_target_color_render_buffer_.get())
3473 offscreen_target_color_render_buffer_->Invalidate();
3474 if (offscreen_target_depth_render_buffer_.get())
3475 offscreen_target_depth_render_buffer_->Invalidate();
3476 if (offscreen_target_stencil_render_buffer_.get())
3477 offscreen_target_stencil_render_buffer_->Invalidate();
3478 if (offscreen_saved_frame_buffer_.get())
3479 offscreen_saved_frame_buffer_->Invalidate();
3480 if (offscreen_saved_color_texture_.get())
3481 offscreen_saved_color_texture_->Invalidate();
3482 if (offscreen_resolved_frame_buffer_.get())
3483 offscreen_resolved_frame_buffer_->Invalidate();
3484 if (offscreen_resolved_color_texture_.get())
3485 offscreen_resolved_color_texture_->Invalidate();
3488 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3489 // Otherwise, we can leak objects. http://crbug.com/258772.
3490 // state_.current_program must be reset before group_ is reset because
3491 // the later deletes the ProgramManager object that referred by
3492 // state_.current_program object.
3493 state_.current_program = NULL;
3495 copy_texture_CHROMIUM_.reset();
3497 if (query_manager_.get()) {
3498 query_manager_->Destroy(have_context);
3499 query_manager_.reset();
3502 if (vertex_array_manager_ .get()) {
3503 vertex_array_manager_->Destroy(have_context);
3504 vertex_array_manager_.reset();
3507 if (image_manager_.get()) {
3508 image_manager_->Destroy(have_context);
3509 image_manager_.reset();
3512 offscreen_target_frame_buffer_.reset();
3513 offscreen_target_color_texture_.reset();
3514 offscreen_target_color_render_buffer_.reset();
3515 offscreen_target_depth_render_buffer_.reset();
3516 offscreen_target_stencil_render_buffer_.reset();
3517 offscreen_saved_frame_buffer_.reset();
3518 offscreen_saved_color_texture_.reset();
3519 offscreen_resolved_frame_buffer_.reset();
3520 offscreen_resolved_color_texture_.reset();
3522 // Need to release these before releasing |group_| which may own the
3523 // ShaderTranslatorCache.
3524 fragment_translator_ = NULL;
3525 vertex_translator_ = NULL;
3527 // Should destroy the transfer manager before the texture manager held
3528 // by the context group.
3529 async_pixel_transfer_manager_.reset();
3531 if (group_.get()) {
3532 framebuffer_manager()->RemoveObserver(this);
3533 group_->Destroy(this, have_context);
3534 group_ = NULL;
3537 if (context_.get()) {
3538 context_->ReleaseCurrent(NULL);
3539 context_ = NULL;
3542 #if defined(OS_MACOSX)
3543 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3544 it != texture_to_io_surface_map_.end(); ++it) {
3545 CFRelease(it->second);
3547 texture_to_io_surface_map_.clear();
3548 #endif
3551 void GLES2DecoderImpl::SetSurface(
3552 const scoped_refptr<gfx::GLSurface>& surface) {
3553 DCHECK(context_->IsCurrent(NULL));
3554 DCHECK(surface_.get());
3555 surface_ = surface;
3556 RestoreCurrentFramebufferBindings();
3559 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3560 if (!offscreen_saved_color_texture_.get()) {
3561 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3562 return;
3564 if (!offscreen_saved_color_texture_info_.get()) {
3565 GLuint service_id = offscreen_saved_color_texture_->id();
3566 offscreen_saved_color_texture_info_ = TextureRef::Create(
3567 texture_manager(), 0, service_id);
3568 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3569 GL_TEXTURE_2D);
3570 UpdateParentTextureInfo();
3572 mailbox_manager()->ProduceTexture(
3573 GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
3576 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3577 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3578 if (!is_offscreen) {
3579 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3580 << " with an onscreen framebuffer.";
3581 return false;
3584 if (offscreen_size_ == size)
3585 return true;
3587 offscreen_size_ = size;
3588 int w = offscreen_size_.width();
3589 int h = offscreen_size_.height();
3590 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3591 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3592 << "to allocate storage due to excessive dimensions.";
3593 return false;
3596 // Reallocate the offscreen target buffers.
3597 DCHECK(offscreen_target_color_format_);
3598 if (IsOffscreenBufferMultisampled()) {
3599 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3600 feature_info_.get(),
3601 offscreen_size_,
3602 offscreen_target_color_format_,
3603 offscreen_target_samples_)) {
3604 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3605 << "to allocate storage for offscreen target color buffer.";
3606 return false;
3608 } else {
3609 if (!offscreen_target_color_texture_->AllocateStorage(
3610 offscreen_size_, offscreen_target_color_format_, false)) {
3611 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3612 << "to allocate storage for offscreen target color texture.";
3613 return false;
3616 if (offscreen_target_depth_format_ &&
3617 !offscreen_target_depth_render_buffer_->AllocateStorage(
3618 feature_info_.get(),
3619 offscreen_size_,
3620 offscreen_target_depth_format_,
3621 offscreen_target_samples_)) {
3622 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3623 << "to allocate storage for offscreen target depth buffer.";
3624 return false;
3626 if (offscreen_target_stencil_format_ &&
3627 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3628 feature_info_.get(),
3629 offscreen_size_,
3630 offscreen_target_stencil_format_,
3631 offscreen_target_samples_)) {
3632 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3633 << "to allocate storage for offscreen target stencil buffer.";
3634 return false;
3637 // Attach the offscreen target buffers to the target frame buffer.
3638 if (IsOffscreenBufferMultisampled()) {
3639 offscreen_target_frame_buffer_->AttachRenderBuffer(
3640 GL_COLOR_ATTACHMENT0,
3641 offscreen_target_color_render_buffer_.get());
3642 } else {
3643 offscreen_target_frame_buffer_->AttachRenderTexture(
3644 offscreen_target_color_texture_.get());
3646 if (offscreen_target_depth_format_) {
3647 offscreen_target_frame_buffer_->AttachRenderBuffer(
3648 GL_DEPTH_ATTACHMENT,
3649 offscreen_target_depth_render_buffer_.get());
3651 const bool packed_depth_stencil =
3652 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3653 if (packed_depth_stencil) {
3654 offscreen_target_frame_buffer_->AttachRenderBuffer(
3655 GL_STENCIL_ATTACHMENT,
3656 offscreen_target_depth_render_buffer_.get());
3657 } else if (offscreen_target_stencil_format_) {
3658 offscreen_target_frame_buffer_->AttachRenderBuffer(
3659 GL_STENCIL_ATTACHMENT,
3660 offscreen_target_stencil_render_buffer_.get());
3663 if (offscreen_target_frame_buffer_->CheckStatus() !=
3664 GL_FRAMEBUFFER_COMPLETE) {
3665 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3666 << "because offscreen FBO was incomplete.";
3667 return false;
3670 // Clear the target frame buffer.
3672 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3673 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3674 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3675 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3676 glClearStencil(0);
3677 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3678 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3679 glClearDepth(0);
3680 state_.SetDeviceDepthMask(GL_TRUE);
3681 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3682 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3683 RestoreClearState();
3686 // Destroy the offscreen resolved framebuffers.
3687 if (offscreen_resolved_frame_buffer_.get())
3688 offscreen_resolved_frame_buffer_->Destroy();
3689 if (offscreen_resolved_color_texture_.get())
3690 offscreen_resolved_color_texture_->Destroy();
3691 offscreen_resolved_color_texture_.reset();
3692 offscreen_resolved_frame_buffer_.reset();
3694 return true;
3697 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3698 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3699 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3700 return error::kDeferCommandUntilLater;
3702 GLuint width = static_cast<GLuint>(c.width);
3703 GLuint height = static_cast<GLuint>(c.height);
3704 GLfloat scale_factor = c.scale_factor;
3705 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3707 width = std::max(1U, width);
3708 height = std::max(1U, height);
3710 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3711 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3712 // Make sure that we are done drawing to the back buffer before resizing.
3713 glFinish();
3714 #endif
3715 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3716 if (is_offscreen) {
3717 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3718 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3719 << "ResizeOffscreenFrameBuffer failed.";
3720 return error::kLostContext;
3724 if (!resize_callback_.is_null()) {
3725 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3726 DCHECK(context_->IsCurrent(surface_.get()));
3727 if (!context_->IsCurrent(surface_.get())) {
3728 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3729 << "current after resize callback.";
3730 return error::kLostContext;
3734 return error::kNoError;
3737 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3738 if (command_id > kStartPoint && command_id < kNumCommands) {
3739 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3741 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3744 // Decode command with its arguments, and call the corresponding GL function.
3745 // Note: args is a pointer to the command buffer. As such, it could be changed
3746 // by a (malicious) client at any time, so if validation has to happen, it
3747 // should operate on a copy of them.
3748 error::Error GLES2DecoderImpl::DoCommand(
3749 unsigned int command,
3750 unsigned int arg_count,
3751 const void* cmd_data) {
3752 error::Error result = error::kNoError;
3753 if (log_commands()) {
3754 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3755 // VLOG(1), no luck.
3756 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
3757 << GetCommandName(command);
3759 unsigned int command_index = command - kStartPoint - 1;
3760 if (command_index < arraysize(g_command_info)) {
3761 const CommandInfo& info = g_command_info[command_index];
3762 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3763 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3764 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3765 bool doing_gpu_trace = false;
3766 if (gpu_trace_commands_) {
3767 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3768 doing_gpu_trace = true;
3769 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3773 uint32 immediate_data_size =
3774 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3775 switch (command) {
3776 #define GLES2_CMD_OP(name) \
3777 case cmds::name::kCmdId: \
3778 result = Handle ## name( \
3779 immediate_data_size, \
3780 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3781 break; \
3783 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3784 #undef GLES2_CMD_OP
3787 if (doing_gpu_trace)
3788 gpu_tracer_->End(kTraceDecoder);
3790 if (debug()) {
3791 GLenum error;
3792 while ((error = glGetError()) != GL_NO_ERROR) {
3793 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3794 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3795 << GetCommandName(command);
3796 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3799 } else {
3800 result = error::kInvalidArguments;
3802 } else {
3803 result = DoCommonCommand(command, arg_count, cmd_data);
3805 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3806 result = current_decoder_error_;
3807 current_decoder_error_ = error::kNoError;
3809 return result;
3812 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3813 buffer_manager()->RemoveBuffer(client_id);
3816 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3817 if (GetProgram(client_id)) {
3818 return false;
3820 GLuint service_id = glCreateProgram();
3821 if (service_id != 0) {
3822 CreateProgram(client_id, service_id);
3824 return true;
3827 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3828 if (GetShader(client_id)) {
3829 return false;
3831 GLuint service_id = glCreateShader(type);
3832 if (service_id != 0) {
3833 CreateShader(client_id, service_id, type);
3835 return true;
3838 void GLES2DecoderImpl::DoFinish() {
3839 glFinish();
3840 ProcessPendingReadPixels();
3841 ProcessPendingQueries();
3844 void GLES2DecoderImpl::DoFlush() {
3845 glFlush();
3846 ProcessPendingQueries();
3849 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3850 GLuint texture_index = texture_unit - GL_TEXTURE0;
3851 if (texture_index >= state_.texture_units.size()) {
3852 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3853 "glActiveTexture", texture_unit, "texture_unit");
3854 return;
3856 state_.active_texture_unit = texture_index;
3857 glActiveTexture(texture_unit);
3860 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3861 Buffer* buffer = NULL;
3862 GLuint service_id = 0;
3863 if (client_id != 0) {
3864 buffer = GetBuffer(client_id);
3865 if (!buffer) {
3866 if (!group_->bind_generates_resource()) {
3867 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3868 "glBindBuffer",
3869 "id not generated by glGenBuffers");
3870 return;
3873 // It's a new id so make a buffer buffer for it.
3874 glGenBuffersARB(1, &service_id);
3875 CreateBuffer(client_id, service_id);
3876 buffer = GetBuffer(client_id);
3877 IdAllocatorInterface* id_allocator =
3878 group_->GetIdAllocator(id_namespaces::kBuffers);
3879 id_allocator->MarkAsUsed(client_id);
3882 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3883 if (buffer) {
3884 if (!buffer_manager()->SetTarget(buffer, target)) {
3885 LOCAL_SET_GL_ERROR(
3886 GL_INVALID_OPERATION,
3887 "glBindBuffer", "buffer bound to more than 1 target");
3888 return;
3890 service_id = buffer->service_id();
3892 switch (target) {
3893 case GL_ARRAY_BUFFER:
3894 state_.bound_array_buffer = buffer;
3895 break;
3896 case GL_ELEMENT_ARRAY_BUFFER:
3897 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3898 break;
3899 default:
3900 NOTREACHED(); // Validation should prevent us getting here.
3901 break;
3903 glBindBuffer(target, service_id);
3906 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3907 bool all_draw_buffers) {
3908 Framebuffer* framebuffer =
3909 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3910 if (!all_draw_buffers || !framebuffer) {
3911 return (GLES2Util::GetChannelsForFormat(
3912 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3914 return framebuffer->HasAlphaMRT();
3917 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3918 Framebuffer* framebuffer =
3919 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3920 if (framebuffer) {
3921 return framebuffer->HasDepthAttachment();
3923 if (offscreen_target_frame_buffer_.get()) {
3924 return offscreen_target_depth_format_ != 0;
3926 return back_buffer_has_depth_;
3929 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3930 Framebuffer* framebuffer =
3931 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3932 if (framebuffer) {
3933 return framebuffer->HasStencilAttachment();
3935 if (offscreen_target_frame_buffer_.get()) {
3936 return offscreen_target_stencil_format_ != 0 ||
3937 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3939 return back_buffer_has_stencil_;
3942 void GLES2DecoderImpl::ApplyDirtyState() {
3943 if (framebuffer_state_.clear_state_dirty) {
3944 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
3945 state_.SetDeviceColorMask(state_.color_mask_red,
3946 state_.color_mask_green,
3947 state_.color_mask_blue,
3948 state_.color_mask_alpha && have_alpha);
3950 bool have_depth = BoundFramebufferHasDepthAttachment();
3951 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
3953 bool have_stencil = BoundFramebufferHasStencilAttachment();
3954 state_.SetDeviceStencilMaskSeparate(
3955 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3956 state_.SetDeviceStencilMaskSeparate(
3957 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3959 state_.SetDeviceCapabilityState(
3960 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3961 state_.SetDeviceCapabilityState(
3962 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3963 framebuffer_state_.clear_state_dirty = false;
3967 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
3968 return (offscreen_target_frame_buffer_.get())
3969 ? offscreen_target_frame_buffer_->id()
3970 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
3973 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
3974 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3975 "context", logger_.GetLogPrefix());
3976 // Restore the Framebuffer first because of bugs in Intel drivers.
3977 // Intel drivers incorrectly clip the viewport settings to
3978 // the size of the current framebuffer object.
3979 RestoreFramebufferBindings();
3980 state_.RestoreState(prev_state);
3983 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3984 GLuint service_id =
3985 framebuffer_state_.bound_draw_framebuffer.get()
3986 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3987 : GetBackbufferServiceId();
3988 if (!features().chromium_framebuffer_multisample) {
3989 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3990 } else {
3991 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
3992 service_id = framebuffer_state_.bound_read_framebuffer.get()
3993 ? framebuffer_state_.bound_read_framebuffer->service_id()
3994 : GetBackbufferServiceId();
3995 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3997 OnFboChanged();
4000 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4001 state_.RestoreRenderbufferBindings();
4004 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4005 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4006 if (texture) {
4007 GLenum target = texture->target();
4008 glBindTexture(target, service_id);
4009 glTexParameteri(
4010 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4011 glTexParameteri(
4012 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4013 glTexParameteri(
4014 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4015 glTexParameteri(
4016 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4017 RestoreTextureUnitBindings(state_.active_texture_unit);
4021 void GLES2DecoderImpl::ClearAllAttributes() const {
4022 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4023 // other VAOs.
4024 if (feature_info_->feature_flags().native_vertex_array_object)
4025 glBindVertexArrayOES(0);
4027 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4028 if (i != 0) // Never disable attribute 0
4029 glDisableVertexAttribArray(i);
4030 if(features().angle_instanced_arrays)
4031 glVertexAttribDivisorANGLE(i, 0);
4035 void GLES2DecoderImpl::RestoreAllAttributes() const {
4036 state_.RestoreVertexAttribs();
4039 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4040 state_.SetIgnoreCachedStateForTest(ignore);
4043 void GLES2DecoderImpl::OnFboChanged() const {
4044 if (workarounds().restore_scissor_on_fbo_change)
4045 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
4048 // Called after the FBO is checked for completeness.
4049 void GLES2DecoderImpl::OnUseFramebuffer() const {
4050 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
4051 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
4052 // The driver forgets the correct scissor when modifying the FBO binding.
4053 glScissor(state_.scissor_x,
4054 state_.scissor_y,
4055 state_.scissor_width,
4056 state_.scissor_height);
4058 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4059 // it's unclear how this bug works.
4060 glFlush();
4064 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4065 Framebuffer* framebuffer = NULL;
4066 GLuint service_id = 0;
4067 if (client_id != 0) {
4068 framebuffer = GetFramebuffer(client_id);
4069 if (!framebuffer) {
4070 if (!group_->bind_generates_resource()) {
4071 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4072 "glBindFramebuffer",
4073 "id not generated by glGenFramebuffers");
4074 return;
4077 // It's a new id so make a framebuffer framebuffer for it.
4078 glGenFramebuffersEXT(1, &service_id);
4079 CreateFramebuffer(client_id, service_id);
4080 framebuffer = GetFramebuffer(client_id);
4081 IdAllocatorInterface* id_allocator =
4082 group_->GetIdAllocator(id_namespaces::kFramebuffers);
4083 id_allocator->MarkAsUsed(client_id);
4084 } else {
4085 service_id = framebuffer->service_id();
4087 framebuffer->MarkAsValid();
4089 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4091 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4092 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4095 // vmiura: This looks like dup code
4096 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4097 framebuffer_state_.bound_read_framebuffer = framebuffer;
4100 framebuffer_state_.clear_state_dirty = true;
4102 // If we are rendering to the backbuffer get the FBO id for any simulated
4103 // backbuffer.
4104 if (framebuffer == NULL) {
4105 service_id = GetBackbufferServiceId();
4108 glBindFramebufferEXT(target, service_id);
4109 OnFboChanged();
4112 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4113 Renderbuffer* renderbuffer = NULL;
4114 GLuint service_id = 0;
4115 if (client_id != 0) {
4116 renderbuffer = GetRenderbuffer(client_id);
4117 if (!renderbuffer) {
4118 if (!group_->bind_generates_resource()) {
4119 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4120 "glBindRenderbuffer",
4121 "id not generated by glGenRenderbuffers");
4122 return;
4125 // It's a new id so make a renderbuffer for it.
4126 glGenRenderbuffersEXT(1, &service_id);
4127 CreateRenderbuffer(client_id, service_id);
4128 renderbuffer = GetRenderbuffer(client_id);
4129 IdAllocatorInterface* id_allocator =
4130 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
4131 id_allocator->MarkAsUsed(client_id);
4132 } else {
4133 service_id = renderbuffer->service_id();
4135 renderbuffer->MarkAsValid();
4137 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4138 state_.bound_renderbuffer = renderbuffer;
4139 state_.bound_renderbuffer_valid = true;
4140 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4143 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4144 TextureRef* texture_ref = NULL;
4145 GLuint service_id = 0;
4146 if (client_id != 0) {
4147 texture_ref = GetTexture(client_id);
4148 if (!texture_ref) {
4149 if (!group_->bind_generates_resource()) {
4150 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4151 "glBindTexture",
4152 "id not generated by glGenTextures");
4153 return;
4156 // It's a new id so make a texture texture for it.
4157 glGenTextures(1, &service_id);
4158 DCHECK_NE(0u, service_id);
4159 CreateTexture(client_id, service_id);
4160 texture_ref = GetTexture(client_id);
4161 IdAllocatorInterface* id_allocator =
4162 group_->GetIdAllocator(id_namespaces::kTextures);
4163 id_allocator->MarkAsUsed(client_id);
4165 } else {
4166 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4169 // Check the texture exists
4170 if (texture_ref) {
4171 Texture* texture = texture_ref->texture();
4172 // Check that we are not trying to bind it to a different target.
4173 if (texture->target() != 0 && texture->target() != target) {
4174 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4175 "glBindTexture",
4176 "texture bound to more than 1 target.");
4177 return;
4179 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4180 if (texture->target() == 0) {
4181 texture_manager()->SetTarget(texture_ref, target);
4183 glBindTexture(target, texture->service_id());
4184 } else {
4185 glBindTexture(target, 0);
4188 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4189 unit.bind_target = target;
4190 switch (target) {
4191 case GL_TEXTURE_2D:
4192 unit.bound_texture_2d = texture_ref;
4193 break;
4194 case GL_TEXTURE_CUBE_MAP:
4195 unit.bound_texture_cube_map = texture_ref;
4196 break;
4197 case GL_TEXTURE_EXTERNAL_OES:
4198 unit.bound_texture_external_oes = texture_ref;
4199 break;
4200 case GL_TEXTURE_RECTANGLE_ARB:
4201 unit.bound_texture_rectangle_arb = texture_ref;
4202 break;
4203 default:
4204 NOTREACHED(); // Validation should prevent us getting here.
4205 break;
4209 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4210 if (state_.vertex_attrib_manager->Enable(index, false)) {
4211 if (index != 0 ||
4212 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4213 glDisableVertexAttribArray(index);
4215 } else {
4216 LOCAL_SET_GL_ERROR(
4217 GL_INVALID_VALUE,
4218 "glDisableVertexAttribArray", "index out of range");
4222 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4223 GLsizei numAttachments,
4224 const GLenum* attachments) {
4225 Framebuffer* framebuffer =
4226 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4228 // Validates the attachments. If one of them fails
4229 // the whole command fails.
4230 for (GLsizei i = 0; i < numAttachments; ++i) {
4231 if ((framebuffer &&
4232 !validators_->attachment.IsValid(attachments[i])) ||
4233 (!framebuffer &&
4234 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4235 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4236 "glDiscardFramebufferEXT", attachments[i], "attachments");
4237 return;
4241 // Marks each one of them as not cleared
4242 for (GLsizei i = 0; i < numAttachments; ++i) {
4243 if (framebuffer) {
4244 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4245 texture_manager(),
4246 attachments[i],
4247 false);
4248 } else {
4249 switch (attachments[i]) {
4250 case GL_COLOR_EXT:
4251 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4252 break;
4253 case GL_DEPTH_EXT:
4254 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4255 case GL_STENCIL_EXT:
4256 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4257 break;
4258 default:
4259 NOTREACHED();
4260 break;
4265 // If the default framebuffer is bound but we are still rendering to an
4266 // FBO, translate attachment names that refer to default framebuffer
4267 // channels to corresponding framebuffer attachments.
4268 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4269 for (GLsizei i = 0; i < numAttachments; ++i) {
4270 GLenum attachment = attachments[i];
4271 if (!framebuffer && GetBackbufferServiceId()) {
4272 switch (attachment) {
4273 case GL_COLOR_EXT:
4274 attachment = GL_COLOR_ATTACHMENT0;
4275 break;
4276 case GL_DEPTH_EXT:
4277 attachment = GL_DEPTH_ATTACHMENT;
4278 break;
4279 case GL_STENCIL_EXT:
4280 attachment = GL_STENCIL_ATTACHMENT;
4281 break;
4282 default:
4283 NOTREACHED();
4284 return;
4287 translated_attachments[i] = attachment;
4290 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4293 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4294 if (state_.vertex_attrib_manager->Enable(index, true)) {
4295 glEnableVertexAttribArray(index);
4296 } else {
4297 LOCAL_SET_GL_ERROR(
4298 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4302 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4303 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4304 &state_, target);
4305 if (!texture_ref ||
4306 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4307 LOCAL_SET_GL_ERROR(
4308 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4309 return;
4312 if (target == GL_TEXTURE_CUBE_MAP) {
4313 for (int i = 0; i < 6; ++i) {
4314 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4315 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4316 LOCAL_SET_GL_ERROR(
4317 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4318 return;
4321 } else {
4322 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4323 LOCAL_SET_GL_ERROR(
4324 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4325 return;
4329 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4330 // Workaround for Mac driver bug. In the large scheme of things setting
4331 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4332 // hit so there's probably no need to make this conditional. The bug appears
4333 // to be that if the filtering mode is set to something that doesn't require
4334 // mipmaps for rendering, or is never set to something other than the default,
4335 // then glGenerateMipmap misbehaves.
4336 if (workarounds().set_texture_filter_before_generating_mipmap) {
4337 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4339 glGenerateMipmapEXT(target);
4340 if (workarounds().set_texture_filter_before_generating_mipmap) {
4341 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4342 texture_ref->texture()->min_filter());
4344 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4345 if (error == GL_NO_ERROR) {
4346 texture_manager()->MarkMipmapsGenerated(texture_ref);
4350 bool GLES2DecoderImpl::GetHelper(
4351 GLenum pname, GLint* params, GLsizei* num_written) {
4352 DCHECK(num_written);
4353 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4354 switch (pname) {
4355 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4356 *num_written = 1;
4357 // Return the GL implementation's preferred format and (see below type)
4358 // if we have the GL extension that exposes this. This allows the GPU
4359 // client to use the implementation's preferred format for glReadPixels
4360 // for optimisation.
4362 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4363 // case when requested on integer/floating point buffers but which is
4364 // acceptable on GLES2 and with the GL_OES_read_format extension.
4366 // Therefore if an error occurs we swallow the error and use the
4367 // internal implementation.
4368 if (params) {
4369 if (context_->HasExtension("GL_OES_read_format")) {
4370 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4371 GetErrorState());
4372 glGetIntegerv(pname, params);
4373 if (glGetError() == GL_NO_ERROR)
4374 return true;
4376 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4377 GetBoundReadFrameBufferInternalFormat());
4379 return true;
4380 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4381 *num_written = 1;
4382 if (params) {
4383 if (context_->HasExtension("GL_OES_read_format")) {
4384 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4385 GetErrorState());
4386 glGetIntegerv(pname, params);
4387 if (glGetError() == GL_NO_ERROR)
4388 return true;
4390 *params = GLES2Util::GetPreferredGLReadPixelsType(
4391 GetBoundReadFrameBufferInternalFormat(),
4392 GetBoundReadFrameBufferTextureType());
4394 return true;
4395 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4396 *num_written = 1;
4397 if (params) {
4398 *params = group_->max_fragment_uniform_vectors();
4400 return true;
4401 case GL_MAX_VARYING_VECTORS:
4402 *num_written = 1;
4403 if (params) {
4404 *params = group_->max_varying_vectors();
4406 return true;
4407 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4408 *num_written = 1;
4409 if (params) {
4410 *params = group_->max_vertex_uniform_vectors();
4412 return true;
4415 switch (pname) {
4416 case GL_MAX_VIEWPORT_DIMS:
4417 if (offscreen_target_frame_buffer_.get()) {
4418 *num_written = 2;
4419 if (params) {
4420 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4421 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4423 return true;
4425 return false;
4426 case GL_MAX_SAMPLES:
4427 *num_written = 1;
4428 if (params) {
4429 params[0] = renderbuffer_manager()->max_samples();
4431 return true;
4432 case GL_MAX_RENDERBUFFER_SIZE:
4433 *num_written = 1;
4434 if (params) {
4435 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4437 return true;
4438 case GL_MAX_TEXTURE_SIZE:
4439 *num_written = 1;
4440 if (params) {
4441 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4443 return true;
4444 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4445 *num_written = 1;
4446 if (params) {
4447 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4449 return true;
4450 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4451 *num_written = 1;
4452 if (params) {
4453 params[0] = group_->max_color_attachments();
4455 return true;
4456 case GL_MAX_DRAW_BUFFERS_ARB:
4457 *num_written = 1;
4458 if (params) {
4459 params[0] = group_->max_draw_buffers();
4461 return true;
4462 case GL_ALPHA_BITS:
4463 *num_written = 1;
4464 if (params) {
4465 GLint v = 0;
4466 glGetIntegerv(GL_ALPHA_BITS, &v);
4467 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4469 return true;
4470 case GL_DEPTH_BITS:
4471 *num_written = 1;
4472 if (params) {
4473 GLint v = 0;
4474 glGetIntegerv(GL_DEPTH_BITS, &v);
4475 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4477 return true;
4478 case GL_STENCIL_BITS:
4479 *num_written = 1;
4480 if (params) {
4481 GLint v = 0;
4482 glGetIntegerv(GL_STENCIL_BITS, &v);
4483 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4485 return true;
4486 case GL_COMPRESSED_TEXTURE_FORMATS:
4487 *num_written = validators_->compressed_texture_format.GetValues().size();
4488 if (params) {
4489 for (GLint ii = 0; ii < *num_written; ++ii) {
4490 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4493 return true;
4494 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4495 *num_written = 1;
4496 if (params) {
4497 *params = validators_->compressed_texture_format.GetValues().size();
4499 return true;
4500 case GL_NUM_SHADER_BINARY_FORMATS:
4501 *num_written = 1;
4502 if (params) {
4503 *params = validators_->shader_binary_format.GetValues().size();
4505 return true;
4506 case GL_SHADER_BINARY_FORMATS:
4507 *num_written = validators_->shader_binary_format.GetValues().size();
4508 if (params) {
4509 for (GLint ii = 0; ii < *num_written; ++ii) {
4510 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4513 return true;
4514 case GL_SHADER_COMPILER:
4515 *num_written = 1;
4516 if (params) {
4517 *params = GL_TRUE;
4519 return true;
4520 case GL_ARRAY_BUFFER_BINDING:
4521 *num_written = 1;
4522 if (params) {
4523 if (state_.bound_array_buffer.get()) {
4524 GLuint client_id = 0;
4525 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4526 &client_id);
4527 *params = client_id;
4528 } else {
4529 *params = 0;
4532 return true;
4533 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4534 *num_written = 1;
4535 if (params) {
4536 if (state_.vertex_attrib_manager->element_array_buffer()) {
4537 GLuint client_id = 0;
4538 buffer_manager()->GetClientId(
4539 state_.vertex_attrib_manager->element_array_buffer()->
4540 service_id(), &client_id);
4541 *params = client_id;
4542 } else {
4543 *params = 0;
4546 return true;
4547 case GL_FRAMEBUFFER_BINDING:
4548 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4549 *num_written = 1;
4550 if (params) {
4551 Framebuffer* framebuffer =
4552 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4553 if (framebuffer) {
4554 GLuint client_id = 0;
4555 framebuffer_manager()->GetClientId(
4556 framebuffer->service_id(), &client_id);
4557 *params = client_id;
4558 } else {
4559 *params = 0;
4562 return true;
4563 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4564 *num_written = 1;
4565 if (params) {
4566 Framebuffer* framebuffer =
4567 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4568 if (framebuffer) {
4569 GLuint client_id = 0;
4570 framebuffer_manager()->GetClientId(
4571 framebuffer->service_id(), &client_id);
4572 *params = client_id;
4573 } else {
4574 *params = 0;
4577 return true;
4578 case GL_RENDERBUFFER_BINDING:
4579 *num_written = 1;
4580 if (params) {
4581 Renderbuffer* renderbuffer =
4582 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4583 if (renderbuffer) {
4584 *params = renderbuffer->client_id();
4585 } else {
4586 *params = 0;
4589 return true;
4590 case GL_CURRENT_PROGRAM:
4591 *num_written = 1;
4592 if (params) {
4593 if (state_.current_program.get()) {
4594 GLuint client_id = 0;
4595 program_manager()->GetClientId(
4596 state_.current_program->service_id(), &client_id);
4597 *params = client_id;
4598 } else {
4599 *params = 0;
4602 return true;
4603 case GL_VERTEX_ARRAY_BINDING_OES:
4604 *num_written = 1;
4605 if (params) {
4606 if (state_.vertex_attrib_manager.get() !=
4607 state_.default_vertex_attrib_manager.get()) {
4608 GLuint client_id = 0;
4609 vertex_array_manager_->GetClientId(
4610 state_.vertex_attrib_manager->service_id(), &client_id);
4611 *params = client_id;
4612 } else {
4613 *params = 0;
4616 return true;
4617 case GL_TEXTURE_BINDING_2D:
4618 *num_written = 1;
4619 if (params) {
4620 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4621 if (unit.bound_texture_2d.get()) {
4622 *params = unit.bound_texture_2d->client_id();
4623 } else {
4624 *params = 0;
4627 return true;
4628 case GL_TEXTURE_BINDING_CUBE_MAP:
4629 *num_written = 1;
4630 if (params) {
4631 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4632 if (unit.bound_texture_cube_map.get()) {
4633 *params = unit.bound_texture_cube_map->client_id();
4634 } else {
4635 *params = 0;
4638 return true;
4639 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4640 *num_written = 1;
4641 if (params) {
4642 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4643 if (unit.bound_texture_external_oes.get()) {
4644 *params = unit.bound_texture_external_oes->client_id();
4645 } else {
4646 *params = 0;
4649 return true;
4650 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4651 *num_written = 1;
4652 if (params) {
4653 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4654 if (unit.bound_texture_rectangle_arb.get()) {
4655 *params = unit.bound_texture_rectangle_arb->client_id();
4656 } else {
4657 *params = 0;
4660 return true;
4661 case GL_UNPACK_FLIP_Y_CHROMIUM:
4662 *num_written = 1;
4663 if (params) {
4664 params[0] = unpack_flip_y_;
4666 return true;
4667 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4668 *num_written = 1;
4669 if (params) {
4670 params[0] = unpack_premultiply_alpha_;
4672 return true;
4673 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4674 *num_written = 1;
4675 if (params) {
4676 params[0] = unpack_unpremultiply_alpha_;
4678 return true;
4679 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
4680 *num_written = 1;
4681 if (params) {
4682 params[0] = group_->bind_generates_resource() ? 1 : 0;
4684 return true;
4685 default:
4686 if (pname >= GL_DRAW_BUFFER0_ARB &&
4687 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4688 *num_written = 1;
4689 if (params) {
4690 Framebuffer* framebuffer =
4691 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4692 if (framebuffer) {
4693 params[0] = framebuffer->GetDrawBuffer(pname);
4694 } else { // backbuffer
4695 if (pname == GL_DRAW_BUFFER0_ARB)
4696 params[0] = group_->draw_buffer();
4697 else
4698 params[0] = GL_NONE;
4701 return true;
4703 *num_written = util_.GLGetNumValuesReturned(pname);
4704 return false;
4708 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4709 GLenum pname, GLsizei* num_values) {
4710 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4711 return true;
4713 return GetHelper(pname, NULL, num_values);
4716 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4717 if (GL_MAX_SAMPLES == pname &&
4718 features().use_img_for_multisampled_render_to_texture) {
4719 return GL_MAX_SAMPLES_IMG;
4721 return pname;
4724 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4725 DCHECK(params);
4726 GLsizei num_written = 0;
4727 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4728 scoped_ptr<GLint[]> values(new GLint[num_written]);
4729 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4730 GetHelper(pname, values.get(), &num_written);
4732 for (GLsizei ii = 0; ii < num_written; ++ii) {
4733 params[ii] = static_cast<GLboolean>(values[ii]);
4735 } else {
4736 pname = AdjustGetPname(pname);
4737 glGetBooleanv(pname, params);
4741 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4742 DCHECK(params);
4743 GLsizei num_written = 0;
4744 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4745 if (GetHelper(pname, NULL, &num_written)) {
4746 scoped_ptr<GLint[]> values(new GLint[num_written]);
4747 GetHelper(pname, values.get(), &num_written);
4748 for (GLsizei ii = 0; ii < num_written; ++ii) {
4749 params[ii] = static_cast<GLfloat>(values[ii]);
4751 } else {
4752 pname = AdjustGetPname(pname);
4753 glGetFloatv(pname, params);
4758 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4759 DCHECK(params);
4760 GLsizei num_written;
4761 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4762 !GetHelper(pname, params, &num_written)) {
4763 pname = AdjustGetPname(pname);
4764 glGetIntegerv(pname, params);
4768 void GLES2DecoderImpl::DoGetProgramiv(
4769 GLuint program_id, GLenum pname, GLint* params) {
4770 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4771 if (!program) {
4772 return;
4774 program->GetProgramiv(pname, params);
4777 void GLES2DecoderImpl::DoGetBufferParameteriv(
4778 GLenum target, GLenum pname, GLint* params) {
4779 // Just delegate it. Some validation is actually done before this.
4780 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4781 &state_, target, pname, params);
4784 void GLES2DecoderImpl::DoBindAttribLocation(
4785 GLuint program_id, GLuint index, const char* name) {
4786 if (!StringIsValidForGLES(name)) {
4787 LOCAL_SET_GL_ERROR(
4788 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4789 return;
4791 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4792 LOCAL_SET_GL_ERROR(
4793 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4794 return;
4796 if (index >= group_->max_vertex_attribs()) {
4797 LOCAL_SET_GL_ERROR(
4798 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4799 return;
4801 Program* program = GetProgramInfoNotShader(
4802 program_id, "glBindAttribLocation");
4803 if (!program) {
4804 return;
4806 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4807 glBindAttribLocation(program->service_id(), index, name);
4810 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4811 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
4812 GLuint program = static_cast<GLuint>(c.program);
4813 GLuint index = static_cast<GLuint>(c.index);
4814 Bucket* bucket = GetBucket(c.name_bucket_id);
4815 if (!bucket || bucket->size() == 0) {
4816 return error::kInvalidArguments;
4818 std::string name_str;
4819 if (!bucket->GetAsString(&name_str)) {
4820 return error::kInvalidArguments;
4822 DoBindAttribLocation(program, index, name_str.c_str());
4823 return error::kNoError;
4826 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4827 GLuint program_id, GLint location, const char* name) {
4828 if (!StringIsValidForGLES(name)) {
4829 LOCAL_SET_GL_ERROR(
4830 GL_INVALID_VALUE,
4831 "glBindUniformLocationCHROMIUM", "Invalid character");
4832 return;
4834 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4835 LOCAL_SET_GL_ERROR(
4836 GL_INVALID_OPERATION,
4837 "glBindUniformLocationCHROMIUM", "reserved prefix");
4838 return;
4840 if (location < 0 || static_cast<uint32>(location) >=
4841 (group_->max_fragment_uniform_vectors() +
4842 group_->max_vertex_uniform_vectors()) * 4) {
4843 LOCAL_SET_GL_ERROR(
4844 GL_INVALID_VALUE,
4845 "glBindUniformLocationCHROMIUM", "location out of range");
4846 return;
4848 Program* program = GetProgramInfoNotShader(
4849 program_id, "glBindUniformLocationCHROMIUM");
4850 if (!program) {
4851 return;
4853 if (!program->SetUniformLocationBinding(name, location)) {
4854 LOCAL_SET_GL_ERROR(
4855 GL_INVALID_VALUE,
4856 "glBindUniformLocationCHROMIUM", "location out of range");
4860 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4861 uint32 immediate_data_size,
4862 const cmds::BindUniformLocationCHROMIUMBucket& c) {
4863 GLuint program = static_cast<GLuint>(c.program);
4864 GLint location = static_cast<GLint>(c.location);
4865 Bucket* bucket = GetBucket(c.name_bucket_id);
4866 if (!bucket || bucket->size() == 0) {
4867 return error::kInvalidArguments;
4869 std::string name_str;
4870 if (!bucket->GetAsString(&name_str)) {
4871 return error::kInvalidArguments;
4873 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4874 return error::kNoError;
4877 error::Error GLES2DecoderImpl::HandleDeleteShader(
4878 uint32 immediate_data_size, const cmds::DeleteShader& c) {
4879 GLuint client_id = c.shader;
4880 if (client_id) {
4881 Shader* shader = GetShader(client_id);
4882 if (shader) {
4883 if (!shader->IsDeleted()) {
4884 glDeleteShader(shader->service_id());
4885 shader_manager()->MarkAsDeleted(shader);
4887 } else {
4888 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4891 return error::kNoError;
4894 error::Error GLES2DecoderImpl::HandleDeleteProgram(
4895 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
4896 GLuint client_id = c.program;
4897 if (client_id) {
4898 Program* program = GetProgram(client_id);
4899 if (program) {
4900 if (!program->IsDeleted()) {
4901 program_manager()->MarkAsDeleted(shader_manager(), program);
4903 } else {
4904 LOCAL_SET_GL_ERROR(
4905 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4908 return error::kNoError;
4911 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4912 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4913 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4914 for (GLsizei ii = 0; ii < n; ++ii) {
4915 id_allocator->FreeID(ids[ii]);
4919 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4920 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
4921 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4922 GLsizei n = static_cast<GLsizei>(c.n);
4923 uint32 data_size;
4924 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4925 return error::kOutOfBounds;
4927 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4928 c.ids_shm_id, c.ids_shm_offset, data_size);
4929 if (n < 0) {
4930 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
4931 return error::kNoError;
4933 if (ids == NULL) {
4934 return error::kOutOfBounds;
4936 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4937 return error::kNoError;
4940 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4941 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4942 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4943 if (id_offset == 0) {
4944 for (GLsizei ii = 0; ii < n; ++ii) {
4945 ids[ii] = id_allocator->AllocateID();
4947 } else {
4948 for (GLsizei ii = 0; ii < n; ++ii) {
4949 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4950 id_offset = ids[ii] + 1;
4955 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4956 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
4957 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4958 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4959 GLsizei n = static_cast<GLsizei>(c.n);
4960 uint32 data_size;
4961 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4962 return error::kOutOfBounds;
4964 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4965 c.ids_shm_id, c.ids_shm_offset, data_size);
4966 if (n < 0) {
4967 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
4968 return error::kNoError;
4970 if (ids == NULL) {
4971 return error::kOutOfBounds;
4973 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4974 return error::kNoError;
4977 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4978 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4979 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4980 for (GLsizei ii = 0; ii < n; ++ii) {
4981 if (!id_allocator->MarkAsUsed(ids[ii])) {
4982 for (GLsizei jj = 0; jj < ii; ++jj) {
4983 id_allocator->FreeID(ids[jj]);
4985 LOCAL_SET_GL_ERROR(
4986 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4987 "attempt to register id that already exists");
4988 return;
4993 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4994 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
4995 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4996 GLsizei n = static_cast<GLsizei>(c.n);
4997 uint32 data_size;
4998 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4999 return error::kOutOfBounds;
5001 GLuint* ids = GetSharedMemoryAs<GLuint*>(
5002 c.ids_shm_id, c.ids_shm_offset, data_size);
5003 if (n < 0) {
5004 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
5005 return error::kNoError;
5007 if (ids == NULL) {
5008 return error::kOutOfBounds;
5010 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
5011 return error::kNoError;
5014 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5015 DCHECK(!ShouldDeferDraws());
5016 if (CheckBoundFramebuffersValid("glClear")) {
5017 ApplyDirtyState();
5018 glClear(mask);
5020 return error::kNoError;
5023 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5024 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5025 GLuint client_renderbuffer_id) {
5026 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5027 if (!framebuffer) {
5028 LOCAL_SET_GL_ERROR(
5029 GL_INVALID_OPERATION,
5030 "glFramebufferRenderbuffer", "no framebuffer bound");
5031 return;
5033 GLuint service_id = 0;
5034 Renderbuffer* renderbuffer = NULL;
5035 if (client_renderbuffer_id) {
5036 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5037 if (!renderbuffer) {
5038 LOCAL_SET_GL_ERROR(
5039 GL_INVALID_OPERATION,
5040 "glFramebufferRenderbuffer", "unknown renderbuffer");
5041 return;
5043 service_id = renderbuffer->service_id();
5045 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5046 glFramebufferRenderbufferEXT(
5047 target, attachment, renderbuffertarget, service_id);
5048 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5049 if (error == GL_NO_ERROR) {
5050 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5052 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5053 framebuffer_state_.clear_state_dirty = true;
5055 OnFboChanged();
5058 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5059 if (SetCapabilityState(cap, false)) {
5060 glDisable(cap);
5064 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5065 if (SetCapabilityState(cap, true)) {
5066 glEnable(cap);
5070 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5071 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5072 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5073 glDepthRange(znear, zfar);
5076 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5077 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5078 state_.sample_coverage_invert = (invert != 0);
5079 glSampleCoverage(state_.sample_coverage_value, invert);
5082 // Assumes framebuffer is complete.
5083 void GLES2DecoderImpl::ClearUnclearedAttachments(
5084 GLenum target, Framebuffer* framebuffer) {
5085 if (target == GL_READ_FRAMEBUFFER_EXT) {
5086 // bind this to the DRAW point, clear then bind back to READ
5087 // TODO(gman): I don't think there is any guarantee that an FBO that
5088 // is complete on the READ attachment will be complete as a DRAW
5089 // attachment.
5090 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5091 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5093 GLbitfield clear_bits = 0;
5094 if (framebuffer->HasUnclearedColorAttachments()) {
5095 glClearColor(
5096 0.0f, 0.0f, 0.0f,
5097 (GLES2Util::GetChannelsForFormat(
5098 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5099 1.0f);
5100 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5101 clear_bits |= GL_COLOR_BUFFER_BIT;
5102 if (feature_info_->feature_flags().ext_draw_buffers)
5103 framebuffer->PrepareDrawBuffersForClear();
5106 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5107 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5108 glClearStencil(0);
5109 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5110 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5111 clear_bits |= GL_STENCIL_BUFFER_BIT;
5114 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5115 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5116 glClearDepth(1.0f);
5117 state_.SetDeviceDepthMask(GL_TRUE);
5118 clear_bits |= GL_DEPTH_BUFFER_BIT;
5121 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5122 glClear(clear_bits);
5124 if ((clear_bits | GL_COLOR_BUFFER_BIT) != 0 &&
5125 feature_info_->feature_flags().ext_draw_buffers)
5126 framebuffer->RestoreDrawBuffersAfterClear();
5128 framebuffer_manager()->MarkAttachmentsAsCleared(
5129 framebuffer, renderbuffer_manager(), texture_manager());
5131 RestoreClearState();
5133 if (target == GL_READ_FRAMEBUFFER_EXT) {
5134 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5135 Framebuffer* draw_framebuffer =
5136 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5137 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5138 GetBackbufferServiceId();
5139 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5143 void GLES2DecoderImpl::RestoreClearState() {
5144 framebuffer_state_.clear_state_dirty = true;
5145 glClearColor(
5146 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5147 state_.color_clear_alpha);
5148 glClearStencil(state_.stencil_clear);
5149 glClearDepth(state_.depth_clear);
5150 if (state_.enable_flags.scissor_test) {
5151 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5155 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5156 Framebuffer* framebuffer =
5157 GetFramebufferInfoForTarget(target);
5158 if (!framebuffer) {
5159 return GL_FRAMEBUFFER_COMPLETE;
5161 GLenum completeness = framebuffer->IsPossiblyComplete();
5162 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5163 return completeness;
5165 return framebuffer->GetStatus(texture_manager(), target);
5168 void GLES2DecoderImpl::DoFramebufferTexture2D(
5169 GLenum target, GLenum attachment, GLenum textarget,
5170 GLuint client_texture_id, GLint level) {
5171 DoFramebufferTexture2DCommon(
5172 "glFramebufferTexture2D", target, attachment,
5173 textarget, client_texture_id, level, 0);
5176 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5177 GLenum target, GLenum attachment, GLenum textarget,
5178 GLuint client_texture_id, GLint level, GLsizei samples) {
5179 DoFramebufferTexture2DCommon(
5180 "glFramebufferTexture2DMultisample", target, attachment,
5181 textarget, client_texture_id, level, samples);
5184 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5185 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5186 GLuint client_texture_id, GLint level, GLsizei samples) {
5187 if (samples > renderbuffer_manager()->max_samples()) {
5188 LOCAL_SET_GL_ERROR(
5189 GL_INVALID_VALUE,
5190 "glFramebufferTexture2DMultisample", "samples too large");
5191 return;
5193 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5194 if (!framebuffer) {
5195 LOCAL_SET_GL_ERROR(
5196 GL_INVALID_OPERATION,
5197 name, "no framebuffer bound.");
5198 return;
5200 GLuint service_id = 0;
5201 TextureRef* texture_ref = NULL;
5202 if (client_texture_id) {
5203 texture_ref = GetTexture(client_texture_id);
5204 if (!texture_ref) {
5205 LOCAL_SET_GL_ERROR(
5206 GL_INVALID_OPERATION,
5207 name, "unknown texture_ref");
5208 return;
5210 service_id = texture_ref->service_id();
5213 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5214 LOCAL_SET_GL_ERROR(
5215 GL_INVALID_VALUE,
5216 name, "level out of range");
5217 return;
5220 if (texture_ref)
5221 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5223 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5224 if (0 == samples) {
5225 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5226 } else {
5227 if (features().use_img_for_multisampled_render_to_texture) {
5228 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5229 service_id, level, samples);
5230 } else {
5231 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5232 service_id, level, samples);
5235 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5236 if (error == GL_NO_ERROR) {
5237 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5238 samples);
5240 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5241 framebuffer_state_.clear_state_dirty = true;
5244 if (texture_ref)
5245 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5247 OnFboChanged();
5250 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5251 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5252 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5253 if (!framebuffer) {
5254 LOCAL_SET_GL_ERROR(
5255 GL_INVALID_OPERATION,
5256 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5257 return;
5259 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5260 const Framebuffer::Attachment* attachment_object =
5261 framebuffer->GetAttachment(attachment);
5262 *params = attachment_object ? attachment_object->object_name() : 0;
5263 } else {
5264 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5265 features().use_img_for_multisampled_render_to_texture) {
5266 pname = GL_TEXTURE_SAMPLES_IMG;
5268 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5272 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5273 GLenum target, GLenum pname, GLint* params) {
5274 Renderbuffer* renderbuffer =
5275 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5276 if (!renderbuffer) {
5277 LOCAL_SET_GL_ERROR(
5278 GL_INVALID_OPERATION,
5279 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5280 return;
5283 EnsureRenderbufferBound();
5284 switch (pname) {
5285 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5286 *params = renderbuffer->internal_format();
5287 break;
5288 case GL_RENDERBUFFER_WIDTH:
5289 *params = renderbuffer->width();
5290 break;
5291 case GL_RENDERBUFFER_HEIGHT:
5292 *params = renderbuffer->height();
5293 break;
5294 case GL_RENDERBUFFER_SAMPLES_EXT:
5295 if (features().use_img_for_multisampled_render_to_texture) {
5296 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5297 params);
5298 } else {
5299 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5300 params);
5302 default:
5303 glGetRenderbufferParameterivEXT(target, pname, params);
5304 break;
5308 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5309 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5310 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5311 GLbitfield mask, GLenum filter) {
5312 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5314 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5315 return;
5318 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5319 BlitFramebufferHelper(
5320 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5321 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5322 state_.enable_flags.scissor_test);
5325 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5326 if (!state_.bound_renderbuffer_valid) {
5327 state_.bound_renderbuffer_valid = true;
5328 glBindRenderbufferEXT(GL_RENDERBUFFER,
5329 state_.bound_renderbuffer.get()
5330 ? state_.bound_renderbuffer->service_id()
5331 : 0);
5335 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5336 const FeatureInfo* feature_info,
5337 GLenum target,
5338 GLsizei samples,
5339 GLenum internal_format,
5340 GLsizei width,
5341 GLsizei height) {
5342 // TODO(sievers): This could be resolved at the GL binding level, but the
5343 // binding process is currently a bit too 'brute force'.
5344 if (feature_info->feature_flags().is_angle) {
5345 glRenderbufferStorageMultisampleANGLE(
5346 target, samples, internal_format, width, height);
5347 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5348 glRenderbufferStorageMultisample(
5349 target, samples, internal_format, width, height);
5350 } else {
5351 glRenderbufferStorageMultisampleEXT(
5352 target, samples, internal_format, width, height);
5356 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5357 GLint srcY0,
5358 GLint srcX1,
5359 GLint srcY1,
5360 GLint dstX0,
5361 GLint dstY0,
5362 GLint dstX1,
5363 GLint dstY1,
5364 GLbitfield mask,
5365 GLenum filter) {
5366 // TODO(sievers): This could be resolved at the GL binding level, but the
5367 // binding process is currently a bit too 'brute force'.
5368 if (feature_info_->feature_flags().is_angle) {
5369 glBlitFramebufferANGLE(
5370 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5371 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5372 glBlitFramebuffer(
5373 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5374 } else {
5375 glBlitFramebufferEXT(
5376 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5380 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5381 GLsizei samples,
5382 GLenum internalformat,
5383 GLsizei width,
5384 GLsizei height) {
5385 if (samples > renderbuffer_manager()->max_samples()) {
5386 LOCAL_SET_GL_ERROR(
5387 GL_INVALID_VALUE,
5388 "glRenderbufferStorageMultisample", "samples too large");
5389 return false;
5392 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5393 height > renderbuffer_manager()->max_renderbuffer_size()) {
5394 LOCAL_SET_GL_ERROR(
5395 GL_INVALID_VALUE,
5396 "glRenderbufferStorageMultisample", "dimensions too large");
5397 return false;
5400 uint32 estimated_size = 0;
5401 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5402 width, height, samples, internalformat, &estimated_size)) {
5403 LOCAL_SET_GL_ERROR(
5404 GL_OUT_OF_MEMORY,
5405 "glRenderbufferStorageMultisample", "dimensions too large");
5406 return false;
5409 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5410 LOCAL_SET_GL_ERROR(
5411 GL_OUT_OF_MEMORY,
5412 "glRenderbufferStorageMultisample", "out of memory");
5413 return false;
5416 return true;
5419 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5420 GLenum target, GLsizei samples, GLenum internalformat,
5421 GLsizei width, GLsizei height) {
5422 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5423 if (!renderbuffer) {
5424 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5425 "glRenderbufferStorageMultisampleCHROMIUM",
5426 "no renderbuffer bound");
5427 return;
5430 if (!ValidateRenderbufferStorageMultisample(
5431 samples, internalformat, width, height)) {
5432 return;
5435 EnsureRenderbufferBound();
5436 GLenum impl_format =
5437 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5438 internalformat);
5439 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5440 "glRenderbufferStorageMultisampleCHROMIUM");
5441 RenderbufferStorageMultisampleHelper(
5442 feature_info_.get(), target, samples, impl_format, width, height);
5443 GLenum error =
5444 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5445 if (error == GL_NO_ERROR) {
5447 if (workarounds().validate_multisample_buffer_allocation) {
5448 if (!VerifyMultisampleRenderbufferIntegrity(
5449 renderbuffer->service_id(), impl_format)) {
5450 LOCAL_SET_GL_ERROR(
5451 GL_OUT_OF_MEMORY,
5452 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5453 return;
5457 // TODO(gman): If renderbuffers tracked which framebuffers they were
5458 // attached to we could just mark those framebuffers as not complete.
5459 framebuffer_manager()->IncFramebufferStateChangeCount();
5460 renderbuffer_manager()->SetInfo(
5461 renderbuffer, samples, internalformat, width, height);
5465 // This is the handler for multisampled_render_to_texture extensions.
5466 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5467 GLenum target, GLsizei samples, GLenum internalformat,
5468 GLsizei width, GLsizei height) {
5469 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5470 if (!renderbuffer) {
5471 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5472 "glRenderbufferStorageMultisampleEXT",
5473 "no renderbuffer bound");
5474 return;
5477 if (!ValidateRenderbufferStorageMultisample(
5478 samples, internalformat, width, height)) {
5479 return;
5482 EnsureRenderbufferBound();
5483 GLenum impl_format =
5484 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5485 internalformat);
5486 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5487 if (features().use_img_for_multisampled_render_to_texture) {
5488 glRenderbufferStorageMultisampleIMG(
5489 target, samples, impl_format, width, height);
5490 } else {
5491 glRenderbufferStorageMultisampleEXT(
5492 target, samples, impl_format, width, height);
5494 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5495 if (error == GL_NO_ERROR) {
5496 // TODO(gman): If renderbuffers tracked which framebuffers they were
5497 // attached to we could just mark those framebuffers as not complete.
5498 framebuffer_manager()->IncFramebufferStateChangeCount();
5499 renderbuffer_manager()->SetInfo(
5500 renderbuffer, samples, internalformat, width, height);
5504 // This function validates the allocation of a multisampled renderbuffer
5505 // by clearing it to a key color, blitting the contents to a texture, and
5506 // reading back the color to ensure it matches the key.
5507 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5508 GLuint renderbuffer, GLenum format) {
5510 // Only validate color buffers.
5511 // These formats have been selected because they are very common or are known
5512 // to be used by the WebGL backbuffer. If problems are observed with other
5513 // color formats they can be added here.
5514 switch(format) {
5515 case GL_RGB:
5516 case GL_RGB8:
5517 case GL_RGBA:
5518 case GL_RGBA8:
5519 break;
5520 default:
5521 return true;
5524 GLint draw_framebuffer, read_framebuffer;
5526 // Cache framebuffer and texture bindings.
5527 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5528 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5530 if (!validation_texture_) {
5531 GLint bound_texture;
5532 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5534 // Create additional resources needed for the verification.
5535 glGenTextures(1, &validation_texture_);
5536 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5537 glGenFramebuffersEXT(1, &validation_fbo_);
5539 // Texture only needs to be 1x1.
5540 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5541 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5542 GL_UNSIGNED_BYTE, NULL);
5544 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5545 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5546 GL_TEXTURE_2D, validation_texture_, 0);
5548 glBindTexture(GL_TEXTURE_2D, bound_texture);
5551 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5552 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5553 GL_RENDERBUFFER, renderbuffer);
5555 // Cache current state and reset it to the values we require.
5556 GLboolean scissor_enabled = false;
5557 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5558 if (scissor_enabled)
5559 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5561 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5562 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5563 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5565 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5566 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5567 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5569 // Clear the buffer to the desired key color.
5570 glClear(GL_COLOR_BUFFER_BIT);
5572 // Blit from the multisample buffer to a standard texture.
5573 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5574 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5576 BlitFramebufferHelper(
5577 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5579 // Read a pixel from the buffer.
5580 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5582 unsigned char pixel[3] = {0, 0, 0};
5583 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5585 // Detach the renderbuffer.
5586 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5587 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5588 GL_RENDERBUFFER, 0);
5590 // Restore cached state.
5591 if (scissor_enabled)
5592 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5594 state_.SetDeviceColorMask(
5595 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5596 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5597 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5598 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5600 // Return true if the pixel matched the desired key color.
5601 return (pixel[0] == 0xFF &&
5602 pixel[1] == 0x00 &&
5603 pixel[2] == 0xFF);
5606 void GLES2DecoderImpl::DoRenderbufferStorage(
5607 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5608 Renderbuffer* renderbuffer =
5609 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5610 if (!renderbuffer) {
5611 LOCAL_SET_GL_ERROR(
5612 GL_INVALID_OPERATION,
5613 "glRenderbufferStorage", "no renderbuffer bound");
5614 return;
5617 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5618 height > renderbuffer_manager()->max_renderbuffer_size()) {
5619 LOCAL_SET_GL_ERROR(
5620 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5621 return;
5624 uint32 estimated_size = 0;
5625 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5626 width, height, 1, internalformat, &estimated_size)) {
5627 LOCAL_SET_GL_ERROR(
5628 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5629 return;
5632 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5633 LOCAL_SET_GL_ERROR(
5634 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5635 return;
5638 EnsureRenderbufferBound();
5639 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5640 glRenderbufferStorageEXT(
5641 target,
5642 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5643 internalformat),
5644 width,
5645 height);
5646 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5647 if (error == GL_NO_ERROR) {
5648 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5649 // we could just mark those framebuffers as not complete.
5650 framebuffer_manager()->IncFramebufferStateChangeCount();
5651 renderbuffer_manager()->SetInfo(
5652 renderbuffer, 1, internalformat, width, height);
5656 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5657 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5658 Program* program = GetProgramInfoNotShader(
5659 program_id, "glLinkProgram");
5660 if (!program) {
5661 return;
5664 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5665 ShaderTranslator* vertex_translator = NULL;
5666 ShaderTranslator* fragment_translator = NULL;
5667 if (use_shader_translator_) {
5668 vertex_translator = vertex_translator_.get();
5669 fragment_translator = fragment_translator_.get();
5671 if (program->Link(shader_manager(),
5672 vertex_translator,
5673 fragment_translator,
5674 workarounds().count_all_in_varyings_packing ?
5675 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5676 shader_cache_callback_)) {
5677 if (program == state_.current_program.get()) {
5678 if (workarounds().use_current_program_after_successful_link)
5679 glUseProgram(program->service_id());
5680 if (workarounds().clear_uniforms_before_first_program_use)
5681 program_manager()->ClearUniforms(program);
5686 void GLES2DecoderImpl::DoTexParameterf(
5687 GLenum target, GLenum pname, GLfloat param) {
5688 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5689 &state_, target);
5690 if (!texture) {
5691 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5692 return;
5695 texture_manager()->SetParameterf(
5696 "glTexParameterf", GetErrorState(), texture, pname, param);
5699 void GLES2DecoderImpl::DoTexParameteri(
5700 GLenum target, GLenum pname, GLint param) {
5701 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5702 &state_, target);
5703 if (!texture) {
5704 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5705 return;
5708 texture_manager()->SetParameteri(
5709 "glTexParameteri", GetErrorState(), texture, pname, param);
5712 void GLES2DecoderImpl::DoTexParameterfv(
5713 GLenum target, GLenum pname, const GLfloat* params) {
5714 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5715 &state_, target);
5716 if (!texture) {
5717 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5718 return;
5721 texture_manager()->SetParameterf(
5722 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5725 void GLES2DecoderImpl::DoTexParameteriv(
5726 GLenum target, GLenum pname, const GLint* params) {
5727 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5728 &state_, target);
5729 if (!texture) {
5730 LOCAL_SET_GL_ERROR(
5731 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5732 return;
5735 texture_manager()->SetParameteri(
5736 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5739 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5740 if (!state_.current_program.get()) {
5741 // The program does not exist.
5742 LOCAL_SET_GL_ERROR(
5743 GL_INVALID_OPERATION, function_name, "no program in use");
5744 return false;
5746 if (!state_.current_program->InUse()) {
5747 LOCAL_SET_GL_ERROR(
5748 GL_INVALID_OPERATION, function_name, "program not linked");
5749 return false;
5751 return true;
5754 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5755 GLint location, const char* function_name) {
5756 if (!CheckCurrentProgram(function_name)) {
5757 return false;
5759 return location != -1;
5762 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5763 GLint fake_location,
5764 const char* function_name,
5765 Program::UniformApiType api_type,
5766 GLint* real_location,
5767 GLenum* type,
5768 GLsizei* count) {
5769 DCHECK(type);
5770 DCHECK(count);
5771 DCHECK(real_location);
5773 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5774 return false;
5776 GLint array_index = -1;
5777 const Program::UniformInfo* info =
5778 state_.current_program->GetUniformInfoByFakeLocation(
5779 fake_location, real_location, &array_index);
5780 if (!info) {
5781 LOCAL_SET_GL_ERROR(
5782 GL_INVALID_OPERATION, function_name, "unknown location");
5783 return false;
5786 if ((api_type & info->accepts_api_type) == 0) {
5787 LOCAL_SET_GL_ERROR(
5788 GL_INVALID_OPERATION, function_name,
5789 "wrong uniform function for type");
5790 return false;
5792 if (*count > 1 && !info->is_array) {
5793 LOCAL_SET_GL_ERROR(
5794 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5795 return false;
5797 *count = std::min(info->size - array_index, *count);
5798 if (*count <= 0) {
5799 return false;
5801 *type = info->type;
5802 return true;
5805 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5806 GLenum type = 0;
5807 GLsizei count = 1;
5808 GLint real_location = -1;
5809 if (!PrepForSetUniformByLocation(fake_location,
5810 "glUniform1i",
5811 Program::kUniform1i,
5812 &real_location,
5813 &type,
5814 &count)) {
5815 return;
5817 if (!state_.current_program->SetSamplers(
5818 state_.texture_units.size(), fake_location, 1, &v0)) {
5819 LOCAL_SET_GL_ERROR(
5820 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5821 return;
5823 glUniform1i(real_location, v0);
5826 void GLES2DecoderImpl::DoUniform1iv(
5827 GLint fake_location, GLsizei count, const GLint *value) {
5828 GLenum type = 0;
5829 GLint real_location = -1;
5830 if (!PrepForSetUniformByLocation(fake_location,
5831 "glUniform1iv",
5832 Program::kUniform1i,
5833 &real_location,
5834 &type,
5835 &count)) {
5836 return;
5838 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5839 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5840 if (!state_.current_program->SetSamplers(
5841 state_.texture_units.size(), fake_location, count, value)) {
5842 LOCAL_SET_GL_ERROR(
5843 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5844 return;
5847 glUniform1iv(real_location, count, value);
5850 void GLES2DecoderImpl::DoUniform1fv(
5851 GLint fake_location, GLsizei count, const GLfloat* value) {
5852 GLenum type = 0;
5853 GLint real_location = -1;
5854 if (!PrepForSetUniformByLocation(fake_location,
5855 "glUniform1fv",
5856 Program::kUniform1f,
5857 &real_location,
5858 &type,
5859 &count)) {
5860 return;
5862 if (type == GL_BOOL) {
5863 scoped_ptr<GLint[]> temp(new GLint[count]);
5864 for (GLsizei ii = 0; ii < count; ++ii) {
5865 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5867 DoUniform1iv(real_location, count, temp.get());
5868 } else {
5869 glUniform1fv(real_location, count, value);
5873 void GLES2DecoderImpl::DoUniform2fv(
5874 GLint fake_location, GLsizei count, const GLfloat* value) {
5875 GLenum type = 0;
5876 GLint real_location = -1;
5877 if (!PrepForSetUniformByLocation(fake_location,
5878 "glUniform2fv",
5879 Program::kUniform2f,
5880 &real_location,
5881 &type,
5882 &count)) {
5883 return;
5885 if (type == GL_BOOL_VEC2) {
5886 GLsizei num_values = count * 2;
5887 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5888 for (GLsizei ii = 0; ii < num_values; ++ii) {
5889 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5891 glUniform2iv(real_location, count, temp.get());
5892 } else {
5893 glUniform2fv(real_location, count, value);
5897 void GLES2DecoderImpl::DoUniform3fv(
5898 GLint fake_location, GLsizei count, const GLfloat* value) {
5899 GLenum type = 0;
5900 GLint real_location = -1;
5901 if (!PrepForSetUniformByLocation(fake_location,
5902 "glUniform3fv",
5903 Program::kUniform3f,
5904 &real_location,
5905 &type,
5906 &count)) {
5907 return;
5909 if (type == GL_BOOL_VEC3) {
5910 GLsizei num_values = count * 3;
5911 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5912 for (GLsizei ii = 0; ii < num_values; ++ii) {
5913 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5915 glUniform3iv(real_location, count, temp.get());
5916 } else {
5917 glUniform3fv(real_location, count, value);
5921 void GLES2DecoderImpl::DoUniform4fv(
5922 GLint fake_location, GLsizei count, const GLfloat* value) {
5923 GLenum type = 0;
5924 GLint real_location = -1;
5925 if (!PrepForSetUniformByLocation(fake_location,
5926 "glUniform4fv",
5927 Program::kUniform4f,
5928 &real_location,
5929 &type,
5930 &count)) {
5931 return;
5933 if (type == GL_BOOL_VEC4) {
5934 GLsizei num_values = count * 4;
5935 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5936 for (GLsizei ii = 0; ii < num_values; ++ii) {
5937 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5939 glUniform4iv(real_location, count, temp.get());
5940 } else {
5941 glUniform4fv(real_location, count, value);
5945 void GLES2DecoderImpl::DoUniform2iv(
5946 GLint fake_location, GLsizei count, const GLint* value) {
5947 GLenum type = 0;
5948 GLint real_location = -1;
5949 if (!PrepForSetUniformByLocation(fake_location,
5950 "glUniform2iv",
5951 Program::kUniform2i,
5952 &real_location,
5953 &type,
5954 &count)) {
5955 return;
5957 glUniform2iv(real_location, count, value);
5960 void GLES2DecoderImpl::DoUniform3iv(
5961 GLint fake_location, GLsizei count, const GLint* value) {
5962 GLenum type = 0;
5963 GLint real_location = -1;
5964 if (!PrepForSetUniformByLocation(fake_location,
5965 "glUniform3iv",
5966 Program::kUniform3i,
5967 &real_location,
5968 &type,
5969 &count)) {
5970 return;
5972 glUniform3iv(real_location, count, value);
5975 void GLES2DecoderImpl::DoUniform4iv(
5976 GLint fake_location, GLsizei count, const GLint* value) {
5977 GLenum type = 0;
5978 GLint real_location = -1;
5979 if (!PrepForSetUniformByLocation(fake_location,
5980 "glUniform4iv",
5981 Program::kUniform4i,
5982 &real_location,
5983 &type,
5984 &count)) {
5985 return;
5987 glUniform4iv(real_location, count, value);
5990 void GLES2DecoderImpl::DoUniformMatrix2fv(
5991 GLint fake_location, GLsizei count, GLboolean transpose,
5992 const GLfloat* value) {
5993 GLenum type = 0;
5994 GLint real_location = -1;
5995 if (!PrepForSetUniformByLocation(fake_location,
5996 "glUniformMatrix2fv",
5997 Program::kUniformMatrix2f,
5998 &real_location,
5999 &type,
6000 &count)) {
6001 return;
6003 glUniformMatrix2fv(real_location, count, transpose, value);
6006 void GLES2DecoderImpl::DoUniformMatrix3fv(
6007 GLint fake_location, GLsizei count, GLboolean transpose,
6008 const GLfloat* value) {
6009 GLenum type = 0;
6010 GLint real_location = -1;
6011 if (!PrepForSetUniformByLocation(fake_location,
6012 "glUniformMatrix3fv",
6013 Program::kUniformMatrix3f,
6014 &real_location,
6015 &type,
6016 &count)) {
6017 return;
6019 glUniformMatrix3fv(real_location, count, transpose, value);
6022 void GLES2DecoderImpl::DoUniformMatrix4fv(
6023 GLint fake_location, GLsizei count, GLboolean transpose,
6024 const GLfloat* value) {
6025 GLenum type = 0;
6026 GLint real_location = -1;
6027 if (!PrepForSetUniformByLocation(fake_location,
6028 "glUniformMatrix4fv",
6029 Program::kUniformMatrix4f,
6030 &real_location,
6031 &type,
6032 &count)) {
6033 return;
6035 glUniformMatrix4fv(real_location, count, transpose, value);
6038 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6039 GLuint service_id = 0;
6040 Program* program = NULL;
6041 if (program_id) {
6042 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6043 if (!program) {
6044 return;
6046 if (!program->IsValid()) {
6047 // Program was not linked successfully. (ie, glLinkProgram)
6048 LOCAL_SET_GL_ERROR(
6049 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6050 return;
6052 service_id = program->service_id();
6054 if (state_.current_program.get()) {
6055 program_manager()->UnuseProgram(shader_manager(),
6056 state_.current_program.get());
6058 state_.current_program = program;
6059 LogClientServiceMapping("glUseProgram", program_id, service_id);
6060 glUseProgram(service_id);
6061 if (state_.current_program.get()) {
6062 program_manager()->UseProgram(state_.current_program.get());
6063 if (workarounds().clear_uniforms_before_first_program_use)
6064 program_manager()->ClearUniforms(program);
6068 void GLES2DecoderImpl::RenderWarning(
6069 const char* filename, int line, const std::string& msg) {
6070 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6073 void GLES2DecoderImpl::PerformanceWarning(
6074 const char* filename, int line, const std::string& msg) {
6075 logger_.LogMessage(filename, line,
6076 std::string("PERFORMANCE WARNING: ") + msg);
6079 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6080 Texture* texture, GLenum textarget) {
6081 // Image is already in use if texture is attached to a framebuffer.
6082 if (texture && !texture->IsAttachedToFramebuffer()) {
6083 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6084 if (image) {
6085 ScopedGLErrorSuppressor suppressor(
6086 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6087 GetErrorState());
6088 glBindTexture(textarget, texture->service_id());
6089 image->WillUseTexImage();
6090 RestoreCurrentTextureBindings(&state_, textarget);
6095 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6096 Texture* texture, GLenum textarget) {
6097 // Image is still in use if texture is attached to a framebuffer.
6098 if (texture && !texture->IsAttachedToFramebuffer()) {
6099 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6100 if (image) {
6101 ScopedGLErrorSuppressor suppressor(
6102 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6103 GetErrorState());
6104 glBindTexture(textarget, texture->service_id());
6105 image->DidUseTexImage();
6106 RestoreCurrentTextureBindings(&state_, textarget);
6111 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6112 DCHECK(state_.current_program.get());
6113 if (!texture_manager()->HaveUnrenderableTextures() &&
6114 !texture_manager()->HaveImages()) {
6115 return true;
6118 bool textures_set = false;
6119 const Program::SamplerIndices& sampler_indices =
6120 state_.current_program->sampler_indices();
6121 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6122 const Program::UniformInfo* uniform_info =
6123 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6124 DCHECK(uniform_info);
6125 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6126 GLuint texture_unit_index = uniform_info->texture_units[jj];
6127 if (texture_unit_index < state_.texture_units.size()) {
6128 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6129 TextureRef* texture_ref =
6130 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6131 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6132 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6133 textures_set = true;
6134 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6135 glBindTexture(
6136 textarget,
6137 texture_manager()->black_texture_id(uniform_info->type));
6138 LOCAL_RENDER_WARNING(
6139 std::string("texture bound to texture unit ") +
6140 base::IntToString(texture_unit_index) +
6141 " is not renderable. It maybe non-power-of-2 and have"
6142 " incompatible texture filtering or is not"
6143 " 'texture complete'");
6144 continue;
6147 if (textarget != GL_TEXTURE_CUBE_MAP) {
6148 Texture* texture = texture_ref->texture();
6149 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6150 if (image && !texture->IsAttachedToFramebuffer()) {
6151 ScopedGLErrorSuppressor suppressor(
6152 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6153 textures_set = true;
6154 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6155 image->WillUseTexImage();
6156 continue;
6160 // else: should this be an error?
6163 return !textures_set;
6166 void GLES2DecoderImpl::RestoreStateForTextures() {
6167 DCHECK(state_.current_program.get());
6168 const Program::SamplerIndices& sampler_indices =
6169 state_.current_program->sampler_indices();
6170 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6171 const Program::UniformInfo* uniform_info =
6172 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6173 DCHECK(uniform_info);
6174 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6175 GLuint texture_unit_index = uniform_info->texture_units[jj];
6176 if (texture_unit_index < state_.texture_units.size()) {
6177 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6178 TextureRef* texture_ref =
6179 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6180 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6181 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6182 // Get the texture_ref info that was previously bound here.
6183 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6184 ? texture_unit.bound_texture_2d.get()
6185 : texture_unit.bound_texture_cube_map.get();
6186 glBindTexture(texture_unit.bind_target,
6187 texture_ref ? texture_ref->service_id() : 0);
6188 continue;
6191 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6192 Texture* texture = texture_ref->texture();
6193 gfx::GLImage* image =
6194 texture->GetLevelImage(texture_unit.bind_target, 0);
6195 if (image && !texture->IsAttachedToFramebuffer()) {
6196 ScopedGLErrorSuppressor suppressor(
6197 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6198 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6199 image->DidUseTexImage();
6200 continue;
6206 // Set the active texture back to whatever the user had it as.
6207 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6210 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6211 // Only check if there are some uncleared textures.
6212 if (!texture_manager()->HaveUnsafeTextures()) {
6213 return true;
6216 // 1: Check all textures we are about to render with.
6217 if (state_.current_program.get()) {
6218 const Program::SamplerIndices& sampler_indices =
6219 state_.current_program->sampler_indices();
6220 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6221 const Program::UniformInfo* uniform_info =
6222 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6223 DCHECK(uniform_info);
6224 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6225 GLuint texture_unit_index = uniform_info->texture_units[jj];
6226 if (texture_unit_index < state_.texture_units.size()) {
6227 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6228 TextureRef* texture_ref =
6229 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6230 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6231 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6232 return false;
6239 return true;
6242 bool GLES2DecoderImpl::IsDrawValid(
6243 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6244 GLsizei primcount) {
6245 DCHECK(instanced || primcount == 1);
6247 // NOTE: We specifically do not check current_program->IsValid() because
6248 // it could never be invalid since glUseProgram would have failed. While
6249 // glLinkProgram could later mark the program as invalid the previous
6250 // valid program will still function if it is still the current program.
6251 if (!state_.current_program.get()) {
6252 // The program does not exist.
6253 // But GL says no ERROR.
6254 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6255 return false;
6258 return state_.vertex_attrib_manager
6259 ->ValidateBindings(function_name,
6260 this,
6261 feature_info_.get(),
6262 state_.current_program.get(),
6263 max_vertex_accessed,
6264 instanced,
6265 primcount);
6268 bool GLES2DecoderImpl::SimulateAttrib0(
6269 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6270 DCHECK(simulated);
6271 *simulated = false;
6273 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6274 return true;
6276 const VertexAttrib* attrib =
6277 state_.vertex_attrib_manager->GetVertexAttrib(0);
6278 // If it's enabled or it's not used then we don't need to do anything.
6279 bool attrib_0_used =
6280 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6281 if (attrib->enabled() && attrib_0_used) {
6282 return true;
6285 // Make a buffer with a single repeated vec4 value enough to
6286 // simulate the constant value that is supposed to be here.
6287 // This is required to emulate GLES2 on GL.
6288 GLuint num_vertices = max_vertex_accessed + 1;
6289 uint32 size_needed = 0;
6291 if (num_vertices == 0 ||
6292 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6293 size_needed > 0x7FFFFFFFU) {
6294 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6295 return false;
6298 LOCAL_PERFORMANCE_WARNING(
6299 "Attribute 0 is disabled. This has signficant performance penalty");
6301 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6302 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6304 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6305 if (new_buffer) {
6306 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6307 GLenum error = glGetError();
6308 if (error != GL_NO_ERROR) {
6309 LOCAL_SET_GL_ERROR(
6310 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6311 return false;
6315 const Vec4& value = state_.attrib_values[0];
6316 if (new_buffer ||
6317 (attrib_0_used &&
6318 (!attrib_0_buffer_matches_value_ ||
6319 (value.v[0] != attrib_0_value_.v[0] ||
6320 value.v[1] != attrib_0_value_.v[1] ||
6321 value.v[2] != attrib_0_value_.v[2] ||
6322 value.v[3] != attrib_0_value_.v[3])))) {
6323 std::vector<Vec4> temp(num_vertices, value);
6324 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6325 attrib_0_buffer_matches_value_ = true;
6326 attrib_0_value_ = value;
6327 attrib_0_size_ = size_needed;
6330 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6332 if (attrib->divisor())
6333 glVertexAttribDivisorANGLE(0, 0);
6335 *simulated = true;
6336 return true;
6339 void GLES2DecoderImpl::RestoreStateForAttrib(
6340 GLuint attrib_index, bool restore_array_binding) {
6341 const VertexAttrib* attrib =
6342 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6343 if (restore_array_binding) {
6344 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6345 Buffer* buffer = attrib->buffer();
6346 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6347 glVertexAttribPointer(
6348 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6349 attrib->gl_stride(), ptr);
6351 if (attrib->divisor())
6352 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6353 glBindBuffer(
6354 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6355 state_.bound_array_buffer->service_id() : 0);
6357 // Never touch vertex attribute 0's state (in particular, never
6358 // disable it) when running on desktop GL because it will never be
6359 // re-enabled.
6360 if (attrib_index != 0 ||
6361 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6362 if (attrib->enabled()) {
6363 glEnableVertexAttribArray(attrib_index);
6364 } else {
6365 glDisableVertexAttribArray(attrib_index);
6370 bool GLES2DecoderImpl::SimulateFixedAttribs(
6371 const char* function_name,
6372 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6373 DCHECK(simulated);
6374 *simulated = false;
6375 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6376 return true;
6378 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6379 return true;
6382 LOCAL_PERFORMANCE_WARNING(
6383 "GL_FIXED attributes have a signficant performance penalty");
6385 // NOTE: we could be smart and try to check if a buffer is used
6386 // twice in 2 different attribs, find the overlapping parts and therefore
6387 // duplicate the minimum amount of data but this whole code path is not meant
6388 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6389 // tests so we just add to the buffer attrib used.
6391 GLuint elements_needed = 0;
6392 const VertexAttribManager::VertexAttribList& enabled_attribs =
6393 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6394 for (VertexAttribManager::VertexAttribList::const_iterator it =
6395 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6396 const VertexAttrib* attrib = *it;
6397 const Program::VertexAttrib* attrib_info =
6398 state_.current_program->GetAttribInfoByLocation(attrib->index());
6399 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6400 max_vertex_accessed);
6401 GLuint num_vertices = max_accessed + 1;
6402 if (num_vertices == 0) {
6403 LOCAL_SET_GL_ERROR(
6404 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6405 return false;
6407 if (attrib_info &&
6408 attrib->CanAccess(max_accessed) &&
6409 attrib->type() == GL_FIXED) {
6410 uint32 elements_used = 0;
6411 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6412 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6413 LOCAL_SET_GL_ERROR(
6414 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6415 return false;
6420 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6421 uint32 size_needed = 0;
6422 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6423 size_needed > 0x7FFFFFFFU) {
6424 LOCAL_SET_GL_ERROR(
6425 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6426 return false;
6429 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6431 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6432 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6433 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6434 GLenum error = glGetError();
6435 if (error != GL_NO_ERROR) {
6436 LOCAL_SET_GL_ERROR(
6437 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6438 return false;
6442 // Copy the elements and convert to float
6443 GLintptr offset = 0;
6444 for (VertexAttribManager::VertexAttribList::const_iterator it =
6445 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6446 const VertexAttrib* attrib = *it;
6447 const Program::VertexAttrib* attrib_info =
6448 state_.current_program->GetAttribInfoByLocation(attrib->index());
6449 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6450 max_vertex_accessed);
6451 GLuint num_vertices = max_accessed + 1;
6452 if (num_vertices == 0) {
6453 LOCAL_SET_GL_ERROR(
6454 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6455 return false;
6457 if (attrib_info &&
6458 attrib->CanAccess(max_accessed) &&
6459 attrib->type() == GL_FIXED) {
6460 int num_elements = attrib->size() * kSizeOfFloat;
6461 int size = num_elements * num_vertices;
6462 scoped_ptr<float[]> data(new float[size]);
6463 const int32* src = reinterpret_cast<const int32 *>(
6464 attrib->buffer()->GetRange(attrib->offset(), size));
6465 const int32* end = src + num_elements;
6466 float* dst = data.get();
6467 while (src != end) {
6468 *dst++ = static_cast<float>(*src++) / 65536.0f;
6470 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6471 glVertexAttribPointer(
6472 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6473 reinterpret_cast<GLvoid*>(offset));
6474 offset += size;
6477 *simulated = true;
6478 return true;
6481 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6482 // There's no need to call glVertexAttribPointer because we shadow all the
6483 // settings and passing GL_FIXED to it will not work.
6484 glBindBuffer(
6485 GL_ARRAY_BUFFER,
6486 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6487 : 0);
6490 error::Error GLES2DecoderImpl::DoDrawArrays(
6491 const char* function_name,
6492 bool instanced,
6493 GLenum mode,
6494 GLint first,
6495 GLsizei count,
6496 GLsizei primcount) {
6497 error::Error error = WillAccessBoundFramebufferForDraw();
6498 if (error != error::kNoError)
6499 return error;
6500 if (!validators_->draw_mode.IsValid(mode)) {
6501 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6502 return error::kNoError;
6504 if (count < 0) {
6505 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6506 return error::kNoError;
6508 if (primcount < 0) {
6509 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6510 return error::kNoError;
6512 if (!CheckBoundFramebuffersValid(function_name)) {
6513 return error::kNoError;
6515 // We have to check this here because the prototype for glDrawArrays
6516 // is GLint not GLsizei.
6517 if (first < 0) {
6518 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6519 return error::kNoError;
6522 if (count == 0 || primcount == 0) {
6523 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6524 return error::kNoError;
6527 GLuint max_vertex_accessed = first + count - 1;
6528 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6529 if (!ClearUnclearedTextures()) {
6530 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6531 return error::kNoError;
6533 bool simulated_attrib_0 = false;
6534 if (!SimulateAttrib0(
6535 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6536 return error::kNoError;
6538 bool simulated_fixed_attribs = false;
6539 if (SimulateFixedAttribs(
6540 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6541 primcount)) {
6542 bool textures_set = !PrepareTexturesForRender();
6543 ApplyDirtyState();
6544 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6545 if (!instanced) {
6546 glDrawArrays(mode, first, count);
6547 } else {
6548 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6550 if (textures_set) {
6551 RestoreStateForTextures();
6553 if (simulated_fixed_attribs) {
6554 RestoreStateForSimulatedFixedAttribs();
6557 if (simulated_attrib_0) {
6558 // We don't have to restore attrib 0 generic data at the end of this
6559 // function even if it is simulated. This is because we will simulate
6560 // it in each draw call, and attrib 0 generic data queries use cached
6561 // values instead of passing down to the underlying driver.
6562 RestoreStateForAttrib(0, false);
6565 return error::kNoError;
6568 error::Error GLES2DecoderImpl::HandleDrawArrays(
6569 uint32 immediate_data_size, const cmds::DrawArrays& c) {
6570 return DoDrawArrays("glDrawArrays",
6571 false,
6572 static_cast<GLenum>(c.mode),
6573 static_cast<GLint>(c.first),
6574 static_cast<GLsizei>(c.count),
6578 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6579 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
6580 if (!features().angle_instanced_arrays) {
6581 LOCAL_SET_GL_ERROR(
6582 GL_INVALID_OPERATION,
6583 "glDrawArraysInstancedANGLE", "function not available");
6584 return error::kNoError;
6586 return DoDrawArrays("glDrawArraysIntancedANGLE",
6587 true,
6588 static_cast<GLenum>(c.mode),
6589 static_cast<GLint>(c.first),
6590 static_cast<GLsizei>(c.count),
6591 static_cast<GLsizei>(c.primcount));
6594 error::Error GLES2DecoderImpl::DoDrawElements(
6595 const char* function_name,
6596 bool instanced,
6597 GLenum mode,
6598 GLsizei count,
6599 GLenum type,
6600 int32 offset,
6601 GLsizei primcount) {
6602 error::Error error = WillAccessBoundFramebufferForDraw();
6603 if (error != error::kNoError)
6604 return error;
6605 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6606 LOCAL_SET_GL_ERROR(
6607 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6608 return error::kNoError;
6611 if (count < 0) {
6612 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6613 return error::kNoError;
6615 if (offset < 0) {
6616 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6617 return error::kNoError;
6619 if (!validators_->draw_mode.IsValid(mode)) {
6620 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6621 return error::kNoError;
6623 if (!validators_->index_type.IsValid(type)) {
6624 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6625 return error::kNoError;
6627 if (primcount < 0) {
6628 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6629 return error::kNoError;
6632 if (!CheckBoundFramebuffersValid(function_name)) {
6633 return error::kNoError;
6636 if (count == 0 || primcount == 0) {
6637 return error::kNoError;
6640 GLuint max_vertex_accessed;
6641 Buffer* element_array_buffer =
6642 state_.vertex_attrib_manager->element_array_buffer();
6644 if (!element_array_buffer->GetMaxValueForRange(
6645 offset, count, type, &max_vertex_accessed)) {
6646 LOCAL_SET_GL_ERROR(
6647 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6648 return error::kNoError;
6651 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6652 if (!ClearUnclearedTextures()) {
6653 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6654 return error::kNoError;
6656 bool simulated_attrib_0 = false;
6657 if (!SimulateAttrib0(
6658 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6659 return error::kNoError;
6661 bool simulated_fixed_attribs = false;
6662 if (SimulateFixedAttribs(
6663 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6664 primcount)) {
6665 bool textures_set = !PrepareTexturesForRender();
6666 ApplyDirtyState();
6667 // TODO(gman): Refactor to hide these details in BufferManager or
6668 // VertexAttribManager.
6669 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6670 bool used_client_side_array = false;
6671 if (element_array_buffer->IsClientSideArray()) {
6672 used_client_side_array = true;
6673 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6674 indices = element_array_buffer->GetRange(offset, 0);
6677 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6678 if (!instanced) {
6679 glDrawElements(mode, count, type, indices);
6680 } else {
6681 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6684 if (used_client_side_array) {
6685 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6686 element_array_buffer->service_id());
6689 if (textures_set) {
6690 RestoreStateForTextures();
6692 if (simulated_fixed_attribs) {
6693 RestoreStateForSimulatedFixedAttribs();
6696 if (simulated_attrib_0) {
6697 // We don't have to restore attrib 0 generic data at the end of this
6698 // function even if it is simulated. This is because we will simulate
6699 // it in each draw call, and attrib 0 generic data queries use cached
6700 // values instead of passing down to the underlying driver.
6701 RestoreStateForAttrib(0, false);
6704 return error::kNoError;
6707 error::Error GLES2DecoderImpl::HandleDrawElements(
6708 uint32 immediate_data_size, const cmds::DrawElements& c) {
6709 return DoDrawElements("glDrawElements",
6710 false,
6711 static_cast<GLenum>(c.mode),
6712 static_cast<GLsizei>(c.count),
6713 static_cast<GLenum>(c.type),
6714 static_cast<int32>(c.index_offset),
6718 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6719 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
6720 if (!features().angle_instanced_arrays) {
6721 LOCAL_SET_GL_ERROR(
6722 GL_INVALID_OPERATION,
6723 "glDrawElementsInstancedANGLE", "function not available");
6724 return error::kNoError;
6726 return DoDrawElements("glDrawElementsInstancedANGLE",
6727 true,
6728 static_cast<GLenum>(c.mode),
6729 static_cast<GLsizei>(c.count),
6730 static_cast<GLenum>(c.type),
6731 static_cast<int32>(c.index_offset),
6732 static_cast<GLsizei>(c.primcount));
6735 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6736 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6737 GLuint max_vertex_accessed = 0;
6738 Buffer* buffer = GetBuffer(buffer_id);
6739 if (!buffer) {
6740 // TODO(gman): Should this be a GL error or a command buffer error?
6741 LOCAL_SET_GL_ERROR(
6742 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6743 } else {
6744 if (!buffer->GetMaxValueForRange(
6745 offset, count, type, &max_vertex_accessed)) {
6746 // TODO(gman): Should this be a GL error or a command buffer error?
6747 LOCAL_SET_GL_ERROR(
6748 GL_INVALID_OPERATION,
6749 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6752 return max_vertex_accessed;
6755 // Calls glShaderSource for the various versions of the ShaderSource command.
6756 // Assumes that data / data_size points to a piece of memory that is in range
6757 // of whatever context it came from (shared memory, immediate memory, bucket
6758 // memory.)
6759 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6760 GLuint client_id, const char* data, uint32 data_size) {
6761 std::string str(data, data + data_size);
6762 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6763 if (!shader) {
6764 return error::kNoError;
6766 // Note: We don't actually call glShaderSource here. We wait until
6767 // the call to glCompileShader.
6768 shader->UpdateSource(str.c_str());
6769 return error::kNoError;
6772 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6773 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
6774 Bucket* bucket = GetBucket(c.data_bucket_id);
6775 if (!bucket || bucket->size() == 0) {
6776 return error::kInvalidArguments;
6778 return ShaderSourceHelper(
6779 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6780 bucket->size() - 1);
6783 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6784 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6785 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6786 if (!shader) {
6787 return;
6789 ShaderTranslator* translator = NULL;
6790 if (use_shader_translator_) {
6791 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6792 vertex_translator_.get() : fragment_translator_.get();
6795 program_manager()->DoCompileShader(
6796 shader,
6797 translator,
6798 feature_info_->feature_flags().angle_translated_shader_source ?
6799 ProgramManager::kANGLE : ProgramManager::kGL);
6802 void GLES2DecoderImpl::DoGetShaderiv(
6803 GLuint shader_id, GLenum pname, GLint* params) {
6804 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6805 if (!shader) {
6806 return;
6808 switch (pname) {
6809 case GL_SHADER_SOURCE_LENGTH:
6810 *params = shader->source() ? shader->source()->size() + 1 : 0;
6811 return;
6812 case GL_COMPILE_STATUS:
6813 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
6814 return;
6815 case GL_INFO_LOG_LENGTH:
6816 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
6817 return;
6818 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6819 *params = shader->translated_source() ?
6820 shader->translated_source()->size() + 1 : 0;
6821 return;
6822 default:
6823 break;
6825 glGetShaderiv(shader->service_id(), pname, params);
6828 error::Error GLES2DecoderImpl::HandleGetShaderSource(
6829 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
6830 GLuint shader_id = c.shader;
6831 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6832 Bucket* bucket = CreateBucket(bucket_id);
6833 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6834 if (!shader || !shader->source()) {
6835 bucket->SetSize(0);
6836 return error::kNoError;
6838 bucket->SetFromString(shader->source()->c_str());
6839 return error::kNoError;
6842 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6843 uint32 immediate_data_size,
6844 const cmds::GetTranslatedShaderSourceANGLE& c) {
6845 GLuint shader_id = c.shader;
6846 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6847 Bucket* bucket = CreateBucket(bucket_id);
6848 Shader* shader = GetShaderInfoNotProgram(
6849 shader_id, "glGetTranslatedShaderSourceANGLE");
6850 if (!shader) {
6851 bucket->SetSize(0);
6852 return error::kNoError;
6855 bucket->SetFromString(shader->translated_source() ?
6856 shader->translated_source()->c_str() : NULL);
6857 return error::kNoError;
6860 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6861 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
6862 GLuint program_id = c.program;
6863 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6864 Bucket* bucket = CreateBucket(bucket_id);
6865 Program* program = GetProgramInfoNotShader(
6866 program_id, "glGetProgramInfoLog");
6867 if (!program || !program->log_info()) {
6868 bucket->SetFromString("");
6869 return error::kNoError;
6871 bucket->SetFromString(program->log_info()->c_str());
6872 return error::kNoError;
6875 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
6876 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
6877 GLuint shader_id = c.shader;
6878 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6879 Bucket* bucket = CreateBucket(bucket_id);
6880 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6881 if (!shader || !shader->log_info()) {
6882 bucket->SetFromString("");
6883 return error::kNoError;
6885 bucket->SetFromString(shader->log_info()->c_str());
6886 return error::kNoError;
6889 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6890 return state_.GetEnabled(cap);
6893 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
6894 const Buffer* buffer = GetBuffer(client_id);
6895 return buffer && buffer->IsValid() && !buffer->IsDeleted();
6898 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
6899 const Framebuffer* framebuffer =
6900 GetFramebuffer(client_id);
6901 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
6904 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
6905 // IsProgram is true for programs as soon as they are created, until they are
6906 // deleted and no longer in use.
6907 const Program* program = GetProgram(client_id);
6908 return program != NULL && !program->IsDeleted();
6911 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
6912 const Renderbuffer* renderbuffer =
6913 GetRenderbuffer(client_id);
6914 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
6917 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
6918 // IsShader is true for shaders as soon as they are created, until they
6919 // are deleted and not attached to any programs.
6920 const Shader* shader = GetShader(client_id);
6921 return shader != NULL && !shader->IsDeleted();
6924 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
6925 const TextureRef* texture_ref = GetTexture(client_id);
6926 return texture_ref && texture_ref->texture()->IsValid();
6929 void GLES2DecoderImpl::DoAttachShader(
6930 GLuint program_client_id, GLint shader_client_id) {
6931 Program* program = GetProgramInfoNotShader(
6932 program_client_id, "glAttachShader");
6933 if (!program) {
6934 return;
6936 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6937 if (!shader) {
6938 return;
6940 if (!program->AttachShader(shader_manager(), shader)) {
6941 LOCAL_SET_GL_ERROR(
6942 GL_INVALID_OPERATION,
6943 "glAttachShader",
6944 "can not attach more than one shader of the same type.");
6945 return;
6947 glAttachShader(program->service_id(), shader->service_id());
6950 void GLES2DecoderImpl::DoDetachShader(
6951 GLuint program_client_id, GLint shader_client_id) {
6952 Program* program = GetProgramInfoNotShader(
6953 program_client_id, "glDetachShader");
6954 if (!program) {
6955 return;
6957 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6958 if (!shader) {
6959 return;
6961 if (!program->DetachShader(shader_manager(), shader)) {
6962 LOCAL_SET_GL_ERROR(
6963 GL_INVALID_OPERATION,
6964 "glDetachShader", "shader not attached to program");
6965 return;
6967 glDetachShader(program->service_id(), shader->service_id());
6970 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
6971 Program* program = GetProgramInfoNotShader(
6972 program_client_id, "glValidateProgram");
6973 if (!program) {
6974 return;
6976 program->Validate();
6979 void GLES2DecoderImpl::GetVertexAttribHelper(
6980 const VertexAttrib* attrib, GLenum pname, GLint* params) {
6981 switch (pname) {
6982 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6983 Buffer* buffer = attrib->buffer();
6984 if (buffer && !buffer->IsDeleted()) {
6985 GLuint client_id;
6986 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6987 *params = client_id;
6989 break;
6991 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6992 *params = attrib->enabled();
6993 break;
6994 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6995 *params = attrib->size();
6996 break;
6997 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6998 *params = attrib->gl_stride();
6999 break;
7000 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7001 *params = attrib->type();
7002 break;
7003 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7004 *params = attrib->normalized();
7005 break;
7006 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
7007 *params = attrib->divisor();
7008 break;
7009 default:
7010 NOTREACHED();
7011 break;
7015 void GLES2DecoderImpl::DoGetTexParameterfv(
7016 GLenum target, GLenum pname, GLfloat* params) {
7017 InitTextureMaxAnisotropyIfNeeded(target, pname);
7018 glGetTexParameterfv(target, pname, params);
7021 void GLES2DecoderImpl::DoGetTexParameteriv(
7022 GLenum target, GLenum pname, GLint* params) {
7023 InitTextureMaxAnisotropyIfNeeded(target, pname);
7024 glGetTexParameteriv(target, pname, params);
7027 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7028 GLenum target, GLenum pname) {
7029 if (!workarounds().init_texture_max_anisotropy)
7030 return;
7031 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7032 !validators_->texture_parameter.IsValid(pname)) {
7033 return;
7036 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7037 &state_, target);
7038 if (!texture_ref) {
7039 LOCAL_SET_GL_ERROR(
7040 GL_INVALID_OPERATION,
7041 "glGetTexParamter{fi}v", "unknown texture for target");
7042 return;
7044 Texture* texture = texture_ref->texture();
7045 texture->InitTextureMaxAnisotropyIfNeeded(target);
7048 void GLES2DecoderImpl::DoGetVertexAttribfv(
7049 GLuint index, GLenum pname, GLfloat* params) {
7050 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7051 if (!attrib) {
7052 LOCAL_SET_GL_ERROR(
7053 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
7054 return;
7056 switch (pname) {
7057 case GL_CURRENT_VERTEX_ATTRIB: {
7058 const Vec4& value = state_.attrib_values[index];
7059 params[0] = value.v[0];
7060 params[1] = value.v[1];
7061 params[2] = value.v[2];
7062 params[3] = value.v[3];
7063 break;
7065 default: {
7066 GLint value = 0;
7067 GetVertexAttribHelper(attrib, pname, &value);
7068 *params = static_cast<GLfloat>(value);
7069 break;
7074 void GLES2DecoderImpl::DoGetVertexAttribiv(
7075 GLuint index, GLenum pname, GLint* params) {
7076 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7077 if (!attrib) {
7078 LOCAL_SET_GL_ERROR(
7079 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
7080 return;
7082 switch (pname) {
7083 case GL_CURRENT_VERTEX_ATTRIB: {
7084 const Vec4& value = state_.attrib_values[index];
7085 params[0] = static_cast<GLint>(value.v[0]);
7086 params[1] = static_cast<GLint>(value.v[1]);
7087 params[2] = static_cast<GLint>(value.v[2]);
7088 params[3] = static_cast<GLint>(value.v[3]);
7089 break;
7091 default:
7092 GetVertexAttribHelper(attrib, pname, params);
7093 break;
7097 bool GLES2DecoderImpl::SetVertexAttribValue(
7098 const char* function_name, GLuint index, const GLfloat* value) {
7099 if (index >= state_.attrib_values.size()) {
7100 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7101 return false;
7103 Vec4& v = state_.attrib_values[index];
7104 v.v[0] = value[0];
7105 v.v[1] = value[1];
7106 v.v[2] = value[2];
7107 v.v[3] = value[3];
7108 return true;
7111 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7112 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7113 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7114 glVertexAttrib1f(index, v0);
7118 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7119 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7120 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7121 glVertexAttrib2f(index, v0, v1);
7125 void GLES2DecoderImpl::DoVertexAttrib3f(
7126 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7127 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7128 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7129 glVertexAttrib3f(index, v0, v1, v2);
7133 void GLES2DecoderImpl::DoVertexAttrib4f(
7134 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7135 GLfloat v[4] = { v0, v1, v2, v3, };
7136 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7137 glVertexAttrib4f(index, v0, v1, v2, v3);
7141 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7142 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7143 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7144 glVertexAttrib1fv(index, v);
7148 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7149 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7150 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7151 glVertexAttrib2fv(index, v);
7155 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7156 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7157 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7158 glVertexAttrib3fv(index, v);
7162 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7163 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7164 glVertexAttrib4fv(index, v);
7168 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7169 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
7171 if (!state_.bound_array_buffer.get() ||
7172 state_.bound_array_buffer->IsDeleted()) {
7173 if (state_.vertex_attrib_manager.get() ==
7174 state_.default_vertex_attrib_manager.get()) {
7175 LOCAL_SET_GL_ERROR(
7176 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7177 return error::kNoError;
7178 } else if (c.offset != 0) {
7179 LOCAL_SET_GL_ERROR(
7180 GL_INVALID_VALUE,
7181 "glVertexAttribPointer", "client side arrays are not allowed");
7182 return error::kNoError;
7186 GLuint indx = c.indx;
7187 GLint size = c.size;
7188 GLenum type = c.type;
7189 GLboolean normalized = c.normalized;
7190 GLsizei stride = c.stride;
7191 GLsizei offset = c.offset;
7192 const void* ptr = reinterpret_cast<const void*>(offset);
7193 if (!validators_->vertex_attrib_type.IsValid(type)) {
7194 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7195 return error::kNoError;
7197 if (!validators_->vertex_attrib_size.IsValid(size)) {
7198 LOCAL_SET_GL_ERROR(
7199 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7200 return error::kNoError;
7202 if (indx >= group_->max_vertex_attribs()) {
7203 LOCAL_SET_GL_ERROR(
7204 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7205 return error::kNoError;
7207 if (stride < 0) {
7208 LOCAL_SET_GL_ERROR(
7209 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7210 return error::kNoError;
7212 if (stride > 255) {
7213 LOCAL_SET_GL_ERROR(
7214 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7215 return error::kNoError;
7217 if (offset < 0) {
7218 LOCAL_SET_GL_ERROR(
7219 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7220 return error::kNoError;
7222 GLsizei component_size =
7223 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7224 // component_size must be a power of two to use & as optimized modulo.
7225 DCHECK(GLES2Util::IsPOT(component_size));
7226 if (offset & (component_size - 1)) {
7227 LOCAL_SET_GL_ERROR(
7228 GL_INVALID_OPERATION,
7229 "glVertexAttribPointer", "offset not valid for type");
7230 return error::kNoError;
7232 if (stride & (component_size - 1)) {
7233 LOCAL_SET_GL_ERROR(
7234 GL_INVALID_OPERATION,
7235 "glVertexAttribPointer", "stride not valid for type");
7236 return error::kNoError;
7238 state_.vertex_attrib_manager
7239 ->SetAttribInfo(indx,
7240 state_.bound_array_buffer.get(),
7241 size,
7242 type,
7243 normalized,
7244 stride,
7245 stride != 0 ? stride : component_size * size,
7246 offset);
7247 if (type != GL_FIXED) {
7248 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7250 return error::kNoError;
7253 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7254 GLsizei height) {
7255 state_.viewport_x = x;
7256 state_.viewport_y = y;
7257 state_.viewport_width = std::min(width, viewport_max_width_);
7258 state_.viewport_height = std::min(height, viewport_max_height_);
7259 glViewport(x, y, width, height);
7262 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7263 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
7264 if (!features().angle_instanced_arrays) {
7265 LOCAL_SET_GL_ERROR(
7266 GL_INVALID_OPERATION,
7267 "glVertexAttribDivisorANGLE", "function not available");
7268 return error::kNoError;
7270 GLuint index = c.index;
7271 GLuint divisor = c.divisor;
7272 if (index >= group_->max_vertex_attribs()) {
7273 LOCAL_SET_GL_ERROR(
7274 GL_INVALID_VALUE,
7275 "glVertexAttribDivisorANGLE", "index out of range");
7276 return error::kNoError;
7279 state_.vertex_attrib_manager->SetDivisor(
7280 index,
7281 divisor);
7282 glVertexAttribDivisorANGLE(index, divisor);
7283 return error::kNoError;
7286 template <typename pixel_data_type>
7287 static void WriteAlphaData(
7288 void *pixels, uint32 row_count, uint32 channel_count,
7289 uint32 alpha_channel_index, uint32 unpadded_row_size,
7290 uint32 padded_row_size, pixel_data_type alpha_value) {
7291 DCHECK_GT(channel_count, 0U);
7292 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7293 uint32 unpadded_row_size_in_elements =
7294 unpadded_row_size / sizeof(pixel_data_type);
7295 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7296 uint32 padded_row_size_in_elements =
7297 padded_row_size / sizeof(pixel_data_type);
7298 pixel_data_type* dst =
7299 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7300 for (uint32 yy = 0; yy < row_count; ++yy) {
7301 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7302 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7303 *d = alpha_value;
7305 dst += padded_row_size_in_elements;
7309 void GLES2DecoderImpl::FinishReadPixels(
7310 const cmds::ReadPixels& c,
7311 GLuint buffer) {
7312 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7313 GLsizei width = c.width;
7314 GLsizei height = c.height;
7315 GLenum format = c.format;
7316 GLenum type = c.type;
7317 typedef cmds::ReadPixels::Result Result;
7318 uint32 pixels_size;
7319 Result* result = NULL;
7320 if (c.result_shm_id != 0) {
7321 result = GetSharedMemoryAs<Result*>(
7322 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7323 if (!result) {
7324 if (buffer != 0) {
7325 glDeleteBuffersARB(1, &buffer);
7327 return;
7330 GLES2Util::ComputeImageDataSizes(
7331 width, height, format, type, state_.pack_alignment, &pixels_size,
7332 NULL, NULL);
7333 void* pixels = GetSharedMemoryAs<void*>(
7334 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7335 if (!pixels) {
7336 if (buffer != 0) {
7337 glDeleteBuffersARB(1, &buffer);
7339 return;
7342 if (buffer != 0) {
7343 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7344 void* data;
7345 if (features().map_buffer_range) {
7346 data = glMapBufferRange(
7347 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7348 } else {
7349 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7351 memcpy(pixels, data, pixels_size);
7352 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7353 // have to restore the state.
7354 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7355 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7356 glDeleteBuffersARB(1, &buffer);
7359 if (result != NULL) {
7360 *result = true;
7363 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7364 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7365 if ((channels_exist & 0x0008) == 0 &&
7366 workarounds().clear_alpha_in_readpixels) {
7367 // Set the alpha to 255 because some drivers are buggy in this regard.
7368 uint32 temp_size;
7370 uint32 unpadded_row_size;
7371 uint32 padded_row_size;
7372 if (!GLES2Util::ComputeImageDataSizes(
7373 width, 2, format, type, state_.pack_alignment, &temp_size,
7374 &unpadded_row_size, &padded_row_size)) {
7375 return;
7378 uint32 channel_count = 0;
7379 uint32 alpha_channel = 0;
7380 switch (format) {
7381 case GL_RGBA:
7382 case GL_BGRA_EXT:
7383 channel_count = 4;
7384 alpha_channel = 3;
7385 break;
7386 case GL_ALPHA:
7387 channel_count = 1;
7388 alpha_channel = 0;
7389 break;
7392 if (channel_count > 0) {
7393 switch (type) {
7394 case GL_UNSIGNED_BYTE:
7395 WriteAlphaData<uint8>(
7396 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7397 padded_row_size, 0xFF);
7398 break;
7399 case GL_FLOAT:
7400 WriteAlphaData<float>(
7401 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7402 padded_row_size, 1.0f);
7403 break;
7404 case GL_HALF_FLOAT:
7405 WriteAlphaData<uint16>(
7406 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7407 padded_row_size, 0x3C00);
7408 break;
7415 error::Error GLES2DecoderImpl::HandleReadPixels(
7416 uint32 immediate_data_size, const cmds::ReadPixels& c) {
7417 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7418 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7419 if (fbo_error != error::kNoError)
7420 return fbo_error;
7421 GLint x = c.x;
7422 GLint y = c.y;
7423 GLsizei width = c.width;
7424 GLsizei height = c.height;
7425 GLenum format = c.format;
7426 GLenum type = c.type;
7427 GLboolean async = c.async;
7428 if (width < 0 || height < 0) {
7429 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7430 return error::kNoError;
7432 typedef cmds::ReadPixels::Result Result;
7433 uint32 pixels_size;
7434 if (!GLES2Util::ComputeImageDataSizes(
7435 width, height, format, type, state_.pack_alignment, &pixels_size,
7436 NULL, NULL)) {
7437 return error::kOutOfBounds;
7439 void* pixels = GetSharedMemoryAs<void*>(
7440 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7441 if (!pixels) {
7442 return error::kOutOfBounds;
7444 Result* result = NULL;
7445 if (c.result_shm_id != 0) {
7446 result = GetSharedMemoryAs<Result*>(
7447 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7448 if (!result) {
7449 return error::kOutOfBounds;
7453 if (!validators_->read_pixel_format.IsValid(format)) {
7454 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7455 return error::kNoError;
7457 if (!validators_->read_pixel_type.IsValid(type)) {
7458 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7459 return error::kNoError;
7461 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7462 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7463 // format and type are acceptable enums but not guaranteed to be supported
7464 // for this framebuffer. Have to ask gl if they are valid.
7465 GLint preferred_format = 0;
7466 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7467 GLint preferred_type = 0;
7468 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7469 if (format != static_cast<GLenum>(preferred_format) ||
7470 type != static_cast<GLenum>(preferred_type)) {
7471 LOCAL_SET_GL_ERROR(
7472 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7473 "with the current read framebuffer");
7474 return error::kNoError;
7477 if (width == 0 || height == 0) {
7478 return error::kNoError;
7481 // Get the size of the current fbo or backbuffer.
7482 gfx::Size max_size = GetBoundReadFrameBufferSize();
7484 int32 max_x;
7485 int32 max_y;
7486 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7487 LOCAL_SET_GL_ERROR(
7488 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7489 return error::kNoError;
7492 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
7493 return error::kNoError;
7496 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7497 return error::kNoError;
7500 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7502 ScopedResolvedFrameBufferBinder binder(this, false, true);
7504 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7505 // The user requested an out of range area. Get the results 1 line
7506 // at a time.
7507 uint32 temp_size;
7508 uint32 unpadded_row_size;
7509 uint32 padded_row_size;
7510 if (!GLES2Util::ComputeImageDataSizes(
7511 width, 2, format, type, state_.pack_alignment, &temp_size,
7512 &unpadded_row_size, &padded_row_size)) {
7513 LOCAL_SET_GL_ERROR(
7514 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7515 return error::kNoError;
7518 GLint dest_x_offset = std::max(-x, 0);
7519 uint32 dest_row_offset;
7520 if (!GLES2Util::ComputeImageDataSizes(
7521 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7522 NULL, NULL)) {
7523 LOCAL_SET_GL_ERROR(
7524 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7525 return error::kNoError;
7528 // Copy each row into the larger dest rect.
7529 int8* dst = static_cast<int8*>(pixels);
7530 GLint read_x = std::max(0, x);
7531 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7532 GLint read_width = read_end_x - read_x;
7533 for (GLint yy = 0; yy < height; ++yy) {
7534 GLint ry = y + yy;
7536 // Clear the row.
7537 memset(dst, 0, unpadded_row_size);
7539 // If the row is in range, copy it.
7540 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7541 glReadPixels(
7542 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7544 dst += padded_row_size;
7546 } else {
7547 if (async && features().use_async_readpixels) {
7548 GLuint buffer;
7549 glGenBuffersARB(1, &buffer);
7550 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7551 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7552 GLenum error = glGetError();
7553 if (error == GL_NO_ERROR) {
7554 glReadPixels(x, y, width, height, format, type, 0);
7555 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7556 new FenceCallback()));
7557 WaitForReadPixels(base::Bind(
7558 &GLES2DecoderImpl::FinishReadPixels,
7559 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7560 <GLES2DecoderImpl>(this),
7561 c, buffer));
7562 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7563 return error::kNoError;
7564 } else {
7565 // On error, unbind pack buffer and fall through to sync readpixels
7566 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7569 glReadPixels(x, y, width, height, format, type, pixels);
7571 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7572 if (error == GL_NO_ERROR) {
7573 if (result != NULL) {
7574 *result = true;
7576 FinishReadPixels(c, 0);
7579 return error::kNoError;
7582 error::Error GLES2DecoderImpl::HandlePixelStorei(
7583 uint32 immediate_data_size, const cmds::PixelStorei& c) {
7584 GLenum pname = c.pname;
7585 GLenum param = c.param;
7586 if (!validators_->pixel_store.IsValid(pname)) {
7587 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7588 return error::kNoError;
7590 switch (pname) {
7591 case GL_PACK_ALIGNMENT:
7592 case GL_UNPACK_ALIGNMENT:
7593 if (!validators_->pixel_store_alignment.IsValid(param)) {
7594 LOCAL_SET_GL_ERROR(
7595 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7596 return error::kNoError;
7598 break;
7599 case GL_UNPACK_FLIP_Y_CHROMIUM:
7600 unpack_flip_y_ = (param != 0);
7601 return error::kNoError;
7602 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7603 unpack_premultiply_alpha_ = (param != 0);
7604 return error::kNoError;
7605 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7606 unpack_unpremultiply_alpha_ = (param != 0);
7607 return error::kNoError;
7608 default:
7609 break;
7611 glPixelStorei(pname, param);
7612 switch (pname) {
7613 case GL_PACK_ALIGNMENT:
7614 state_.pack_alignment = param;
7615 break;
7616 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7617 state_.pack_reverse_row_order = (param != 0);
7618 break;
7619 case GL_UNPACK_ALIGNMENT:
7620 state_.unpack_alignment = param;
7621 break;
7622 default:
7623 // Validation should have prevented us from getting here.
7624 NOTREACHED();
7625 break;
7627 return error::kNoError;
7630 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7631 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
7632 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7634 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7636 if (!supports_post_sub_buffer_) {
7637 LOCAL_SET_GL_ERROR(
7638 GL_INVALID_OPERATION,
7639 "glPostSubBufferCHROMIUM", "command not supported by surface");
7640 return error::kNoError;
7642 bool is_tracing;
7643 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7644 &is_tracing);
7645 if (is_tracing) {
7646 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7647 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7648 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7649 is_offscreen ? offscreen_size_ : surface_->GetSize());
7651 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7652 return error::kNoError;
7653 } else {
7654 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7655 return error::kLostContext;
7659 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7660 uint32 immediate_data_size,
7661 const cmds::ScheduleOverlayPlaneCHROMIUM& c) {
7662 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
7663 if (!ref) {
7664 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
7665 "glScheduleOverlayPlaneCHROMIUM",
7666 "unknown texture");
7667 return error::kNoError;
7669 gfx::GLImage* image =
7670 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
7671 if (!image) {
7672 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
7673 "glScheduleOverlayPlaneCHROMIUM",
7674 "unsupported texture format");
7675 return error::kNoError;
7677 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
7678 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
7679 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
7680 "glScheduleOverlayPlaneCHROMIUM",
7681 "invalid transform enum");
7682 return error::kNoError;
7684 if (!surface_->ScheduleOverlayPlane(
7685 c.plane_z_order,
7686 transform,
7687 image,
7688 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
7689 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
7690 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
7691 "glScheduleOverlayPlaneCHROMIUM",
7692 "failed to schedule overlay");
7694 return error::kNoError;
7697 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7698 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7699 const std::string& name_str) {
7700 if (!StringIsValidForGLES(name_str.c_str())) {
7701 LOCAL_SET_GL_ERROR(
7702 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7703 return error::kNoError;
7705 Program* program = GetProgramInfoNotShader(
7706 client_id, "glGetAttribLocation");
7707 if (!program) {
7708 return error::kNoError;
7710 if (!program->IsValid()) {
7711 LOCAL_SET_GL_ERROR(
7712 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7713 return error::kNoError;
7715 GLint* location = GetSharedMemoryAs<GLint*>(
7716 location_shm_id, location_shm_offset, sizeof(GLint));
7717 if (!location) {
7718 return error::kOutOfBounds;
7720 // Require the client to init this incase the context is lost and we are no
7721 // longer executing commands.
7722 if (*location != -1) {
7723 return error::kGenericError;
7725 *location = program->GetAttribLocation(name_str);
7726 return error::kNoError;
7729 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7730 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
7731 Bucket* bucket = GetBucket(c.name_bucket_id);
7732 if (!bucket) {
7733 return error::kInvalidArguments;
7735 std::string name_str;
7736 if (!bucket->GetAsString(&name_str)) {
7737 return error::kInvalidArguments;
7739 return GetAttribLocationHelper(
7740 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7743 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7744 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7745 const std::string& name_str) {
7746 if (!StringIsValidForGLES(name_str.c_str())) {
7747 LOCAL_SET_GL_ERROR(
7748 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7749 return error::kNoError;
7751 Program* program = GetProgramInfoNotShader(
7752 client_id, "glGetUniformLocation");
7753 if (!program) {
7754 return error::kNoError;
7756 if (!program->IsValid()) {
7757 LOCAL_SET_GL_ERROR(
7758 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7759 return error::kNoError;
7761 GLint* location = GetSharedMemoryAs<GLint*>(
7762 location_shm_id, location_shm_offset, sizeof(GLint));
7763 if (!location) {
7764 return error::kOutOfBounds;
7766 // Require the client to init this incase the context is lost an we are no
7767 // longer executing commands.
7768 if (*location != -1) {
7769 return error::kGenericError;
7771 *location = program->GetUniformFakeLocation(name_str);
7772 return error::kNoError;
7775 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7776 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
7777 Bucket* bucket = GetBucket(c.name_bucket_id);
7778 if (!bucket) {
7779 return error::kInvalidArguments;
7781 std::string name_str;
7782 if (!bucket->GetAsString(&name_str)) {
7783 return error::kInvalidArguments;
7785 return GetUniformLocationHelper(
7786 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7789 error::Error GLES2DecoderImpl::HandleGetString(
7790 uint32 immediate_data_size, const cmds::GetString& c) {
7791 GLenum name = static_cast<GLenum>(c.name);
7792 if (!validators_->string_type.IsValid(name)) {
7793 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7794 return error::kNoError;
7796 const char* str = reinterpret_cast<const char*>(glGetString(name));
7797 std::string extensions;
7798 switch (name) {
7799 case GL_VERSION:
7800 str = "OpenGL ES 2.0 Chromium";
7801 break;
7802 case GL_SHADING_LANGUAGE_VERSION:
7803 str = "OpenGL ES GLSL ES 1.0 Chromium";
7804 break;
7805 case GL_RENDERER:
7806 case GL_VENDOR:
7807 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7808 // They are used by WEBGL_debug_renderer_info.
7809 if (!force_webgl_glsl_validation_)
7810 str = "Chromium";
7811 break;
7812 case GL_EXTENSIONS:
7814 // For WebGL contexts, strip out the OES derivatives and
7815 // EXT frag depth extensions if they have not been enabled.
7816 if (force_webgl_glsl_validation_) {
7817 extensions = feature_info_->extensions();
7818 if (!derivatives_explicitly_enabled_) {
7819 size_t offset = extensions.find(kOESDerivativeExtension);
7820 if (std::string::npos != offset) {
7821 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7822 std::string());
7825 if (!frag_depth_explicitly_enabled_) {
7826 size_t offset = extensions.find(kEXTFragDepthExtension);
7827 if (std::string::npos != offset) {
7828 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7829 std::string());
7832 if (!draw_buffers_explicitly_enabled_) {
7833 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7834 if (std::string::npos != offset) {
7835 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7836 std::string());
7839 if (!shader_texture_lod_explicitly_enabled_) {
7840 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
7841 if (std::string::npos != offset) {
7842 extensions.replace(offset,
7843 arraysize(kEXTShaderTextureLodExtension),
7844 std::string());
7847 } else {
7848 extensions = feature_info_->extensions().c_str();
7850 if (supports_post_sub_buffer_)
7851 extensions += " GL_CHROMIUM_post_sub_buffer";
7852 str = extensions.c_str();
7854 break;
7855 default:
7856 break;
7858 Bucket* bucket = CreateBucket(c.bucket_id);
7859 bucket->SetFromString(str);
7860 return error::kNoError;
7863 error::Error GLES2DecoderImpl::HandleBufferData(
7864 uint32 immediate_data_size, const cmds::BufferData& c) {
7865 GLenum target = static_cast<GLenum>(c.target);
7866 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7867 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7868 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7869 GLenum usage = static_cast<GLenum>(c.usage);
7870 const void* data = NULL;
7871 if (data_shm_id != 0 || data_shm_offset != 0) {
7872 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7873 if (!data) {
7874 return error::kOutOfBounds;
7877 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
7878 return error::kNoError;
7881 void GLES2DecoderImpl::DoBufferSubData(
7882 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
7883 // Just delegate it. Some validation is actually done before this.
7884 buffer_manager()->ValidateAndDoBufferSubData(
7885 &state_, target, offset, size, data);
7888 bool GLES2DecoderImpl::ClearLevel(
7889 unsigned service_id,
7890 unsigned bind_target,
7891 unsigned target,
7892 int level,
7893 unsigned internal_format,
7894 unsigned format,
7895 unsigned type,
7896 int width,
7897 int height,
7898 bool is_texture_immutable) {
7899 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7900 if (feature_info_->feature_flags().angle_depth_texture &&
7901 (channels & GLES2Util::kDepth) != 0) {
7902 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7903 // on depth formats.
7904 GLuint fb = 0;
7905 glGenFramebuffersEXT(1, &fb);
7906 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7908 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7909 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7910 GL_DEPTH_ATTACHMENT;
7912 glFramebufferTexture2DEXT(
7913 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7914 // ANGLE promises a depth only attachment ok.
7915 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7916 GL_FRAMEBUFFER_COMPLETE) {
7917 return false;
7919 glClearStencil(0);
7920 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
7921 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
7922 glClearDepth(1.0f);
7923 state_.SetDeviceDepthMask(GL_TRUE);
7924 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
7925 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7927 RestoreClearState();
7929 glDeleteFramebuffersEXT(1, &fb);
7930 Framebuffer* framebuffer =
7931 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7932 GLuint fb_service_id =
7933 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7934 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7935 return true;
7938 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7940 uint32 size;
7941 uint32 padded_row_size;
7942 if (!GLES2Util::ComputeImageDataSizes(
7943 width, height, format, type, state_.unpack_alignment, &size,
7944 NULL, &padded_row_size)) {
7945 return false;
7948 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7950 int tile_height;
7952 if (size > kMaxZeroSize) {
7953 if (kMaxZeroSize < padded_row_size) {
7954 // That'd be an awfully large texture.
7955 return false;
7957 // We should never have a large total size with a zero row size.
7958 DCHECK_GT(padded_row_size, 0U);
7959 tile_height = kMaxZeroSize / padded_row_size;
7960 if (!GLES2Util::ComputeImageDataSizes(
7961 width, tile_height, format, type, state_.unpack_alignment, &size,
7962 NULL, NULL)) {
7963 return false;
7965 } else {
7966 tile_height = height;
7969 // Assumes the size has already been checked.
7970 scoped_ptr<char[]> zero(new char[size]);
7971 memset(zero.get(), 0, size);
7972 glBindTexture(bind_target, service_id);
7974 GLint y = 0;
7975 while (y < height) {
7976 GLint h = y + tile_height > height ? height - y : tile_height;
7977 if (is_texture_immutable || h != height) {
7978 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7979 } else {
7980 glTexImage2D(
7981 target, level, internal_format, width, h, 0, format, type,
7982 zero.get());
7984 y += tile_height;
7986 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7987 &state_, bind_target);
7988 glBindTexture(bind_target, texture ? texture->service_id() : 0);
7989 return true;
7992 namespace {
7994 const int kS3TCBlockWidth = 4;
7995 const int kS3TCBlockHeight = 4;
7996 const int kS3TCDXT1BlockSize = 8;
7997 const int kS3TCDXT3AndDXT5BlockSize = 16;
7999 bool IsValidDXTSize(GLint level, GLsizei size) {
8000 return (size == 1) ||
8001 (size == 2) || !(size % kS3TCBlockWidth);
8004 bool IsValidPVRTCSize(GLint level, GLsizei size) {
8005 return GLES2Util::IsPOT(size);
8008 } // anonymous namespace.
8010 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8011 const char* function_name,
8012 GLsizei width, GLsizei height, GLenum format, size_t size) {
8013 unsigned int bytes_required = 0;
8015 switch (format) {
8016 case GL_ATC_RGB_AMD:
8017 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8018 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8019 case GL_ETC1_RGB8_OES: {
8020 int num_blocks_across =
8021 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8022 int num_blocks_down =
8023 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8024 int num_blocks = num_blocks_across * num_blocks_down;
8025 bytes_required = num_blocks * kS3TCDXT1BlockSize;
8026 break;
8028 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8029 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8030 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8031 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8032 int num_blocks_across =
8033 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8034 int num_blocks_down =
8035 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8036 int num_blocks = num_blocks_across * num_blocks_down;
8037 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
8038 break;
8040 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8041 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
8042 bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
8043 break;
8045 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8046 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8047 bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
8048 break;
8050 default:
8051 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8052 return false;
8055 if (size != bytes_required) {
8056 LOCAL_SET_GL_ERROR(
8057 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
8058 return false;
8061 return true;
8064 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8065 const char* function_name,
8066 GLint level, GLsizei width, GLsizei height, GLenum format) {
8067 switch (format) {
8068 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8069 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8070 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8071 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8072 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
8073 LOCAL_SET_GL_ERROR(
8074 GL_INVALID_OPERATION, function_name,
8075 "width or height invalid for level");
8076 return false;
8078 return true;
8080 case GL_ATC_RGB_AMD:
8081 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8082 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8083 case GL_ETC1_RGB8_OES: {
8084 if (width <= 0 || height <= 0) {
8085 LOCAL_SET_GL_ERROR(
8086 GL_INVALID_OPERATION, function_name,
8087 "width or height invalid for level");
8088 return false;
8090 return true;
8092 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8093 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8094 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8095 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8096 if (!IsValidPVRTCSize(level, width) ||
8097 !IsValidPVRTCSize(level, height)) {
8098 LOCAL_SET_GL_ERROR(
8099 GL_INVALID_OPERATION, function_name,
8100 "width or height invalid for level");
8101 return false;
8103 return true;
8105 default:
8106 return false;
8110 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8111 const char* function_name,
8112 GLenum target, GLint level, GLint xoffset, GLint yoffset,
8113 GLsizei width, GLsizei height, GLenum format,
8114 Texture* texture) {
8115 if (xoffset < 0 || yoffset < 0) {
8116 LOCAL_SET_GL_ERROR(
8117 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
8118 return false;
8121 switch (format) {
8122 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8123 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8124 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8125 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8126 const int kBlockWidth = 4;
8127 const int kBlockHeight = 4;
8128 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
8129 LOCAL_SET_GL_ERROR(
8130 GL_INVALID_OPERATION, function_name,
8131 "xoffset or yoffset not multiple of 4");
8132 return false;
8134 GLsizei tex_width = 0;
8135 GLsizei tex_height = 0;
8136 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8137 width - xoffset > tex_width ||
8138 height - yoffset > tex_height) {
8139 LOCAL_SET_GL_ERROR(
8140 GL_INVALID_OPERATION, function_name, "dimensions out of range");
8141 return false;
8143 return ValidateCompressedTexDimensions(
8144 function_name, level, width, height, format);
8146 case GL_ATC_RGB_AMD:
8147 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8148 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
8149 LOCAL_SET_GL_ERROR(
8150 GL_INVALID_OPERATION, function_name,
8151 "not supported for ATC textures");
8152 return false;
8154 case GL_ETC1_RGB8_OES: {
8155 LOCAL_SET_GL_ERROR(
8156 GL_INVALID_OPERATION, function_name,
8157 "not supported for ECT1_RGB8_OES textures");
8158 return false;
8160 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8161 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8162 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8163 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8164 if ((xoffset != 0) || (yoffset != 0)) {
8165 LOCAL_SET_GL_ERROR(
8166 GL_INVALID_OPERATION, function_name,
8167 "xoffset and yoffset must be zero");
8168 return false;
8170 GLsizei tex_width = 0;
8171 GLsizei tex_height = 0;
8172 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8173 width != tex_width ||
8174 height != tex_height) {
8175 LOCAL_SET_GL_ERROR(
8176 GL_INVALID_OPERATION, function_name,
8177 "dimensions must match existing texture level dimensions");
8178 return false;
8180 return ValidateCompressedTexDimensions(
8181 function_name, level, width, height, format);
8183 default:
8184 return false;
8188 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
8189 GLenum target,
8190 GLint level,
8191 GLenum internal_format,
8192 GLsizei width,
8193 GLsizei height,
8194 GLint border,
8195 GLsizei image_size,
8196 const void* data) {
8197 // TODO(gman): Validate image_size is correct for width, height and format.
8198 if (!validators_->texture_target.IsValid(target)) {
8199 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8200 "glCompressedTexImage2D", target, "target");
8201 return error::kNoError;
8203 if (!validators_->compressed_texture_format.IsValid(
8204 internal_format)) {
8205 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8206 "glCompressedTexImage2D", internal_format, "internal_format");
8207 return error::kNoError;
8209 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8210 border != 0) {
8211 LOCAL_SET_GL_ERROR(
8212 GL_INVALID_VALUE,
8213 "glCompressedTexImage2D", "dimensions out of range");
8214 return error::kNoError;
8216 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8217 &state_, target);
8218 if (!texture_ref) {
8219 LOCAL_SET_GL_ERROR(
8220 GL_INVALID_VALUE,
8221 "glCompressedTexImage2D", "unknown texture target");
8222 return error::kNoError;
8224 Texture* texture = texture_ref->texture();
8225 if (texture->IsImmutable()) {
8226 LOCAL_SET_GL_ERROR(
8227 GL_INVALID_OPERATION,
8228 "glCompressedTexImage2D", "texture is immutable");
8229 return error::kNoError;
8232 if (!ValidateCompressedTexDimensions(
8233 "glCompressedTexImage2D", level, width, height, internal_format) ||
8234 !ValidateCompressedTexFuncData(
8235 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8236 return error::kNoError;
8239 if (!EnsureGPUMemoryAvailable(image_size)) {
8240 LOCAL_SET_GL_ERROR(
8241 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8242 return error::kNoError;
8245 if (texture->IsAttachedToFramebuffer()) {
8246 framebuffer_state_.clear_state_dirty = true;
8249 scoped_ptr<int8[]> zero;
8250 if (!data) {
8251 zero.reset(new int8[image_size]);
8252 memset(zero.get(), 0, image_size);
8253 data = zero.get();
8255 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8256 glCompressedTexImage2D(
8257 target, level, internal_format, width, height, border, image_size, data);
8258 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8259 if (error == GL_NO_ERROR) {
8260 texture_manager()->SetLevelInfo(
8261 texture_ref, target, level, internal_format,
8262 width, height, 1, border, 0, 0, true);
8264 return error::kNoError;
8267 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8268 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
8269 GLenum target = static_cast<GLenum>(c.target);
8270 GLint level = static_cast<GLint>(c.level);
8271 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8272 GLsizei width = static_cast<GLsizei>(c.width);
8273 GLsizei height = static_cast<GLsizei>(c.height);
8274 GLint border = static_cast<GLint>(c.border);
8275 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8276 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8277 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8278 const void* data = NULL;
8279 if (data_shm_id != 0 || data_shm_offset != 0) {
8280 data = GetSharedMemoryAs<const void*>(
8281 data_shm_id, data_shm_offset, image_size);
8282 if (!data) {
8283 return error::kOutOfBounds;
8286 return DoCompressedTexImage2D(
8287 target, level, internal_format, width, height, border, image_size, data);
8290 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8291 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
8292 GLenum target = static_cast<GLenum>(c.target);
8293 GLint level = static_cast<GLint>(c.level);
8294 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8295 GLsizei width = static_cast<GLsizei>(c.width);
8296 GLsizei height = static_cast<GLsizei>(c.height);
8297 GLint border = static_cast<GLint>(c.border);
8298 Bucket* bucket = GetBucket(c.bucket_id);
8299 if (!bucket) {
8300 return error::kInvalidArguments;
8302 uint32 data_size = bucket->size();
8303 GLsizei imageSize = data_size;
8304 const void* data = bucket->GetData(0, data_size);
8305 if (!data) {
8306 return error::kInvalidArguments;
8308 return DoCompressedTexImage2D(
8309 target, level, internal_format, width, height, border,
8310 imageSize, data);
8313 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8314 uint32 immediate_data_size,
8315 const cmds::CompressedTexSubImage2DBucket& c) {
8316 GLenum target = static_cast<GLenum>(c.target);
8317 GLint level = static_cast<GLint>(c.level);
8318 GLint xoffset = static_cast<GLint>(c.xoffset);
8319 GLint yoffset = static_cast<GLint>(c.yoffset);
8320 GLsizei width = static_cast<GLsizei>(c.width);
8321 GLsizei height = static_cast<GLsizei>(c.height);
8322 GLenum format = static_cast<GLenum>(c.format);
8323 Bucket* bucket = GetBucket(c.bucket_id);
8324 if (!bucket) {
8325 return error::kInvalidArguments;
8327 uint32 data_size = bucket->size();
8328 GLsizei imageSize = data_size;
8329 const void* data = bucket->GetData(0, data_size);
8330 if (!data) {
8331 return error::kInvalidArguments;
8333 if (!validators_->texture_target.IsValid(target)) {
8334 LOCAL_SET_GL_ERROR(
8335 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8336 return error::kNoError;
8338 if (!validators_->compressed_texture_format.IsValid(format)) {
8339 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8340 "glCompressedTexSubImage2D", format, "format");
8341 return error::kNoError;
8343 if (width < 0) {
8344 LOCAL_SET_GL_ERROR(
8345 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8346 return error::kNoError;
8348 if (height < 0) {
8349 LOCAL_SET_GL_ERROR(
8350 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8351 return error::kNoError;
8353 if (imageSize < 0) {
8354 LOCAL_SET_GL_ERROR(
8355 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8356 return error::kNoError;
8358 DoCompressedTexSubImage2D(
8359 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8360 return error::kNoError;
8363 error::Error GLES2DecoderImpl::HandleTexImage2D(
8364 uint32 immediate_data_size, const cmds::TexImage2D& c) {
8365 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8366 "width", c.width, "height", c.height);
8367 // Set as failed for now, but if it successed, this will be set to not failed.
8368 texture_state_.tex_image_2d_failed = true;
8369 GLenum target = static_cast<GLenum>(c.target);
8370 GLint level = static_cast<GLint>(c.level);
8371 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8372 // for internalformat.
8373 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8374 GLsizei width = static_cast<GLsizei>(c.width);
8375 GLsizei height = static_cast<GLsizei>(c.height);
8376 GLint border = static_cast<GLint>(c.border);
8377 GLenum format = static_cast<GLenum>(c.format);
8378 GLenum type = static_cast<GLenum>(c.type);
8379 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8380 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8381 uint32 pixels_size;
8382 if (!GLES2Util::ComputeImageDataSizes(
8383 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8384 NULL)) {
8385 return error::kOutOfBounds;
8387 const void* pixels = NULL;
8388 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8389 pixels = GetSharedMemoryAs<const void*>(
8390 pixels_shm_id, pixels_shm_offset, pixels_size);
8391 if (!pixels) {
8392 return error::kOutOfBounds;
8396 TextureManager::DoTextImage2DArguments args = {
8397 target, level, internal_format, width, height, border, format, type,
8398 pixels, pixels_size};
8399 texture_manager()->ValidateAndDoTexImage2D(
8400 &texture_state_, &state_, &framebuffer_state_, args);
8401 return error::kNoError;
8404 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8405 GLenum target,
8406 GLint level,
8407 GLint xoffset,
8408 GLint yoffset,
8409 GLsizei width,
8410 GLsizei height,
8411 GLenum format,
8412 GLsizei image_size,
8413 const void * data) {
8414 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8415 &state_, target);
8416 if (!texture_ref) {
8417 LOCAL_SET_GL_ERROR(
8418 GL_INVALID_OPERATION,
8419 "glCompressedTexSubImage2D", "unknown texture for target");
8420 return;
8422 Texture* texture = texture_ref->texture();
8423 GLenum type = 0;
8424 GLenum internal_format = 0;
8425 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8426 LOCAL_SET_GL_ERROR(
8427 GL_INVALID_OPERATION,
8428 "glCompressedTexSubImage2D", "level does not exist.");
8429 return;
8431 if (internal_format != format) {
8432 LOCAL_SET_GL_ERROR(
8433 GL_INVALID_OPERATION,
8434 "glCompressedTexSubImage2D", "format does not match internal format.");
8435 return;
8437 if (!texture->ValidForTexture(
8438 target, level, xoffset, yoffset, width, height, type)) {
8439 LOCAL_SET_GL_ERROR(
8440 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8441 return;
8444 if (!ValidateCompressedTexFuncData(
8445 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8446 !ValidateCompressedTexSubDimensions(
8447 "glCompressedTexSubImage2D",
8448 target, level, xoffset, yoffset, width, height, format, texture)) {
8449 return;
8453 // Note: There is no need to deal with texture cleared tracking here
8454 // because the validation above means you can only get here if the level
8455 // is already a matching compressed format and in that case
8456 // CompressedTexImage2D already cleared the texture.
8457 glCompressedTexSubImage2D(
8458 target, level, xoffset, yoffset, width, height, format, image_size, data);
8461 static void Clip(
8462 GLint start, GLint range, GLint sourceRange,
8463 GLint* out_start, GLint* out_range) {
8464 DCHECK(out_start);
8465 DCHECK(out_range);
8466 if (start < 0) {
8467 range += start;
8468 start = 0;
8470 GLint end = start + range;
8471 if (end > sourceRange) {
8472 range -= end - sourceRange;
8474 *out_start = start;
8475 *out_range = range;
8478 void GLES2DecoderImpl::DoCopyTexImage2D(
8479 GLenum target,
8480 GLint level,
8481 GLenum internal_format,
8482 GLint x,
8483 GLint y,
8484 GLsizei width,
8485 GLsizei height,
8486 GLint border) {
8487 DCHECK(!ShouldDeferReads());
8488 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8489 &state_, target);
8490 if (!texture_ref) {
8491 LOCAL_SET_GL_ERROR(
8492 GL_INVALID_OPERATION,
8493 "glCopyTexImage2D", "unknown texture for target");
8494 return;
8496 Texture* texture = texture_ref->texture();
8497 if (texture->IsImmutable()) {
8498 LOCAL_SET_GL_ERROR(
8499 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8500 return;
8502 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8503 border != 0) {
8504 LOCAL_SET_GL_ERROR(
8505 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8506 return;
8508 if (!texture_manager()->ValidateFormatAndTypeCombination(
8509 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8510 GL_UNSIGNED_BYTE)) {
8511 return;
8514 // Check we have compatible formats.
8515 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8516 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8517 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8519 if ((channels_needed & channels_exist) != channels_needed) {
8520 LOCAL_SET_GL_ERROR(
8521 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8522 return;
8525 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8526 LOCAL_SET_GL_ERROR(
8527 GL_INVALID_OPERATION,
8528 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8529 return;
8532 uint32 estimated_size = 0;
8533 if (!GLES2Util::ComputeImageDataSizes(
8534 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8535 &estimated_size, NULL, NULL)) {
8536 LOCAL_SET_GL_ERROR(
8537 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8538 return;
8541 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8542 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8543 return;
8546 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
8547 return;
8550 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8551 return;
8554 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8555 ScopedResolvedFrameBufferBinder binder(this, false, true);
8556 gfx::Size size = GetBoundReadFrameBufferSize();
8558 if (texture->IsAttachedToFramebuffer()) {
8559 framebuffer_state_.clear_state_dirty = true;
8562 // Clip to size to source dimensions
8563 GLint copyX = 0;
8564 GLint copyY = 0;
8565 GLint copyWidth = 0;
8566 GLint copyHeight = 0;
8567 Clip(x, width, size.width(), &copyX, &copyWidth);
8568 Clip(y, height, size.height(), &copyY, &copyHeight);
8570 if (copyX != x ||
8571 copyY != y ||
8572 copyWidth != width ||
8573 copyHeight != height) {
8574 // some part was clipped so clear the texture.
8575 if (!ClearLevel(
8576 texture->service_id(), texture->target(),
8577 target, level, internal_format, internal_format, GL_UNSIGNED_BYTE,
8578 width, height, texture->IsImmutable())) {
8579 LOCAL_SET_GL_ERROR(
8580 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8581 return;
8583 if (copyHeight > 0 && copyWidth > 0) {
8584 GLint dx = copyX - x;
8585 GLint dy = copyY - y;
8586 GLint destX = dx;
8587 GLint destY = dy;
8588 ScopedModifyPixels modify(texture_ref);
8589 glCopyTexSubImage2D(target, level,
8590 destX, destY, copyX, copyY,
8591 copyWidth, copyHeight);
8593 } else {
8594 ScopedModifyPixels modify(texture_ref);
8595 glCopyTexImage2D(target, level, internal_format,
8596 copyX, copyY, copyWidth, copyHeight, border);
8598 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8599 if (error == GL_NO_ERROR) {
8600 texture_manager()->SetLevelInfo(
8601 texture_ref, target, level, internal_format, width, height, 1,
8602 border, internal_format, GL_UNSIGNED_BYTE, true);
8606 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8607 GLenum target,
8608 GLint level,
8609 GLint xoffset,
8610 GLint yoffset,
8611 GLint x,
8612 GLint y,
8613 GLsizei width,
8614 GLsizei height) {
8615 DCHECK(!ShouldDeferReads());
8616 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8617 &state_, target);
8618 if (!texture_ref) {
8619 LOCAL_SET_GL_ERROR(
8620 GL_INVALID_OPERATION,
8621 "glCopyTexSubImage2D", "unknown texture for target");
8622 return;
8624 Texture* texture = texture_ref->texture();
8625 GLenum type = 0;
8626 GLenum format = 0;
8627 if (!texture->GetLevelType(target, level, &type, &format) ||
8628 !texture->ValidForTexture(
8629 target, level, xoffset, yoffset, width, height, type)) {
8630 LOCAL_SET_GL_ERROR(
8631 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8632 return;
8634 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8635 LOCAL_SET_GL_ERROR(
8636 GL_INVALID_OPERATION,
8637 "glCopyTexSubImage2D", "async upload pending for texture");
8638 return;
8641 // Check we have compatible formats.
8642 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8643 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8644 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8646 if (!channels_needed ||
8647 (channels_needed & channels_exist) != channels_needed) {
8648 LOCAL_SET_GL_ERROR(
8649 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8650 return;
8653 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8654 LOCAL_SET_GL_ERROR(
8655 GL_INVALID_OPERATION,
8656 "glCopySubImage2D", "can not be used with depth or stencil textures");
8657 return;
8660 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
8661 return;
8664 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8665 return;
8668 ScopedResolvedFrameBufferBinder binder(this, false, true);
8669 gfx::Size size = GetBoundReadFrameBufferSize();
8670 GLint copyX = 0;
8671 GLint copyY = 0;
8672 GLint copyWidth = 0;
8673 GLint copyHeight = 0;
8674 Clip(x, width, size.width(), &copyX, &copyWidth);
8675 Clip(y, height, size.height(), &copyY, &copyHeight);
8677 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8678 LOCAL_SET_GL_ERROR(
8679 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8680 return;
8683 if (copyX != x ||
8684 copyY != y ||
8685 copyWidth != width ||
8686 copyHeight != height) {
8687 // some part was clipped so clear the sub rect.
8688 uint32 pixels_size = 0;
8689 if (!GLES2Util::ComputeImageDataSizes(
8690 width, height, format, type, state_.unpack_alignment, &pixels_size,
8691 NULL, NULL)) {
8692 LOCAL_SET_GL_ERROR(
8693 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8694 return;
8696 scoped_ptr<char[]> zero(new char[pixels_size]);
8697 memset(zero.get(), 0, pixels_size);
8698 ScopedModifyPixels modify(texture_ref);
8699 glTexSubImage2D(
8700 target, level, xoffset, yoffset, width, height,
8701 format, type, zero.get());
8704 if (copyHeight > 0 && copyWidth > 0) {
8705 GLint dx = copyX - x;
8706 GLint dy = copyY - y;
8707 GLint destX = xoffset + dx;
8708 GLint destY = yoffset + dy;
8709 ScopedModifyPixels modify(texture_ref);
8710 glCopyTexSubImage2D(target, level,
8711 destX, destY, copyX, copyY,
8712 copyWidth, copyHeight);
8716 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8717 error::Error* error,
8718 const char* function_name,
8719 GLenum target,
8720 GLint level,
8721 GLint xoffset,
8722 GLint yoffset,
8723 GLsizei width,
8724 GLsizei height,
8725 GLenum format,
8726 GLenum type,
8727 const void * data) {
8728 (*error) = error::kNoError;
8729 if (!validators_->texture_target.IsValid(target)) {
8730 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8731 return false;
8733 if (width < 0) {
8734 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8735 return false;
8737 if (height < 0) {
8738 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8739 return false;
8741 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8742 &state_, target);
8743 if (!texture_ref) {
8744 LOCAL_SET_GL_ERROR(
8745 GL_INVALID_OPERATION,
8746 function_name, "unknown texture for target");
8747 return false;
8749 Texture* texture = texture_ref->texture();
8750 GLenum current_type = 0;
8751 GLenum internal_format = 0;
8752 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
8753 LOCAL_SET_GL_ERROR(
8754 GL_INVALID_OPERATION, function_name, "level does not exist.");
8755 return false;
8757 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
8758 function_name, format, type, internal_format, level)) {
8759 return false;
8761 if (type != current_type) {
8762 LOCAL_SET_GL_ERROR(
8763 GL_INVALID_OPERATION,
8764 function_name, "type does not match type of texture.");
8765 return false;
8767 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8768 LOCAL_SET_GL_ERROR(
8769 GL_INVALID_OPERATION,
8770 function_name, "async upload pending for texture");
8771 return false;
8773 if (!texture->ValidForTexture(
8774 target, level, xoffset, yoffset, width, height, type)) {
8775 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8776 return false;
8778 if ((GLES2Util::GetChannelsForFormat(format) &
8779 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8780 LOCAL_SET_GL_ERROR(
8781 GL_INVALID_OPERATION,
8782 function_name, "can not supply data for depth or stencil textures");
8783 return false;
8785 if (data == NULL) {
8786 (*error) = error::kOutOfBounds;
8787 return false;
8789 return true;
8792 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8793 GLenum target,
8794 GLint level,
8795 GLint xoffset,
8796 GLint yoffset,
8797 GLsizei width,
8798 GLsizei height,
8799 GLenum format,
8800 GLenum type,
8801 const void * data) {
8802 error::Error error = error::kNoError;
8803 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8804 xoffset, yoffset, width, height, format, type, data)) {
8805 return error;
8807 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8808 &state_, target);
8809 Texture* texture = texture_ref->texture();
8810 GLsizei tex_width = 0;
8811 GLsizei tex_height = 0;
8812 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8813 DCHECK(ok);
8814 if (xoffset != 0 || yoffset != 0 ||
8815 width != tex_width || height != tex_height) {
8816 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8817 target, level)) {
8818 LOCAL_SET_GL_ERROR(
8819 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8820 return error::kNoError;
8822 ScopedTextureUploadTimer timer(&texture_state_);
8823 glTexSubImage2D(
8824 target, level, xoffset, yoffset, width, height, format, type, data);
8825 return error::kNoError;
8828 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
8829 !texture->IsImmutable()) {
8830 ScopedTextureUploadTimer timer(&texture_state_);
8831 GLenum internal_format;
8832 GLenum tex_type;
8833 texture->GetLevelType(target, level, &tex_type, &internal_format);
8834 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
8835 // to look it up.
8836 glTexImage2D(
8837 target, level, internal_format, width, height, 0, format, type, data);
8838 } else {
8839 ScopedTextureUploadTimer timer(&texture_state_);
8840 glTexSubImage2D(
8841 target, level, xoffset, yoffset, width, height, format, type, data);
8843 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
8844 return error::kNoError;
8847 error::Error GLES2DecoderImpl::HandleTexSubImage2D(
8848 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
8849 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
8850 "width", c.width, "height", c.height);
8851 GLboolean internal = static_cast<GLboolean>(c.internal);
8852 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
8853 return error::kNoError;
8855 GLenum target = static_cast<GLenum>(c.target);
8856 GLint level = static_cast<GLint>(c.level);
8857 GLint xoffset = static_cast<GLint>(c.xoffset);
8858 GLint yoffset = static_cast<GLint>(c.yoffset);
8859 GLsizei width = static_cast<GLsizei>(c.width);
8860 GLsizei height = static_cast<GLsizei>(c.height);
8861 GLenum format = static_cast<GLenum>(c.format);
8862 GLenum type = static_cast<GLenum>(c.type);
8863 uint32 data_size;
8864 if (!GLES2Util::ComputeImageDataSizes(
8865 width, height, format, type, state_.unpack_alignment, &data_size,
8866 NULL, NULL)) {
8867 return error::kOutOfBounds;
8869 const void* pixels = GetSharedMemoryAs<const void*>(
8870 c.pixels_shm_id, c.pixels_shm_offset, data_size);
8871 return DoTexSubImage2D(
8872 target, level, xoffset, yoffset, width, height, format, type, pixels);
8875 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8876 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
8877 GLuint index = static_cast<GLuint>(c.index);
8878 GLenum pname = static_cast<GLenum>(c.pname);
8879 typedef cmds::GetVertexAttribPointerv::Result Result;
8880 Result* result = GetSharedMemoryAs<Result*>(
8881 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8882 if (!result) {
8883 return error::kOutOfBounds;
8885 // Check that the client initialized the result.
8886 if (result->size != 0) {
8887 return error::kInvalidArguments;
8889 if (!validators_->vertex_pointer.IsValid(pname)) {
8890 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8891 "glGetVertexAttribPointerv", pname, "pname");
8892 return error::kNoError;
8894 if (index >= group_->max_vertex_attribs()) {
8895 LOCAL_SET_GL_ERROR(
8896 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
8897 return error::kNoError;
8899 result->SetNumResults(1);
8900 *result->GetData() =
8901 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
8902 return error::kNoError;
8905 bool GLES2DecoderImpl::GetUniformSetup(
8906 GLuint program_id, GLint fake_location,
8907 uint32 shm_id, uint32 shm_offset,
8908 error::Error* error, GLint* real_location,
8909 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8910 DCHECK(error);
8911 DCHECK(service_id);
8912 DCHECK(result_pointer);
8913 DCHECK(result_type);
8914 DCHECK(real_location);
8915 *error = error::kNoError;
8916 // Make sure we have enough room for the result on failure.
8917 SizedResult<GLint>* result;
8918 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8919 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8920 if (!result) {
8921 *error = error::kOutOfBounds;
8922 return false;
8924 *result_pointer = result;
8925 // Set the result size to 0 so the client does not have to check for success.
8926 result->SetNumResults(0);
8927 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8928 if (!program) {
8929 return false;
8931 if (!program->IsValid()) {
8932 // Program was not linked successfully. (ie, glLinkProgram)
8933 LOCAL_SET_GL_ERROR(
8934 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
8935 return false;
8937 *service_id = program->service_id();
8938 GLint array_index = -1;
8939 const Program::UniformInfo* uniform_info =
8940 program->GetUniformInfoByFakeLocation(
8941 fake_location, real_location, &array_index);
8942 if (!uniform_info) {
8943 // No such location.
8944 LOCAL_SET_GL_ERROR(
8945 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
8946 return false;
8948 GLenum type = uniform_info->type;
8949 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8950 if (size == 0) {
8951 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
8952 return false;
8954 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8955 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8956 if (!result) {
8957 *error = error::kOutOfBounds;
8958 return false;
8960 result->size = size;
8961 *result_type = type;
8962 return true;
8965 error::Error GLES2DecoderImpl::HandleGetUniformiv(
8966 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
8967 GLuint program = c.program;
8968 GLint fake_location = c.location;
8969 GLuint service_id;
8970 GLenum result_type;
8971 GLint real_location = -1;
8972 Error error;
8973 void* result;
8974 if (GetUniformSetup(
8975 program, fake_location, c.params_shm_id, c.params_shm_offset,
8976 &error, &real_location, &service_id, &result, &result_type)) {
8977 glGetUniformiv(
8978 service_id, real_location,
8979 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
8981 return error;
8984 error::Error GLES2DecoderImpl::HandleGetUniformfv(
8985 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
8986 GLuint program = c.program;
8987 GLint fake_location = c.location;
8988 GLuint service_id;
8989 GLint real_location = -1;
8990 Error error;
8991 typedef cmds::GetUniformfv::Result Result;
8992 Result* result;
8993 GLenum result_type;
8994 if (GetUniformSetup(
8995 program, fake_location, c.params_shm_id, c.params_shm_offset,
8996 &error, &real_location, &service_id,
8997 reinterpret_cast<void**>(&result), &result_type)) {
8998 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8999 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
9000 GLsizei num_values = result->GetNumResults();
9001 scoped_ptr<GLint[]> temp(new GLint[num_values]);
9002 glGetUniformiv(service_id, real_location, temp.get());
9003 GLfloat* dst = result->GetData();
9004 for (GLsizei ii = 0; ii < num_values; ++ii) {
9005 dst[ii] = (temp[ii] != 0);
9007 } else {
9008 glGetUniformfv(service_id, real_location, result->GetData());
9011 return error;
9014 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9015 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
9016 GLenum shader_type = static_cast<GLenum>(c.shadertype);
9017 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
9018 typedef cmds::GetShaderPrecisionFormat::Result Result;
9019 Result* result = GetSharedMemoryAs<Result*>(
9020 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9021 if (!result) {
9022 return error::kOutOfBounds;
9024 // Check that the client initialized the result.
9025 if (result->success != 0) {
9026 return error::kInvalidArguments;
9028 if (!validators_->shader_type.IsValid(shader_type)) {
9029 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9030 "glGetShaderPrecisionFormat", shader_type, "shader_type");
9031 return error::kNoError;
9033 if (!validators_->shader_precision.IsValid(precision_type)) {
9034 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9035 "glGetShaderPrecisionFormat", precision_type, "precision_type");
9036 return error::kNoError;
9039 result->success = 1; // true
9041 GLint range[2] = { 0, 0 };
9042 GLint precision = 0;
9043 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
9045 result->min_range = range[0];
9046 result->max_range = range[1];
9047 result->precision = precision;
9049 return error::kNoError;
9052 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
9053 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
9054 uint32 result_size = c.result_size;
9055 GLuint program_id = static_cast<GLuint>(c.program);
9056 Program* program = GetProgramInfoNotShader(
9057 program_id, "glGetAttachedShaders");
9058 if (!program) {
9059 return error::kNoError;
9061 typedef cmds::GetAttachedShaders::Result Result;
9062 uint32 max_count = Result::ComputeMaxResults(result_size);
9063 Result* result = GetSharedMemoryAs<Result*>(
9064 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
9065 if (!result) {
9066 return error::kOutOfBounds;
9068 // Check that the client initialized the result.
9069 if (result->size != 0) {
9070 return error::kInvalidArguments;
9072 GLsizei count = 0;
9073 glGetAttachedShaders(
9074 program->service_id(), max_count, &count, result->GetData());
9075 for (GLsizei ii = 0; ii < count; ++ii) {
9076 if (!shader_manager()->GetClientId(result->GetData()[ii],
9077 &result->GetData()[ii])) {
9078 NOTREACHED();
9079 return error::kGenericError;
9082 result->SetNumResults(count);
9083 return error::kNoError;
9086 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
9087 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
9088 GLuint program_id = c.program;
9089 GLuint index = c.index;
9090 uint32 name_bucket_id = c.name_bucket_id;
9091 typedef cmds::GetActiveUniform::Result Result;
9092 Result* result = GetSharedMemoryAs<Result*>(
9093 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9094 if (!result) {
9095 return error::kOutOfBounds;
9097 // Check that the client initialized the result.
9098 if (result->success != 0) {
9099 return error::kInvalidArguments;
9101 Program* program = GetProgramInfoNotShader(
9102 program_id, "glGetActiveUniform");
9103 if (!program) {
9104 return error::kNoError;
9106 const Program::UniformInfo* uniform_info =
9107 program->GetUniformInfo(index);
9108 if (!uniform_info) {
9109 LOCAL_SET_GL_ERROR(
9110 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
9111 return error::kNoError;
9113 result->success = 1; // true.
9114 result->size = uniform_info->size;
9115 result->type = uniform_info->type;
9116 Bucket* bucket = CreateBucket(name_bucket_id);
9117 bucket->SetFromString(uniform_info->name.c_str());
9118 return error::kNoError;
9121 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
9122 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
9123 GLuint program_id = c.program;
9124 GLuint index = c.index;
9125 uint32 name_bucket_id = c.name_bucket_id;
9126 typedef cmds::GetActiveAttrib::Result Result;
9127 Result* result = GetSharedMemoryAs<Result*>(
9128 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9129 if (!result) {
9130 return error::kOutOfBounds;
9132 // Check that the client initialized the result.
9133 if (result->success != 0) {
9134 return error::kInvalidArguments;
9136 Program* program = GetProgramInfoNotShader(
9137 program_id, "glGetActiveAttrib");
9138 if (!program) {
9139 return error::kNoError;
9141 const Program::VertexAttrib* attrib_info =
9142 program->GetAttribInfo(index);
9143 if (!attrib_info) {
9144 LOCAL_SET_GL_ERROR(
9145 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
9146 return error::kNoError;
9148 result->success = 1; // true.
9149 result->size = attrib_info->size;
9150 result->type = attrib_info->type;
9151 Bucket* bucket = CreateBucket(name_bucket_id);
9152 bucket->SetFromString(attrib_info->name.c_str());
9153 return error::kNoError;
9156 error::Error GLES2DecoderImpl::HandleShaderBinary(
9157 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
9158 #if 1 // No binary shader support.
9159 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
9160 return error::kNoError;
9161 #else
9162 GLsizei n = static_cast<GLsizei>(c.n);
9163 if (n < 0) {
9164 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
9165 return error::kNoError;
9167 GLsizei length = static_cast<GLsizei>(c.length);
9168 if (length < 0) {
9169 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
9170 return error::kNoError;
9172 uint32 data_size;
9173 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
9174 return error::kOutOfBounds;
9176 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
9177 c.shaders_shm_id, c.shaders_shm_offset, data_size);
9178 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
9179 const void* binary = GetSharedMemoryAs<const void*>(
9180 c.binary_shm_id, c.binary_shm_offset, length);
9181 if (shaders == NULL || binary == NULL) {
9182 return error::kOutOfBounds;
9184 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9185 for (GLsizei ii = 0; ii < n; ++ii) {
9186 Shader* shader = GetShader(shaders[ii]);
9187 if (!shader) {
9188 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
9189 return error::kNoError;
9191 service_ids[ii] = shader->service_id();
9193 // TODO(gman): call glShaderBinary
9194 return error::kNoError;
9195 #endif
9198 void GLES2DecoderImpl::DoSwapBuffers() {
9199 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
9201 int this_frame_number = frame_number_++;
9202 // TRACE_EVENT for gpu tests:
9203 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9204 TRACE_EVENT_SCOPE_THREAD,
9205 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9206 "width", (is_offscreen ? offscreen_size_.width() :
9207 surface_->GetSize().width()));
9208 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9209 "offscreen", is_offscreen,
9210 "frame", this_frame_number);
9212 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9215 bool is_tracing;
9216 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9217 &is_tracing);
9218 if (is_tracing) {
9219 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
9220 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
9221 is_offscreen ? offscreen_size_ : surface_->GetSize());
9224 // If offscreen then don't actually SwapBuffers to the display. Just copy
9225 // the rendered frame to another frame buffer.
9226 if (is_offscreen) {
9227 TRACE_EVENT2("gpu", "Offscreen",
9228 "width", offscreen_size_.width(), "height", offscreen_size_.height());
9229 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
9230 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9231 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9232 // fix this.
9233 if (workarounds().needs_offscreen_buffer_workaround) {
9234 offscreen_saved_frame_buffer_->Create();
9235 glFinish();
9238 // Allocate the offscreen saved color texture.
9239 DCHECK(offscreen_saved_color_format_);
9240 offscreen_saved_color_texture_->AllocateStorage(
9241 offscreen_size_, offscreen_saved_color_format_, false);
9243 offscreen_saved_frame_buffer_->AttachRenderTexture(
9244 offscreen_saved_color_texture_.get());
9245 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
9246 if (offscreen_saved_frame_buffer_->CheckStatus() !=
9247 GL_FRAMEBUFFER_COMPLETE) {
9248 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9249 << "because offscreen saved FBO was incomplete.";
9250 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9251 return;
9254 // Clear the offscreen color texture.
9255 // TODO(piman): Is this still necessary?
9257 ScopedFrameBufferBinder binder(this,
9258 offscreen_saved_frame_buffer_->id());
9259 glClearColor(0, 0, 0, 0);
9260 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9261 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
9262 glClear(GL_COLOR_BUFFER_BIT);
9263 RestoreClearState();
9267 UpdateParentTextureInfo();
9270 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
9271 return;
9272 ScopedGLErrorSuppressor suppressor(
9273 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9275 if (IsOffscreenBufferMultisampled()) {
9276 // For multisampled buffers, resolve the frame buffer.
9277 ScopedResolvedFrameBufferBinder binder(this, true, false);
9278 } else {
9279 ScopedFrameBufferBinder binder(this,
9280 offscreen_target_frame_buffer_->id());
9282 if (offscreen_target_buffer_preserved_) {
9283 // Copy the target frame buffer to the saved offscreen texture.
9284 offscreen_saved_color_texture_->Copy(
9285 offscreen_saved_color_texture_->size(),
9286 offscreen_saved_color_format_);
9287 } else {
9288 // Flip the textures in the parent context via the texture manager.
9289 if (!!offscreen_saved_color_texture_info_.get())
9290 offscreen_saved_color_texture_info_->texture()->
9291 SetServiceId(offscreen_target_color_texture_->id());
9293 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9294 offscreen_target_frame_buffer_->AttachRenderTexture(
9295 offscreen_target_color_texture_.get());
9298 // Ensure the side effects of the copy are visible to the parent
9299 // context. There is no need to do this for ANGLE because it uses a
9300 // single D3D device for all contexts.
9301 if (!feature_info_->feature_flags().is_angle)
9302 glFlush();
9304 } else {
9305 if (!surface_->SwapBuffers()) {
9306 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9307 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9312 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9313 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
9314 Bucket* bucket = GetBucket(c.bucket_id);
9315 if (!bucket || bucket->size() == 0) {
9316 return error::kInvalidArguments;
9318 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9319 Result* result = GetSharedMemoryAs<Result*>(
9320 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9321 if (!result) {
9322 return error::kOutOfBounds;
9324 // Check that the client initialized the result.
9325 if (*result != 0) {
9326 return error::kInvalidArguments;
9328 std::string feature_str;
9329 if (!bucket->GetAsString(&feature_str)) {
9330 return error::kInvalidArguments;
9333 // TODO(gman): make this some kind of table to function pointer thingy.
9334 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9335 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9336 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9337 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9338 // TODO(gman): decide how to remove the need for this const_cast.
9339 // I could make validators_ non const but that seems bad as this is the only
9340 // place it is needed. I could make some special friend class of validators
9341 // just to allow this to set them. That seems silly. I could refactor this
9342 // code to use the extension mechanism or the initialization attributes to
9343 // turn this feature on. Given that the only real point of this is to make
9344 // the conformance tests pass and given that there is lots of real work that
9345 // needs to be done it seems like refactoring for one to one of those
9346 // methods is a very low priority.
9347 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9348 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9349 force_webgl_glsl_validation_ = true;
9350 InitializeShaderTranslator();
9351 } else {
9352 return error::kNoError;
9355 *result = 1; // true.
9356 return error::kNoError;
9359 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9360 uint32 immediate_data_size,
9361 const cmds::GetRequestableExtensionsCHROMIUM& c) {
9362 Bucket* bucket = CreateBucket(c.bucket_id);
9363 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9364 info->Initialize(disallowed_features_);
9365 bucket->SetFromString(info->extensions().c_str());
9366 return error::kNoError;
9369 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9370 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
9371 Bucket* bucket = GetBucket(c.bucket_id);
9372 if (!bucket || bucket->size() == 0) {
9373 return error::kInvalidArguments;
9375 std::string feature_str;
9376 if (!bucket->GetAsString(&feature_str)) {
9377 return error::kInvalidArguments;
9380 bool desire_webgl_glsl_validation =
9381 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9382 bool desire_standard_derivatives = false;
9383 bool desire_frag_depth = false;
9384 bool desire_draw_buffers = false;
9385 bool desire_shader_texture_lod = false;
9386 if (force_webgl_glsl_validation_) {
9387 desire_standard_derivatives =
9388 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9389 desire_frag_depth =
9390 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9391 desire_draw_buffers =
9392 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9393 desire_shader_texture_lod =
9394 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
9397 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9398 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9399 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9400 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9401 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9402 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9403 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9404 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9405 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
9406 InitializeShaderTranslator();
9409 UpdateCapabilities();
9411 return error::kNoError;
9414 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9415 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
9416 GLuint count = c.count;
9417 uint32 pnames_size;
9418 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9419 return error::kOutOfBounds;
9421 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9422 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9423 if (pnames == NULL) {
9424 return error::kOutOfBounds;
9427 // We have to copy them since we use them twice so the client
9428 // can't change them between the time we validate them and the time we use
9429 // them.
9430 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9431 memcpy(enums.get(), pnames, pnames_size);
9433 // Count up the space needed for the result.
9434 uint32 num_results = 0;
9435 for (GLuint ii = 0; ii < count; ++ii) {
9436 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9437 if (num == 0) {
9438 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9439 "glGetMultipleCHROMIUM", enums[ii], "pname");
9440 return error::kNoError;
9442 // Num will never be more than 4.
9443 DCHECK_LE(num, 4u);
9444 if (!SafeAddUint32(num_results, num, &num_results)) {
9445 return error::kOutOfBounds;
9449 uint32 result_size = 0;
9450 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9451 return error::kOutOfBounds;
9454 if (result_size != static_cast<uint32>(c.size)) {
9455 LOCAL_SET_GL_ERROR(
9456 GL_INVALID_VALUE,
9457 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9458 return error::kNoError;
9461 GLint* results = GetSharedMemoryAs<GLint*>(
9462 c.results_shm_id, c.results_shm_offset, result_size);
9463 if (results == NULL) {
9464 return error::kOutOfBounds;
9467 // Check the results have been cleared in case the context was lost.
9468 for (uint32 ii = 0; ii < num_results; ++ii) {
9469 if (results[ii]) {
9470 return error::kInvalidArguments;
9474 // Get each result.
9475 GLint* start = results;
9476 for (GLuint ii = 0; ii < count; ++ii) {
9477 GLsizei num_written = 0;
9478 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9479 !GetHelper(enums[ii], results, &num_written)) {
9480 DoGetIntegerv(enums[ii], results);
9482 results += num_written;
9485 // Just to verify. Should this be a DCHECK?
9486 if (static_cast<uint32>(results - start) != num_results) {
9487 return error::kOutOfBounds;
9490 return error::kNoError;
9493 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9494 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
9495 GLuint program_id = static_cast<GLuint>(c.program);
9496 uint32 bucket_id = c.bucket_id;
9497 Bucket* bucket = CreateBucket(bucket_id);
9498 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9499 Program* program = NULL;
9500 program = GetProgram(program_id);
9501 if (!program || !program->IsValid()) {
9502 return error::kNoError;
9504 program->GetProgramInfo(program_manager(), bucket);
9505 return error::kNoError;
9508 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9509 switch (reset_status_) {
9510 case GL_NO_ERROR:
9511 // TODO(kbr): improve the precision of the error code in this case.
9512 // Consider delegating to context for error code if MakeCurrent fails.
9513 return error::kUnknown;
9514 case GL_GUILTY_CONTEXT_RESET_ARB:
9515 return error::kGuilty;
9516 case GL_INNOCENT_CONTEXT_RESET_ARB:
9517 return error::kInnocent;
9518 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9519 return error::kUnknown;
9522 NOTREACHED();
9523 return error::kUnknown;
9526 bool GLES2DecoderImpl::WasContextLost() {
9527 if (reset_status_ != GL_NO_ERROR) {
9528 return true;
9530 if (context_->WasAllocatedUsingRobustnessExtension()) {
9531 GLenum status = GL_NO_ERROR;
9532 if (has_robustness_extension_)
9533 status = glGetGraphicsResetStatusARB();
9534 if (status != GL_NO_ERROR) {
9535 // The graphics card was reset. Signal a lost context to the application.
9536 reset_status_ = status;
9537 reset_by_robustness_extension_ = true;
9538 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9539 << " context lost via ARB/EXT_robustness. Reset status = "
9540 << GLES2Util::GetStringEnum(status);
9541 return true;
9544 return false;
9547 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9548 return WasContextLost() && reset_by_robustness_extension_;
9551 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9552 // Only loses the context once.
9553 if (reset_status_ != GL_NO_ERROR) {
9554 return;
9557 // Marks this context as lost.
9558 reset_status_ = reset_status;
9559 current_decoder_error_ = error::kLostContext;
9562 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9563 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9564 return error::kUnknownCommand;
9567 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9568 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9569 group_->mailbox_manager()->PullTextureUpdates();
9570 if (wait_sync_point_callback_.is_null())
9571 return error::kNoError;
9573 return wait_sync_point_callback_.Run(c.sync_point) ?
9574 error::kNoError : error::kDeferCommandUntilLater;
9577 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9578 uint32 immediate_data_size, const cmds::DiscardBackbufferCHROMIUM& c) {
9579 if (surface_->DeferDraws())
9580 return error::kDeferCommandUntilLater;
9581 if (!surface_->SetBackbufferAllocation(false))
9582 return error::kLostContext;
9583 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9584 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9585 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9586 return error::kNoError;
9589 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9590 GLsizei n, const GLuint* client_ids) {
9591 for (GLsizei ii = 0; ii < n; ++ii) {
9592 if (query_manager_->GetQuery(client_ids[ii])) {
9593 return false;
9596 query_manager_->GenQueries(n, client_ids);
9597 return true;
9600 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9601 GLsizei n, const GLuint* client_ids) {
9602 for (GLsizei ii = 0; ii < n; ++ii) {
9603 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9604 if (query && !query->IsDeleted()) {
9605 ContextState::QueryMap::iterator it =
9606 state_.current_queries.find(query->target());
9607 if (it != state_.current_queries.end())
9608 state_.current_queries.erase(it);
9610 query->Destroy(true);
9612 query_manager_->RemoveQuery(client_ids[ii]);
9616 bool GLES2DecoderImpl::ProcessPendingQueries() {
9617 if (query_manager_.get() == NULL) {
9618 return false;
9620 if (!query_manager_->ProcessPendingQueries()) {
9621 current_decoder_error_ = error::kOutOfBounds;
9623 return query_manager_->HavePendingQueries();
9626 // Note that if there are no pending readpixels right now,
9627 // this function will call the callback immediately.
9628 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9629 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9630 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9631 } else {
9632 callback.Run();
9636 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9637 while (!pending_readpixel_fences_.empty() &&
9638 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9639 std::vector<base::Closure> callbacks =
9640 pending_readpixel_fences_.front()->callbacks;
9641 pending_readpixel_fences_.pop();
9642 for (size_t i = 0; i < callbacks.size(); i++) {
9643 callbacks[i].Run();
9648 bool GLES2DecoderImpl::HasMoreIdleWork() {
9649 return !pending_readpixel_fences_.empty() ||
9650 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9653 void GLES2DecoderImpl::PerformIdleWork() {
9654 ProcessPendingReadPixels();
9655 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9656 return;
9657 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9658 ProcessFinishedAsyncTransfers();
9661 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
9662 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
9663 GLenum target = static_cast<GLenum>(c.target);
9664 GLuint client_id = static_cast<GLuint>(c.id);
9665 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9666 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9668 switch (target) {
9669 case GL_COMMANDS_ISSUED_CHROMIUM:
9670 case GL_LATENCY_QUERY_CHROMIUM:
9671 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9672 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9673 case GL_GET_ERROR_QUERY_CHROMIUM:
9674 break;
9675 case GL_COMMANDS_COMPLETED_CHROMIUM:
9676 if (!features().chromium_sync_query) {
9677 LOCAL_SET_GL_ERROR(
9678 GL_INVALID_OPERATION, "glBeginQueryEXT",
9679 "not enabled for commands completed queries");
9680 return error::kNoError;
9682 break;
9683 default:
9684 if (!features().occlusion_query_boolean) {
9685 LOCAL_SET_GL_ERROR(
9686 GL_INVALID_OPERATION, "glBeginQueryEXT",
9687 "not enabled for occlusion queries");
9688 return error::kNoError;
9690 break;
9693 if (state_.current_queries.find(target) != state_.current_queries.end()) {
9694 LOCAL_SET_GL_ERROR(
9695 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9696 return error::kNoError;
9699 if (client_id == 0) {
9700 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9701 return error::kNoError;
9704 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9705 if (!query) {
9706 if (!query_manager_->IsValidQuery(client_id)) {
9707 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9708 "glBeginQueryEXT",
9709 "id not made by glGenQueriesEXT");
9710 return error::kNoError;
9712 query = query_manager_->CreateQuery(
9713 target, client_id, sync_shm_id, sync_shm_offset);
9716 if (query->target() != target) {
9717 LOCAL_SET_GL_ERROR(
9718 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9719 return error::kNoError;
9720 } else if (query->shm_id() != sync_shm_id ||
9721 query->shm_offset() != sync_shm_offset) {
9722 DLOG(ERROR) << "Shared memory used by query not the same as before";
9723 return error::kInvalidArguments;
9726 if (!query_manager_->BeginQuery(query)) {
9727 return error::kOutOfBounds;
9730 state_.current_queries[target] = query;
9731 return error::kNoError;
9734 error::Error GLES2DecoderImpl::HandleEndQueryEXT(
9735 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
9736 GLenum target = static_cast<GLenum>(c.target);
9737 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9738 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
9740 if (it == state_.current_queries.end()) {
9741 LOCAL_SET_GL_ERROR(
9742 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9743 return error::kNoError;
9746 QueryManager::Query* query = it->second.get();
9747 if (!query_manager_->EndQuery(query, submit_count)) {
9748 return error::kOutOfBounds;
9751 query_manager_->ProcessPendingTransferQueries();
9753 state_.current_queries.erase(it);
9754 return error::kNoError;
9757 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9758 GLsizei n, const GLuint* client_ids) {
9759 for (GLsizei ii = 0; ii < n; ++ii) {
9760 if (GetVertexAttribManager(client_ids[ii])) {
9761 return false;
9765 if (!features().native_vertex_array_object) {
9766 // Emulated VAO
9767 for (GLsizei ii = 0; ii < n; ++ii) {
9768 CreateVertexAttribManager(client_ids[ii], 0, true);
9770 } else {
9771 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9773 glGenVertexArraysOES(n, service_ids.get());
9774 for (GLsizei ii = 0; ii < n; ++ii) {
9775 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
9779 return true;
9782 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9783 GLsizei n, const GLuint* client_ids) {
9784 for (GLsizei ii = 0; ii < n; ++ii) {
9785 VertexAttribManager* vao =
9786 GetVertexAttribManager(client_ids[ii]);
9787 if (vao && !vao->IsDeleted()) {
9788 if (state_.vertex_attrib_manager.get() == vao) {
9789 DoBindVertexArrayOES(0);
9791 RemoveVertexAttribManager(client_ids[ii]);
9796 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9797 VertexAttribManager* vao = NULL;
9798 if (client_id != 0) {
9799 vao = GetVertexAttribManager(client_id);
9800 if (!vao) {
9801 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9802 // only allows names that have been previously generated. As such, we do
9803 // not generate new names here.
9804 LOCAL_SET_GL_ERROR(
9805 GL_INVALID_OPERATION,
9806 "glBindVertexArrayOES", "bad vertex array id.");
9807 current_decoder_error_ = error::kNoError;
9808 return;
9810 } else {
9811 vao = state_.default_vertex_attrib_manager.get();
9814 // Only set the VAO state if it's changed
9815 if (state_.vertex_attrib_manager.get() != vao) {
9816 state_.vertex_attrib_manager = vao;
9817 if (!features().native_vertex_array_object) {
9818 EmulateVertexArrayState();
9819 } else {
9820 GLuint service_id = vao->service_id();
9821 glBindVertexArrayOES(service_id);
9826 // Used when OES_vertex_array_object isn't natively supported
9827 void GLES2DecoderImpl::EmulateVertexArrayState() {
9828 // Setup the Vertex attribute state
9829 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9830 RestoreStateForAttrib(vv, true);
9833 // Setup the element buffer
9834 Buffer* element_array_buffer =
9835 state_.vertex_attrib_manager->element_array_buffer();
9836 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9837 element_array_buffer ? element_array_buffer->service_id() : 0);
9840 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9841 const VertexAttribManager* vao =
9842 GetVertexAttribManager(client_id);
9843 return vao && vao->IsValid() && !vao->IsDeleted();
9846 #if defined(OS_MACOSX)
9847 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9848 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9849 texture_id);
9850 if (it != texture_to_io_surface_map_.end()) {
9851 // Found a previous IOSurface bound to this texture; release it.
9852 IOSurfaceRef surface = it->second;
9853 CFRelease(surface);
9854 texture_to_io_surface_map_.erase(it);
9857 #endif
9859 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9860 GLenum target, GLsizei width, GLsizei height,
9861 GLuint io_surface_id, GLuint plane) {
9862 #if defined(OS_MACOSX)
9863 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
9864 LOCAL_SET_GL_ERROR(
9865 GL_INVALID_OPERATION,
9866 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9867 return;
9870 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9871 // This might be supported in the future, and if we could require
9872 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9873 // could delete a lot of code. For now, perform strict validation so we
9874 // know what's going on.
9875 LOCAL_SET_GL_ERROR(
9876 GL_INVALID_OPERATION,
9877 "glTexImageIOSurface2DCHROMIUM",
9878 "requires TEXTURE_RECTANGLE_ARB target");
9879 return;
9882 // Default target might be conceptually valid, but disallow it to avoid
9883 // accidents.
9884 TextureRef* texture_ref =
9885 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9886 if (!texture_ref) {
9887 LOCAL_SET_GL_ERROR(
9888 GL_INVALID_OPERATION,
9889 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9890 return;
9893 // Look up the new IOSurface. Note that because of asynchrony
9894 // between processes this might fail; during live resizing the
9895 // plugin process might allocate and release an IOSurface before
9896 // this process gets a chance to look it up. Hold on to any old
9897 // IOSurface in this case.
9898 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
9899 if (!surface) {
9900 LOCAL_SET_GL_ERROR(
9901 GL_INVALID_OPERATION,
9902 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9903 return;
9906 // Release any IOSurface previously bound to this texture.
9907 ReleaseIOSurfaceForTexture(texture_ref->service_id());
9909 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9910 texture_to_io_surface_map_.insert(
9911 std::make_pair(texture_ref->service_id(), surface));
9913 CGLContextObj context =
9914 static_cast<CGLContextObj>(context_->GetHandle());
9916 CGLError err = CGLTexImageIOSurface2D(
9917 context,
9918 target,
9919 GL_RGBA,
9920 width,
9921 height,
9922 GL_BGRA,
9923 GL_UNSIGNED_INT_8_8_8_8_REV,
9924 surface,
9925 plane);
9927 if (err != kCGLNoError) {
9928 LOCAL_SET_GL_ERROR(
9929 GL_INVALID_OPERATION,
9930 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9931 return;
9934 texture_manager()->SetLevelInfo(
9935 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
9936 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9938 #else
9939 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9940 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9941 #endif
9944 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9945 switch (internalformat) {
9946 case GL_RGB565:
9947 return GL_RGB;
9948 case GL_RGBA4:
9949 return GL_RGBA;
9950 case GL_RGB5_A1:
9951 return GL_RGBA;
9952 case GL_RGB8_OES:
9953 return GL_RGB;
9954 case GL_RGBA8_OES:
9955 return GL_RGBA;
9956 case GL_LUMINANCE8_ALPHA8_EXT:
9957 return GL_LUMINANCE_ALPHA;
9958 case GL_LUMINANCE8_EXT:
9959 return GL_LUMINANCE;
9960 case GL_ALPHA8_EXT:
9961 return GL_ALPHA;
9962 case GL_RGBA32F_EXT:
9963 return GL_RGBA;
9964 case GL_RGB32F_EXT:
9965 return GL_RGB;
9966 case GL_ALPHA32F_EXT:
9967 return GL_ALPHA;
9968 case GL_LUMINANCE32F_EXT:
9969 return GL_LUMINANCE;
9970 case GL_LUMINANCE_ALPHA32F_EXT:
9971 return GL_LUMINANCE_ALPHA;
9972 case GL_RGBA16F_EXT:
9973 return GL_RGBA;
9974 case GL_RGB16F_EXT:
9975 return GL_RGB;
9976 case GL_ALPHA16F_EXT:
9977 return GL_ALPHA;
9978 case GL_LUMINANCE16F_EXT:
9979 return GL_LUMINANCE;
9980 case GL_LUMINANCE_ALPHA16F_EXT:
9981 return GL_LUMINANCE_ALPHA;
9982 case GL_BGRA8_EXT:
9983 return GL_BGRA_EXT;
9984 default:
9985 return GL_NONE;
9989 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9990 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
9991 GLenum internal_format, GLenum dest_type) {
9992 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
9994 TextureRef* dest_texture_ref = GetTexture(dest_id);
9995 TextureRef* source_texture_ref = GetTexture(source_id);
9997 if (!source_texture_ref || !dest_texture_ref) {
9998 LOCAL_SET_GL_ERROR(
9999 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
10000 return;
10003 if (GL_TEXTURE_2D != target) {
10004 LOCAL_SET_GL_ERROR(
10005 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
10006 return;
10009 Texture* source_texture = source_texture_ref->texture();
10010 Texture* dest_texture = dest_texture_ref->texture();
10011 if (dest_texture->target() != GL_TEXTURE_2D ||
10012 (source_texture->target() != GL_TEXTURE_2D &&
10013 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
10014 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
10015 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10016 "glCopyTextureCHROMIUM",
10017 "invalid texture target binding");
10018 return;
10021 int source_width, source_height, dest_width, dest_height;
10023 gfx::GLImage* image =
10024 source_texture->GetLevelImage(source_texture->target(), 0);
10025 if (image) {
10026 gfx::Size size = image->GetSize();
10027 source_width = size.width();
10028 source_height = size.height();
10029 if (source_width <= 0 || source_height <= 0) {
10030 LOCAL_SET_GL_ERROR(
10031 GL_INVALID_VALUE,
10032 "glCopyTextureChromium", "invalid image size");
10033 return;
10035 } else {
10036 if (!source_texture->GetLevelSize(
10037 source_texture->target(), 0, &source_width, &source_height)) {
10038 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10039 "glCopyTextureChromium",
10040 "source texture has no level 0");
10041 return;
10044 // Check that this type of texture is allowed.
10045 if (!texture_manager()->ValidForTarget(
10046 source_texture->target(), level, source_width, source_height, 1)) {
10047 LOCAL_SET_GL_ERROR(
10048 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
10049 return;
10053 // Clear the source texture if necessary.
10054 if (!texture_manager()->ClearTextureLevel(
10055 this, source_texture_ref, source_texture->target(), 0)) {
10056 LOCAL_SET_GL_ERROR(
10057 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
10058 return;
10061 GLenum source_type = 0;
10062 GLenum source_internal_format = 0;
10063 source_texture->GetLevelType(
10064 source_texture->target(), 0, &source_type, &source_internal_format);
10066 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
10067 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
10068 // renderable on some platforms.
10069 bool valid_dest_format =
10070 internal_format == GL_RGB || internal_format == GL_RGBA;
10071 bool valid_source_format = source_internal_format == GL_ALPHA ||
10072 source_internal_format == GL_RGB ||
10073 source_internal_format == GL_RGBA ||
10074 source_internal_format == GL_LUMINANCE ||
10075 source_internal_format == GL_LUMINANCE_ALPHA ||
10076 source_internal_format == GL_BGRA_EXT;
10077 if (!valid_source_format || !valid_dest_format) {
10078 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10079 "glCopyTextureCHROMIUM",
10080 "invalid internal format");
10081 return;
10084 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
10085 // needed because it takes 10s of milliseconds to initialize.
10086 if (!copy_texture_CHROMIUM_.get()) {
10087 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10088 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
10089 copy_texture_CHROMIUM_->Initialize(this);
10090 RestoreCurrentFramebufferBindings();
10091 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
10092 return;
10095 GLenum dest_type_previous = dest_type;
10096 GLenum dest_internal_format = internal_format;
10097 bool dest_level_defined = dest_texture->GetLevelSize(
10098 GL_TEXTURE_2D, level, &dest_width, &dest_height);
10100 if (dest_level_defined) {
10101 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
10102 &dest_internal_format);
10105 // Resize the destination texture to the dimensions of the source texture.
10106 if (!dest_level_defined || dest_width != source_width ||
10107 dest_height != source_height ||
10108 dest_internal_format != internal_format ||
10109 dest_type_previous != dest_type) {
10110 // Ensure that the glTexImage2D succeeds.
10111 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10112 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
10113 glTexImage2D(
10114 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
10115 0, internal_format, dest_type, NULL);
10116 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
10117 if (error != GL_NO_ERROR) {
10118 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
10119 return;
10122 texture_manager()->SetLevelInfo(
10123 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
10124 source_height, 1, 0, internal_format, dest_type, true);
10125 } else {
10126 texture_manager()->SetLevelCleared(
10127 dest_texture_ref, GL_TEXTURE_2D, level, true);
10130 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
10131 ScopedModifyPixels modify(dest_texture_ref);
10133 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
10134 // before presenting.
10135 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
10136 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
10137 // instead of using default matrix crbug.com/226218.
10138 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
10139 0.0f, 1.0f, 0.0f, 0.0f,
10140 0.0f, 0.0f, 1.0f, 0.0f,
10141 0.0f, 0.0f, 0.0f, 1.0f};
10142 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
10143 this,
10144 source_texture->target(),
10145 source_texture->service_id(),
10146 dest_texture->service_id(),
10147 level,
10148 source_width,
10149 source_height,
10150 unpack_flip_y_,
10151 unpack_premultiply_alpha_,
10152 unpack_unpremultiply_alpha_,
10153 default_matrix);
10154 } else {
10155 copy_texture_CHROMIUM_->DoCopyTexture(this,
10156 source_texture->target(),
10157 source_texture->service_id(),
10158 source_internal_format,
10159 dest_texture->service_id(),
10160 level,
10161 internal_format,
10162 source_width,
10163 source_height,
10164 unpack_flip_y_,
10165 unpack_premultiply_alpha_,
10166 unpack_unpremultiply_alpha_);
10169 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
10172 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
10173 switch (internalformat) {
10174 case GL_RGB565:
10175 return GL_UNSIGNED_SHORT_5_6_5;
10176 case GL_RGBA4:
10177 return GL_UNSIGNED_SHORT_4_4_4_4;
10178 case GL_RGB5_A1:
10179 return GL_UNSIGNED_SHORT_5_5_5_1;
10180 case GL_RGB8_OES:
10181 return GL_UNSIGNED_BYTE;
10182 case GL_RGBA8_OES:
10183 return GL_UNSIGNED_BYTE;
10184 case GL_LUMINANCE8_ALPHA8_EXT:
10185 return GL_UNSIGNED_BYTE;
10186 case GL_LUMINANCE8_EXT:
10187 return GL_UNSIGNED_BYTE;
10188 case GL_ALPHA8_EXT:
10189 return GL_UNSIGNED_BYTE;
10190 case GL_RGBA32F_EXT:
10191 return GL_FLOAT;
10192 case GL_RGB32F_EXT:
10193 return GL_FLOAT;
10194 case GL_ALPHA32F_EXT:
10195 return GL_FLOAT;
10196 case GL_LUMINANCE32F_EXT:
10197 return GL_FLOAT;
10198 case GL_LUMINANCE_ALPHA32F_EXT:
10199 return GL_FLOAT;
10200 case GL_RGBA16F_EXT:
10201 return GL_HALF_FLOAT_OES;
10202 case GL_RGB16F_EXT:
10203 return GL_HALF_FLOAT_OES;
10204 case GL_ALPHA16F_EXT:
10205 return GL_HALF_FLOAT_OES;
10206 case GL_LUMINANCE16F_EXT:
10207 return GL_HALF_FLOAT_OES;
10208 case GL_LUMINANCE_ALPHA16F_EXT:
10209 return GL_HALF_FLOAT_OES;
10210 case GL_BGRA8_EXT:
10211 return GL_UNSIGNED_BYTE;
10212 default:
10213 return GL_NONE;
10217 void GLES2DecoderImpl::DoTexStorage2DEXT(
10218 GLenum target,
10219 GLint levels,
10220 GLenum internal_format,
10221 GLsizei width,
10222 GLsizei height) {
10223 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10224 "width", width, "height", height);
10225 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
10226 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
10227 LOCAL_SET_GL_ERROR(
10228 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
10229 return;
10231 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10232 &state_, target);
10233 if (!texture_ref) {
10234 LOCAL_SET_GL_ERROR(
10235 GL_INVALID_OPERATION,
10236 "glTexStorage2DEXT", "unknown texture for target");
10237 return;
10239 Texture* texture = texture_ref->texture();
10240 if (texture->IsAttachedToFramebuffer()) {
10241 framebuffer_state_.clear_state_dirty = true;
10243 if (texture->IsImmutable()) {
10244 LOCAL_SET_GL_ERROR(
10245 GL_INVALID_OPERATION,
10246 "glTexStorage2DEXT", "texture is immutable");
10247 return;
10250 GLenum format = ExtractFormatFromStorageFormat(internal_format);
10251 GLenum type = ExtractTypeFromStorageFormat(internal_format);
10254 GLsizei level_width = width;
10255 GLsizei level_height = height;
10256 uint32 estimated_size = 0;
10257 for (int ii = 0; ii < levels; ++ii) {
10258 uint32 level_size = 0;
10259 if (!GLES2Util::ComputeImageDataSizes(
10260 level_width, level_height, format, type, state_.unpack_alignment,
10261 &estimated_size, NULL, NULL) ||
10262 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
10263 LOCAL_SET_GL_ERROR(
10264 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
10265 return;
10267 level_width = std::max(1, level_width >> 1);
10268 level_height = std::max(1, level_height >> 1);
10270 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10271 LOCAL_SET_GL_ERROR(
10272 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
10273 return;
10277 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10278 glTexStorage2DEXT(target, levels, internal_format, width, height);
10279 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10280 if (error == GL_NO_ERROR) {
10281 GLsizei level_width = width;
10282 GLsizei level_height = height;
10283 for (int ii = 0; ii < levels; ++ii) {
10284 texture_manager()->SetLevelInfo(
10285 texture_ref, target, ii, format,
10286 level_width, level_height, 1, 0, format, type, false);
10287 level_width = std::max(1, level_width >> 1);
10288 level_height = std::max(1, level_height >> 1);
10290 texture->SetImmutable(true);
10294 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10295 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
10296 return error::kUnknownCommand;
10299 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10300 const GLbyte* data) {
10301 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10302 "context", logger_.GetLogPrefix(),
10303 "mailbox[0]", static_cast<unsigned char>(data[0]));
10305 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10306 &state_, target);
10307 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
10310 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
10311 GLenum target, const GLbyte* data) {
10312 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10313 "context", logger_.GetLogPrefix(),
10314 "mailbox[0]", static_cast<unsigned char>(data[0]));
10316 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
10317 target, data);
10320 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
10321 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
10322 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10323 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
10324 "mailbox that was not generated by "
10325 "GenMailboxCHROMIUM.";
10327 if (!texture_ref) {
10328 LOCAL_SET_GL_ERROR(
10329 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
10330 return;
10333 Texture* produced = texture_manager()->Produce(texture_ref);
10334 if (!produced) {
10335 LOCAL_SET_GL_ERROR(
10336 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
10337 return;
10340 if (produced->target() != target) {
10341 LOCAL_SET_GL_ERROR(
10342 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
10343 return;
10346 group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
10349 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10350 const GLbyte* data) {
10351 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10352 "context", logger_.GetLogPrefix(),
10353 "mailbox[0]", static_cast<unsigned char>(data[0]));
10354 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10355 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10356 "mailbox that was not generated by "
10357 "GenMailboxCHROMIUM.";
10359 scoped_refptr<TextureRef> texture_ref =
10360 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10361 if (!texture_ref.get()) {
10362 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10363 "glConsumeTextureCHROMIUM",
10364 "unknown texture for target");
10365 return;
10367 GLuint client_id = texture_ref->client_id();
10368 if (!client_id) {
10369 LOCAL_SET_GL_ERROR(
10370 GL_INVALID_OPERATION,
10371 "glConsumeTextureCHROMIUM", "unknown texture for target");
10372 return;
10374 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10375 if (!texture) {
10376 LOCAL_SET_GL_ERROR(
10377 GL_INVALID_OPERATION,
10378 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10379 return;
10381 if (texture->target() != target) {
10382 LOCAL_SET_GL_ERROR(
10383 GL_INVALID_OPERATION,
10384 "glConsumeTextureCHROMIUM", "invalid target");
10385 return;
10388 DeleteTexturesHelper(1, &client_id);
10389 texture_ref = texture_manager()->Consume(client_id, texture);
10390 glBindTexture(target, texture_ref->service_id());
10392 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10393 unit.bind_target = target;
10394 switch (target) {
10395 case GL_TEXTURE_2D:
10396 unit.bound_texture_2d = texture_ref;
10397 break;
10398 case GL_TEXTURE_CUBE_MAP:
10399 unit.bound_texture_cube_map = texture_ref;
10400 break;
10401 case GL_TEXTURE_EXTERNAL_OES:
10402 unit.bound_texture_external_oes = texture_ref;
10403 break;
10404 case GL_TEXTURE_RECTANGLE_ARB:
10405 unit.bound_texture_rectangle_arb = texture_ref;
10406 break;
10407 default:
10408 NOTREACHED(); // Validation should prevent us getting here.
10409 break;
10413 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10414 uint32_t immediate_data_size,
10415 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c) {
10416 GLenum target = static_cast<GLenum>(c.target);
10417 uint32_t data_size;
10418 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
10419 return error::kOutOfBounds;
10421 if (data_size > immediate_data_size) {
10422 return error::kOutOfBounds;
10424 const GLbyte* mailbox =
10425 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
10426 if (!validators_->texture_bind_target.IsValid(target)) {
10427 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10428 "glCreateAndConsumeTextureCHROMIUM", target, "target");
10429 return error::kNoError;
10431 if (mailbox == NULL) {
10432 return error::kOutOfBounds;
10434 uint32_t client_id = c.client_id;
10435 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
10436 return error::kNoError;
10439 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
10440 const GLbyte* data, GLuint client_id) {
10441 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
10442 "context", logger_.GetLogPrefix(),
10443 "mailbox[0]", static_cast<unsigned char>(data[0]));
10444 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10445 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
10446 "passed a mailbox that was not "
10447 "generated by GenMailboxCHROMIUM.";
10449 TextureRef* texture_ref = GetTexture(client_id);
10450 if (texture_ref) {
10451 LOCAL_SET_GL_ERROR(
10452 GL_INVALID_OPERATION,
10453 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
10454 return;
10456 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10457 if (!texture) {
10458 LOCAL_SET_GL_ERROR(
10459 GL_INVALID_OPERATION,
10460 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
10461 return;
10463 if (texture->target() != target) {
10464 LOCAL_SET_GL_ERROR(
10465 GL_INVALID_OPERATION,
10466 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
10467 return;
10470 IdAllocatorInterface* id_allocator =
10471 group_->GetIdAllocator(id_namespaces::kTextures);
10472 id_allocator->MarkAsUsed(client_id);
10474 texture_ref = texture_manager()->Consume(client_id, texture);
10477 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10478 GLsizei length, const GLchar* marker) {
10479 if (!marker) {
10480 marker = "";
10482 debug_marker_manager_.SetMarker(
10483 length ? std::string(marker, length) : std::string(marker));
10486 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10487 GLsizei length, const GLchar* marker) {
10488 if (!marker) {
10489 marker = "";
10491 std::string name = length ? std::string(marker, length) : std::string(marker);
10492 debug_marker_manager_.PushGroup(name);
10493 gpu_tracer_->Begin(name, kTraceGroupMarker);
10496 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10497 debug_marker_manager_.PopGroup();
10498 gpu_tracer_->End(kTraceGroupMarker);
10501 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10502 GLenum target, GLint image_id) {
10503 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10505 if (target == GL_TEXTURE_CUBE_MAP) {
10506 LOCAL_SET_GL_ERROR(
10507 GL_INVALID_ENUM,
10508 "glBindTexImage2DCHROMIUM", "invalid target");
10509 return;
10512 // Default target might be conceptually valid, but disallow it to avoid
10513 // accidents.
10514 TextureRef* texture_ref =
10515 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10516 if (!texture_ref) {
10517 LOCAL_SET_GL_ERROR(
10518 GL_INVALID_OPERATION,
10519 "glBindTexImage2DCHROMIUM", "no texture bound");
10520 return;
10523 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10524 if (!gl_image) {
10525 LOCAL_SET_GL_ERROR(
10526 GL_INVALID_OPERATION,
10527 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10528 return;
10532 ScopedGLErrorSuppressor suppressor(
10533 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10534 if (!gl_image->BindTexImage(target)) {
10535 LOCAL_SET_GL_ERROR(
10536 GL_INVALID_OPERATION,
10537 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10538 return;
10542 gfx::Size size = gl_image->GetSize();
10543 texture_manager()->SetLevelInfo(
10544 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10545 GL_RGBA, GL_UNSIGNED_BYTE, true);
10546 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10549 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10550 GLenum target, GLint image_id) {
10551 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10553 // Default target might be conceptually valid, but disallow it to avoid
10554 // accidents.
10555 TextureRef* texture_ref =
10556 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10557 if (!texture_ref) {
10558 LOCAL_SET_GL_ERROR(
10559 GL_INVALID_OPERATION,
10560 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10561 return;
10564 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10565 if (!gl_image) {
10566 LOCAL_SET_GL_ERROR(
10567 GL_INVALID_OPERATION,
10568 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10569 return;
10572 // Do nothing when image is not currently bound.
10573 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10574 return;
10577 ScopedGLErrorSuppressor suppressor(
10578 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10579 gl_image->ReleaseTexImage(target);
10582 texture_manager()->SetLevelInfo(
10583 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10584 GL_RGBA, GL_UNSIGNED_BYTE, false);
10587 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10588 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10589 Bucket* bucket = GetBucket(c.bucket_id);
10590 if (!bucket || bucket->size() == 0) {
10591 return error::kInvalidArguments;
10593 std::string command_name;
10594 if (!bucket->GetAsString(&command_name)) {
10595 return error::kInvalidArguments;
10597 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10598 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
10599 LOCAL_SET_GL_ERROR(
10600 GL_INVALID_OPERATION,
10601 "glTraceBeginCHROMIUM", "unable to create begin trace");
10602 return error::kNoError;
10604 return error::kNoError;
10607 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10608 if (gpu_tracer_->CurrentName().empty()) {
10609 LOCAL_SET_GL_ERROR(
10610 GL_INVALID_OPERATION,
10611 "glTraceEndCHROMIUM", "no trace begin found");
10612 return;
10614 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10615 gpu_tracer_->End(kTraceCHROMIUM);
10618 void GLES2DecoderImpl::DoDrawBuffersEXT(
10619 GLsizei count, const GLenum* bufs) {
10620 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10621 LOCAL_SET_GL_ERROR(
10622 GL_INVALID_VALUE,
10623 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10624 return;
10627 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10628 if (framebuffer) {
10629 for (GLsizei i = 0; i < count; ++i) {
10630 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10631 bufs[i] != GL_NONE) {
10632 LOCAL_SET_GL_ERROR(
10633 GL_INVALID_OPERATION,
10634 "glDrawBuffersEXT",
10635 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10636 return;
10639 glDrawBuffersARB(count, bufs);
10640 framebuffer->SetDrawBuffers(count, bufs);
10641 } else { // backbuffer
10642 if (count > 1 ||
10643 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10644 LOCAL_SET_GL_ERROR(
10645 GL_INVALID_OPERATION,
10646 "glDrawBuffersEXT",
10647 "more than one buffer or bufs not GL_NONE or GL_BACK");
10648 return;
10650 GLenum mapped_buf = bufs[0];
10651 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10652 bufs[0] == GL_BACK) {
10653 mapped_buf = GL_COLOR_ATTACHMENT0;
10655 glDrawBuffersARB(count, &mapped_buf);
10656 group_->set_draw_buffer(bufs[0]);
10660 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
10661 group_->LoseContexts(other);
10662 reset_status_ = current;
10663 current_decoder_error_ = error::kLostContext;
10666 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
10667 const GLfloat* matrix) {
10668 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
10669 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
10670 if (!features().chromium_path_rendering) {
10671 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10672 "glMatrixLoadfCHROMIUM",
10673 "function not available");
10674 return;
10677 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
10678 ? state_.projection_matrix
10679 : state_.modelview_matrix;
10680 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
10681 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
10682 // since the values of the _NV and _CHROMIUM tokens match.
10683 glMatrixLoadfEXT(matrix_mode, matrix);
10686 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
10687 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
10688 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
10690 if (!features().chromium_path_rendering) {
10691 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10692 "glMatrixLoadIdentityCHROMIUM",
10693 "function not available");
10694 return;
10697 static GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
10698 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
10699 0.0f, 0.0f, 0.0f, 1.0f};
10701 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
10702 ? state_.projection_matrix
10703 : state_.modelview_matrix;
10704 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
10705 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
10706 // since the values of the _NV and _CHROMIUM tokens match.
10707 glMatrixLoadIdentityEXT(matrix_mode);
10710 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10711 const char* function_name,
10712 TextureRef* texture_ref,
10713 GLenum target,
10714 GLint level,
10715 const void * data) {
10716 // We only support async uploads to 2D textures for now.
10717 if (GL_TEXTURE_2D != target) {
10718 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10719 return false;
10721 // We only support uploads to level zero for now.
10722 if (level != 0) {
10723 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10724 return false;
10726 // A transfer buffer must be bound, even for asyncTexImage2D.
10727 if (data == NULL) {
10728 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10729 return false;
10731 // We only support one async transfer in progress.
10732 if (!texture_ref ||
10733 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10734 LOCAL_SET_GL_ERROR(
10735 GL_INVALID_OPERATION,
10736 function_name, "transfer already in progress");
10737 return false;
10739 return true;
10742 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
10743 uint32 async_upload_token,
10744 uint32 sync_data_shm_id,
10745 uint32 sync_data_shm_offset) {
10746 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
10747 if (!buffer.get() ||
10748 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
10749 return base::Closure();
10751 AsyncMemoryParams mem_params(buffer,
10752 sync_data_shm_offset,
10753 sizeof(AsyncUploadSync));
10755 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
10756 new AsyncUploadTokenCompletionObserver(async_upload_token));
10758 return base::Bind(
10759 &AsyncPixelTransferManager::AsyncNotifyCompletion,
10760 base::Unretained(GetAsyncPixelTransferManager()),
10761 mem_params,
10762 observer);
10765 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10766 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10767 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10768 GLenum target = static_cast<GLenum>(c.target);
10769 GLint level = static_cast<GLint>(c.level);
10770 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10771 GLsizei width = static_cast<GLsizei>(c.width);
10772 GLsizei height = static_cast<GLsizei>(c.height);
10773 GLint border = static_cast<GLint>(c.border);
10774 GLenum format = static_cast<GLenum>(c.format);
10775 GLenum type = static_cast<GLenum>(c.type);
10776 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10777 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10778 uint32 pixels_size;
10779 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
10780 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
10781 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10783 base::ScopedClosureRunner scoped_completion_callback;
10784 if (async_upload_token) {
10785 base::Closure completion_closure =
10786 AsyncUploadTokenCompletionClosure(async_upload_token,
10787 sync_data_shm_id,
10788 sync_data_shm_offset);
10789 if (completion_closure.is_null())
10790 return error::kInvalidArguments;
10792 scoped_completion_callback.Reset(completion_closure);
10795 // TODO(epenner): Move this and copies of this memory validation
10796 // into ValidateTexImage2D step.
10797 if (!GLES2Util::ComputeImageDataSizes(
10798 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10799 NULL)) {
10800 return error::kOutOfBounds;
10802 const void* pixels = NULL;
10803 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10804 pixels = GetSharedMemoryAs<const void*>(
10805 pixels_shm_id, pixels_shm_offset, pixels_size);
10806 if (!pixels) {
10807 return error::kOutOfBounds;
10811 TextureManager::DoTextImage2DArguments args = {
10812 target, level, internal_format, width, height, border, format, type,
10813 pixels, pixels_size};
10814 TextureRef* texture_ref;
10815 // All the normal glTexSubImage2D validation.
10816 if (!texture_manager()->ValidateTexImage2D(
10817 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
10818 return error::kNoError;
10821 // Extra async validation.
10822 Texture* texture = texture_ref->texture();
10823 if (!ValidateAsyncTransfer(
10824 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
10825 return error::kNoError;
10827 // Don't allow async redefinition of a textures.
10828 if (texture->IsDefined()) {
10829 LOCAL_SET_GL_ERROR(
10830 GL_INVALID_OPERATION,
10831 "glAsyncTexImage2DCHROMIUM", "already defined");
10832 return error::kNoError;
10835 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10836 LOCAL_SET_GL_ERROR(
10837 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10838 return error::kNoError;
10841 // Setup the parameters.
10842 AsyncTexImage2DParams tex_params = {
10843 target, level, static_cast<GLenum>(internal_format),
10844 width, height, border, format, type};
10845 AsyncMemoryParams mem_params(
10846 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
10848 // Set up the async state if needed, and make the texture
10849 // immutable so the async state stays valid. The level info
10850 // is set up lazily when the transfer completes.
10851 AsyncPixelTransferDelegate* delegate =
10852 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10853 tex_params);
10854 texture->SetImmutable(true);
10856 delegate->AsyncTexImage2D(
10857 tex_params,
10858 mem_params,
10859 base::Bind(&TextureManager::SetLevelInfoFromParams,
10860 // The callback is only invoked if the transfer delegate still
10861 // exists, which implies through manager->texture_ref->state
10862 // ownership that both of these pointers are valid.
10863 base::Unretained(texture_manager()),
10864 base::Unretained(texture_ref),
10865 tex_params));
10866 return error::kNoError;
10869 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10870 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10871 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10872 GLenum target = static_cast<GLenum>(c.target);
10873 GLint level = static_cast<GLint>(c.level);
10874 GLint xoffset = static_cast<GLint>(c.xoffset);
10875 GLint yoffset = static_cast<GLint>(c.yoffset);
10876 GLsizei width = static_cast<GLsizei>(c.width);
10877 GLsizei height = static_cast<GLsizei>(c.height);
10878 GLenum format = static_cast<GLenum>(c.format);
10879 GLenum type = static_cast<GLenum>(c.type);
10880 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
10881 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
10882 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10884 base::ScopedClosureRunner scoped_completion_callback;
10885 if (async_upload_token) {
10886 base::Closure completion_closure =
10887 AsyncUploadTokenCompletionClosure(async_upload_token,
10888 sync_data_shm_id,
10889 sync_data_shm_offset);
10890 if (completion_closure.is_null())
10891 return error::kInvalidArguments;
10893 scoped_completion_callback.Reset(completion_closure);
10896 // TODO(epenner): Move this and copies of this memory validation
10897 // into ValidateTexSubImage2D step.
10898 uint32 data_size;
10899 if (!GLES2Util::ComputeImageDataSizes(
10900 width, height, format, type, state_.unpack_alignment, &data_size,
10901 NULL, NULL)) {
10902 return error::kOutOfBounds;
10904 const void* pixels = GetSharedMemoryAs<const void*>(
10905 c.data_shm_id, c.data_shm_offset, data_size);
10907 // All the normal glTexSubImage2D validation.
10908 error::Error error = error::kNoError;
10909 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10910 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10911 return error;
10914 // Extra async validation.
10915 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10916 &state_, target);
10917 Texture* texture = texture_ref->texture();
10918 if (!ValidateAsyncTransfer(
10919 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
10920 return error::kNoError;
10922 // Guarantee async textures are always 'cleared' as follows:
10923 // - AsyncTexImage2D can not redefine an existing texture
10924 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10925 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10926 // - Textures become immutable after an async call.
10927 // This way we know in all cases that an async texture is always clear.
10928 if (!texture->SafeToRenderFrom()) {
10929 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10930 target, level)) {
10931 LOCAL_SET_GL_ERROR(
10932 GL_OUT_OF_MEMORY,
10933 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10934 return error::kNoError;
10938 // Setup the parameters.
10939 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
10940 width, height, format, type};
10941 AsyncMemoryParams mem_params(
10942 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
10943 AsyncPixelTransferDelegate* delegate =
10944 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10945 if (!delegate) {
10946 // TODO(epenner): We may want to enforce exclusive use
10947 // of async APIs in which case this should become an error,
10948 // (the texture should have been async defined).
10949 AsyncTexImage2DParams define_params = {target, level,
10950 0, 0, 0, 0, 0, 0};
10951 texture->GetLevelSize(target, level, &define_params.width,
10952 &define_params.height);
10953 texture->GetLevelType(target, level, &define_params.type,
10954 &define_params.internal_format);
10955 // Set up the async state if needed, and make the texture
10956 // immutable so the async state stays valid.
10957 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
10958 texture_ref, define_params);
10959 texture->SetImmutable(true);
10962 delegate->AsyncTexSubImage2D(tex_params, mem_params);
10963 return error::kNoError;
10966 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10967 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10968 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10969 GLenum target = static_cast<GLenum>(c.target);
10971 if (GL_TEXTURE_2D != target) {
10972 LOCAL_SET_GL_ERROR(
10973 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10974 return error::kNoError;
10976 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10977 &state_, target);
10978 if (!texture_ref) {
10979 LOCAL_SET_GL_ERROR(
10980 GL_INVALID_OPERATION,
10981 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10982 return error::kNoError;
10984 AsyncPixelTransferDelegate* delegate =
10985 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10986 if (!delegate) {
10987 LOCAL_SET_GL_ERROR(
10988 GL_INVALID_OPERATION,
10989 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10990 return error::kNoError;
10992 delegate->WaitForTransferCompletion();
10993 ProcessFinishedAsyncTransfers();
10994 return error::kNoError;
10997 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
10998 uint32 immediate_data_size, const cmds::WaitAllAsyncTexImage2DCHROMIUM& c) {
10999 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11001 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
11002 ProcessFinishedAsyncTransfers();
11003 return error::kNoError;
11006 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
11007 TextureRef* texture_ref) {
11008 Texture* texture = texture_ref->texture();
11009 DoDidUseTexImageIfNeeded(texture, texture->target());
11012 void GLES2DecoderImpl::OnOutOfMemoryError() {
11013 if (lose_context_when_out_of_memory_) {
11014 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
11015 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB);
11019 // Include the auto-generated part of this file. We split this because it means
11020 // we can easily edit the non-auto generated parts right here in this file
11021 // instead of having to edit some template or the code generator.
11022 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
11024 } // namespace gles2
11025 } // namespace gpu