Performance histograms for extension content verification
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob02ac2f68eff5d11c63625616e781cedb442ce94b
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/memory/scoped_ptr.h"
23 #include "base/numerics/safe_math.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_split.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/id_allocator.h"
32 #include "gpu/command_buffer/common/mailbox.h"
33 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
35 #include "gpu/command_buffer/service/buffer_manager.h"
36 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
37 #include "gpu/command_buffer/service/context_group.h"
38 #include "gpu/command_buffer/service/context_state.h"
39 #include "gpu/command_buffer/service/error_state.h"
40 #include "gpu/command_buffer/service/feature_info.h"
41 #include "gpu/command_buffer/service/framebuffer_manager.h"
42 #include "gpu/command_buffer/service/gl_utils.h"
43 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
44 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
45 #include "gpu/command_buffer/service/gpu_state_tracer.h"
46 #include "gpu/command_buffer/service/gpu_switches.h"
47 #include "gpu/command_buffer/service/gpu_tracer.h"
48 #include "gpu/command_buffer/service/image_manager.h"
49 #include "gpu/command_buffer/service/mailbox_manager.h"
50 #include "gpu/command_buffer/service/memory_tracking.h"
51 #include "gpu/command_buffer/service/program_manager.h"
52 #include "gpu/command_buffer/service/query_manager.h"
53 #include "gpu/command_buffer/service/renderbuffer_manager.h"
54 #include "gpu/command_buffer/service/shader_manager.h"
55 #include "gpu/command_buffer/service/shader_translator.h"
56 #include "gpu/command_buffer/service/shader_translator_cache.h"
57 #include "gpu/command_buffer/service/texture_manager.h"
58 #include "gpu/command_buffer/service/vertex_array_manager.h"
59 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
60 #include "third_party/smhasher/src/City.h"
61 #include "ui/gl/gl_bindings.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 } // namespace
158 class GLES2DecoderImpl;
160 // Local versions of the SET_GL_ERROR macros
161 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
162 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
163 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
164 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
165 function_name, value, label)
166 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
167 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
168 function_name, pname)
169 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
170 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
171 function_name)
172 #define LOCAL_PEEK_GL_ERROR(function_name) \
173 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
174 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
175 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
176 #define LOCAL_PERFORMANCE_WARNING(msg) \
177 PerformanceWarning(__FILE__, __LINE__, msg)
178 #define LOCAL_RENDER_WARNING(msg) \
179 RenderWarning(__FILE__, __LINE__, msg)
181 // Check that certain assumptions the code makes are true. There are places in
182 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
183 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
184 // a few others) are 32bits. If they are not 32bits the code will have to change
185 // to call those GL functions with service side memory and then copy the results
186 // to shared memory, converting the sizes.
187 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
188 GLint_not_same_size_as_uint32);
189 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
190 GLint_not_same_size_as_uint32);
191 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
192 GLfloat_not_same_size_as_float);
194 // TODO(kbr): the use of this anonymous namespace core dumps the
195 // linker on Mac OS X 10.6 when the symbol ordering file is used
196 // namespace {
198 // Returns the address of the first byte after a struct.
199 template <typename T>
200 const void* AddressAfterStruct(const T& pod) {
201 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
204 // Returns the address of the frst byte after the struct or NULL if size >
205 // immediate_data_size.
206 template <typename RETURN_TYPE, typename COMMAND_TYPE>
207 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
208 uint32 size,
209 uint32 immediate_data_size) {
210 return (size <= immediate_data_size) ?
211 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
212 NULL;
215 // Computes the data size for certain gl commands like glUniform.
216 bool ComputeDataSize(
217 GLuint count,
218 size_t size,
219 unsigned int elements_per_unit,
220 uint32* dst) {
221 uint32 value;
222 if (!SafeMultiplyUint32(count, size, &value)) {
223 return false;
225 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
226 return false;
228 *dst = value;
229 return true;
232 // A struct to hold info about each command.
233 struct CommandInfo {
234 uint8 arg_flags; // How to handle the arguments for this command
235 uint8 cmd_flags; // How to handle this command
236 uint16 arg_count; // How many arguments are expected for this command.
239 // cmds::name::cmd_flags,
240 // A table of CommandInfo for all the commands.
241 const CommandInfo g_command_info[] = {
242 #define GLES2_CMD_OP(name) { \
243 cmds::name::kArgFlags, \
244 cmds::name::cmd_flags, \
245 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */
247 GLES2_COMMAND_LIST(GLES2_CMD_OP)
249 #undef GLES2_CMD_OP
252 // Return true if a character belongs to the ASCII subset as defined in
253 // GLSL ES 1.0 spec section 3.1.
254 static bool CharacterIsValidForGLES(unsigned char c) {
255 // Printing characters are valid except " $ ` @ \ ' DEL.
256 if (c >= 32 && c <= 126 &&
257 c != '"' &&
258 c != '$' &&
259 c != '`' &&
260 c != '@' &&
261 c != '\\' &&
262 c != '\'') {
263 return true;
265 // Horizontal tab, line feed, vertical tab, form feed, carriage return
266 // are also valid.
267 if (c >= 9 && c <= 13) {
268 return true;
271 return false;
274 static bool StringIsValidForGLES(const char* str) {
275 for (; *str; ++str) {
276 if (!CharacterIsValidForGLES(*str)) {
277 return false;
280 return true;
283 // This class prevents any GL errors that occur when it is in scope from
284 // being reported to the client.
285 class ScopedGLErrorSuppressor {
286 public:
287 explicit ScopedGLErrorSuppressor(
288 const char* function_name, ErrorState* error_state);
289 ~ScopedGLErrorSuppressor();
290 private:
291 const char* function_name_;
292 ErrorState* error_state_;
293 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
296 // Temporarily changes a decoder's bound texture and restore it when this
297 // object goes out of scope. Also temporarily switches to using active texture
298 // unit zero in case the client has changed that to something invalid.
299 class ScopedTextureBinder {
300 public:
301 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
302 ~ScopedTextureBinder();
304 private:
305 ContextState* state_;
306 GLenum target_;
307 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
310 // Temporarily changes a decoder's bound render buffer and restore it when this
311 // object goes out of scope.
312 class ScopedRenderBufferBinder {
313 public:
314 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
315 ~ScopedRenderBufferBinder();
317 private:
318 ContextState* state_;
319 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
322 // Temporarily changes a decoder's bound frame buffer and restore it when this
323 // object goes out of scope.
324 class ScopedFrameBufferBinder {
325 public:
326 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
327 ~ScopedFrameBufferBinder();
329 private:
330 GLES2DecoderImpl* decoder_;
331 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
334 // Temporarily changes a decoder's bound frame buffer to a resolved version of
335 // the multisampled offscreen render buffer if that buffer is multisampled, and,
336 // if it is bound or enforce_internal_framebuffer is true. If internal is
337 // true, the resolved framebuffer is not visible to the parent.
338 class ScopedResolvedFrameBufferBinder {
339 public:
340 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
341 bool enforce_internal_framebuffer,
342 bool internal);
343 ~ScopedResolvedFrameBufferBinder();
345 private:
346 GLES2DecoderImpl* decoder_;
347 bool resolve_and_bind_;
348 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
351 class ScopedModifyPixels {
352 public:
353 explicit ScopedModifyPixels(TextureRef* ref);
354 ~ScopedModifyPixels();
356 private:
357 TextureRef* ref_;
360 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
361 if (ref_)
362 ref_->texture()->OnWillModifyPixels();
365 ScopedModifyPixels::~ScopedModifyPixels() {
366 if (ref_)
367 ref_->texture()->OnDidModifyPixels();
370 class ScopedRenderTo {
371 public:
372 explicit ScopedRenderTo(Framebuffer* framebuffer);
373 ~ScopedRenderTo();
375 private:
376 const Framebuffer* framebuffer_;
379 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
380 : framebuffer_(framebuffer) {
381 if (framebuffer)
382 framebuffer_->OnWillRenderTo();
385 ScopedRenderTo::~ScopedRenderTo() {
386 if (framebuffer_)
387 framebuffer_->OnDidRenderTo();
390 // Encapsulates an OpenGL texture.
391 class BackTexture {
392 public:
393 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
394 ~BackTexture();
396 // Create a new render texture.
397 void Create();
399 // Set the initial size and format of a render texture or resize it.
400 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
402 // Copy the contents of the currently bound frame buffer.
403 void Copy(const gfx::Size& size, GLenum format);
405 // Destroy the render texture. This must be explicitly called before
406 // destroying this object.
407 void Destroy();
409 // Invalidate the texture. This can be used when a context is lost and it is
410 // not possible to make it current in order to free the resource.
411 void Invalidate();
413 GLuint id() const {
414 return id_;
417 gfx::Size size() const {
418 return size_;
421 private:
422 MemoryTypeTracker memory_tracker_;
423 ContextState* state_;
424 size_t bytes_allocated_;
425 GLuint id_;
426 gfx::Size size_;
427 DISALLOW_COPY_AND_ASSIGN(BackTexture);
430 // Encapsulates an OpenGL render buffer of any format.
431 class BackRenderbuffer {
432 public:
433 explicit BackRenderbuffer(
434 RenderbufferManager* renderbuffer_manager,
435 MemoryTracker* memory_tracker,
436 ContextState* state);
437 ~BackRenderbuffer();
439 // Create a new render buffer.
440 void Create();
442 // Set the initial size and format of a render buffer or resize it.
443 bool AllocateStorage(const FeatureInfo* feature_info,
444 const gfx::Size& size,
445 GLenum format,
446 GLsizei samples);
448 // Destroy the render buffer. This must be explicitly called before destroying
449 // this object.
450 void Destroy();
452 // Invalidate the render buffer. This can be used when a context is lost and
453 // it is not possible to make it current in order to free the resource.
454 void Invalidate();
456 GLuint id() const {
457 return id_;
460 private:
461 RenderbufferManager* renderbuffer_manager_;
462 MemoryTypeTracker memory_tracker_;
463 ContextState* state_;
464 size_t bytes_allocated_;
465 GLuint id_;
466 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
469 // Encapsulates an OpenGL frame buffer.
470 class BackFramebuffer {
471 public:
472 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
473 ~BackFramebuffer();
475 // Create a new frame buffer.
476 void Create();
478 // Attach a color render buffer to a frame buffer.
479 void AttachRenderTexture(BackTexture* texture);
481 // Attach a render buffer to a frame buffer. Note that this unbinds any
482 // currently bound frame buffer.
483 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
485 // Destroy the frame buffer. This must be explicitly called before destroying
486 // this object.
487 void Destroy();
489 // Invalidate the frame buffer. This can be used when a context is lost and it
490 // is not possible to make it current in order to free the resource.
491 void Invalidate();
493 // See glCheckFramebufferStatusEXT.
494 GLenum CheckStatus();
496 GLuint id() const {
497 return id_;
500 private:
501 GLES2DecoderImpl* decoder_;
502 GLuint id_;
503 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
506 struct FenceCallback {
507 explicit FenceCallback()
508 : fence(gfx::GLFence::Create()) {
509 DCHECK(fence);
511 std::vector<base::Closure> callbacks;
512 scoped_ptr<gfx::GLFence> fence;
515 class AsyncUploadTokenCompletionObserver
516 : public AsyncPixelTransferCompletionObserver {
517 public:
518 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
519 : async_upload_token_(async_upload_token) {
522 virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE {
523 DCHECK(mem_params.buffer());
524 void* data = mem_params.GetDataAddress();
525 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
526 sync->SetAsyncUploadToken(async_upload_token_);
529 private:
530 virtual ~AsyncUploadTokenCompletionObserver() {
533 uint32 async_upload_token_;
535 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
538 // } // anonymous namespace.
540 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
541 uint32* service_texture_id) {
542 return false;
545 GLES2Decoder::GLES2Decoder()
546 : initialized_(false),
547 debug_(false),
548 log_commands_(false) {
551 GLES2Decoder::~GLES2Decoder() {
554 void GLES2Decoder::BeginDecoding() {}
556 void GLES2Decoder::EndDecoding() {}
558 // This class implements GLES2Decoder so we don't have to expose all the GLES2
559 // cmd stuff to outside this class.
560 class GLES2DecoderImpl : public GLES2Decoder,
561 public FramebufferManager::TextureDetachObserver,
562 public ErrorStateClient {
563 public:
564 explicit GLES2DecoderImpl(ContextGroup* group);
565 virtual ~GLES2DecoderImpl();
567 // Overridden from AsyncAPIInterface.
568 virtual Error DoCommand(unsigned int command,
569 unsigned int arg_count,
570 const void* args) OVERRIDE;
572 // Overridden from AsyncAPIInterface.
573 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
575 // Overridden from GLES2Decoder.
576 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
577 const scoped_refptr<gfx::GLContext>& context,
578 bool offscreen,
579 const gfx::Size& size,
580 const DisallowedFeatures& disallowed_features,
581 const std::vector<int32>& attribs) OVERRIDE;
582 virtual void Destroy(bool have_context) OVERRIDE;
583 virtual void SetSurface(
584 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
585 virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
586 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
587 void UpdateParentTextureInfo();
588 virtual bool MakeCurrent() OVERRIDE;
589 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
590 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
591 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
592 virtual Capabilities GetCapabilities() OVERRIDE;
593 virtual void RestoreState(const ContextState* prev_state) const OVERRIDE;
595 virtual void RestoreActiveTexture() const OVERRIDE {
596 state_.RestoreActiveTexture();
598 virtual void RestoreAllTextureUnitBindings(
599 const ContextState* prev_state) const OVERRIDE {
600 state_.RestoreAllTextureUnitBindings(prev_state);
602 virtual void RestoreActiveTextureUnitBinding(
603 unsigned int target) const OVERRIDE {
604 state_.RestoreActiveTextureUnitBinding(target);
606 virtual void RestoreBufferBindings() const OVERRIDE {
607 state_.RestoreBufferBindings();
609 virtual void RestoreGlobalState() const OVERRIDE {
610 state_.RestoreGlobalState(NULL);
612 virtual void RestoreProgramBindings() const OVERRIDE {
613 state_.RestoreProgramBindings();
615 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
616 state_.RestoreTextureUnitBindings(unit, NULL);
618 virtual void RestoreFramebufferBindings() const OVERRIDE;
619 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
621 virtual void ClearAllAttributes() const OVERRIDE;
622 virtual void RestoreAllAttributes() const OVERRIDE;
624 virtual QueryManager* GetQueryManager() OVERRIDE {
625 return query_manager_.get();
627 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
628 return vertex_array_manager_.get();
630 virtual bool ProcessPendingQueries() OVERRIDE;
631 virtual bool HasMoreIdleWork() OVERRIDE;
632 virtual void PerformIdleWork() OVERRIDE;
634 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
636 virtual void SetResizeCallback(
637 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
639 virtual Logger* GetLogger() OVERRIDE;
641 virtual void BeginDecoding() OVERRIDE;
642 virtual void EndDecoding() OVERRIDE;
644 virtual ErrorState* GetErrorState() OVERRIDE;
645 virtual const ContextState* GetContextState() OVERRIDE { return &state_; }
647 virtual void SetShaderCacheCallback(
648 const ShaderCacheCallback& callback) OVERRIDE;
649 virtual void SetWaitSyncPointCallback(
650 const WaitSyncPointCallback& callback) OVERRIDE;
652 virtual AsyncPixelTransferManager*
653 GetAsyncPixelTransferManager() OVERRIDE;
654 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
655 virtual void SetAsyncPixelTransferManagerForTest(
656 AsyncPixelTransferManager* manager) OVERRIDE;
657 virtual void SetIgnoreCachedStateForTest(bool ignore) OVERRIDE;
658 void ProcessFinishedAsyncTransfers();
660 virtual bool GetServiceTextureId(uint32 client_texture_id,
661 uint32* service_texture_id) OVERRIDE;
663 virtual uint32 GetTextureUploadCount() OVERRIDE;
664 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
665 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
666 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
668 // Restores the current state to the user's settings.
669 void RestoreCurrentFramebufferBindings();
671 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
672 void ApplyDirtyState();
674 // These check the state of the currently bound framebuffer or the
675 // backbuffer if no framebuffer is bound.
676 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
677 // check with all attached and enabled color attachments.
678 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
679 bool BoundFramebufferHasDepthAttachment();
680 bool BoundFramebufferHasStencilAttachment();
682 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
684 // Overridden from FramebufferManager::TextureDetachObserver:
685 virtual void OnTextureRefDetachedFromFramebuffer(
686 TextureRef* texture) OVERRIDE;
688 // Overriden from ErrorStateClient.
689 virtual void OnOutOfMemoryError() OVERRIDE;
691 // Helpers to facilitate calling into compatible extensions.
692 static void RenderbufferStorageMultisampleHelper(
693 const FeatureInfo* feature_info,
694 GLenum target,
695 GLsizei samples,
696 GLenum internal_format,
697 GLsizei width,
698 GLsizei height);
700 void BlitFramebufferHelper(GLint srcX0,
701 GLint srcY0,
702 GLint srcX1,
703 GLint srcY1,
704 GLint dstX0,
705 GLint dstY0,
706 GLint dstX1,
707 GLint dstY1,
708 GLbitfield mask,
709 GLenum filter);
711 private:
712 friend class ScopedFrameBufferBinder;
713 friend class ScopedResolvedFrameBufferBinder;
714 friend class BackFramebuffer;
716 // Initialize or re-initialize the shader translator.
717 bool InitializeShaderTranslator();
719 void UpdateCapabilities();
721 // Helpers for the glGen and glDelete functions.
722 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
723 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
724 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
725 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
726 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
727 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
728 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
729 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
730 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
731 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
732 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
733 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
735 // Helper for async upload token completion notification callback.
736 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
737 uint32 sync_data_shm_id,
738 uint32 sync_data_shm_offset);
742 // Workarounds
743 void OnFboChanged() const;
744 void OnUseFramebuffer() const;
746 // TODO(gman): Cache these pointers?
747 BufferManager* buffer_manager() {
748 return group_->buffer_manager();
751 RenderbufferManager* renderbuffer_manager() {
752 return group_->renderbuffer_manager();
755 FramebufferManager* framebuffer_manager() {
756 return group_->framebuffer_manager();
759 ProgramManager* program_manager() {
760 return group_->program_manager();
763 ShaderManager* shader_manager() {
764 return group_->shader_manager();
767 ShaderTranslatorCache* shader_translator_cache() {
768 return group_->shader_translator_cache();
771 const TextureManager* texture_manager() const {
772 return group_->texture_manager();
775 TextureManager* texture_manager() {
776 return group_->texture_manager();
779 MailboxManager* mailbox_manager() {
780 return group_->mailbox_manager();
783 ImageManager* image_manager() {
784 return group_->image_manager();
787 VertexArrayManager* vertex_array_manager() {
788 return vertex_array_manager_.get();
791 MemoryTracker* memory_tracker() {
792 return group_->memory_tracker();
795 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
796 MemoryTracker* tracker = memory_tracker();
797 if (tracker) {
798 return tracker->EnsureGPUMemoryAvailable(estimated_size);
800 return true;
803 bool IsOffscreenBufferMultisampled() const {
804 return offscreen_target_samples_ > 1;
807 // Creates a Texture for the given texture.
808 TextureRef* CreateTexture(
809 GLuint client_id, GLuint service_id) {
810 return texture_manager()->CreateTexture(client_id, service_id);
813 // Gets the texture info for the given texture. Returns NULL if none exists.
814 TextureRef* GetTexture(GLuint client_id) const {
815 return texture_manager()->GetTexture(client_id);
818 // Deletes the texture info for the given texture.
819 void RemoveTexture(GLuint client_id) {
820 texture_manager()->RemoveTexture(client_id);
823 // Get the size (in pixels) of the currently bound frame buffer (either FBO
824 // or regular back buffer).
825 gfx::Size GetBoundReadFrameBufferSize();
827 // Get the format of the currently bound frame buffer (either FBO or regular
828 // back buffer)
829 GLenum GetBoundReadFrameBufferTextureType();
830 GLenum GetBoundReadFrameBufferInternalFormat();
831 GLenum GetBoundDrawFrameBufferInternalFormat();
833 // Wrapper for CompressedTexImage2D commands.
834 error::Error DoCompressedTexImage2D(
835 GLenum target,
836 GLint level,
837 GLenum internal_format,
838 GLsizei width,
839 GLsizei height,
840 GLint border,
841 GLsizei image_size,
842 const void* data);
844 // Wrapper for CompressedTexSubImage2D.
845 void DoCompressedTexSubImage2D(
846 GLenum target,
847 GLint level,
848 GLint xoffset,
849 GLint yoffset,
850 GLsizei width,
851 GLsizei height,
852 GLenum format,
853 GLsizei imageSize,
854 const void * data);
856 // Wrapper for CopyTexImage2D.
857 void DoCopyTexImage2D(
858 GLenum target,
859 GLint level,
860 GLenum internal_format,
861 GLint x,
862 GLint y,
863 GLsizei width,
864 GLsizei height,
865 GLint border);
867 // Wrapper for SwapBuffers.
868 void DoSwapBuffers();
870 // Wrapper for CopyTexSubImage2D.
871 void DoCopyTexSubImage2D(
872 GLenum target,
873 GLint level,
874 GLint xoffset,
875 GLint yoffset,
876 GLint x,
877 GLint y,
878 GLsizei width,
879 GLsizei height);
881 // Validation for TexSubImage2D.
882 bool ValidateTexSubImage2D(
883 error::Error* error,
884 const char* function_name,
885 GLenum target,
886 GLint level,
887 GLint xoffset,
888 GLint yoffset,
889 GLsizei width,
890 GLsizei height,
891 GLenum format,
892 GLenum type,
893 const void * data);
895 // Wrapper for TexSubImage2D.
896 error::Error DoTexSubImage2D(
897 GLenum target,
898 GLint level,
899 GLint xoffset,
900 GLint yoffset,
901 GLsizei width,
902 GLsizei height,
903 GLenum format,
904 GLenum type,
905 const void * data);
907 // Extra validation for async tex(Sub)Image2D.
908 bool ValidateAsyncTransfer(
909 const char* function_name,
910 TextureRef* texture_ref,
911 GLenum target,
912 GLint level,
913 const void * data);
915 // Wrapper for TexImageIOSurface2DCHROMIUM.
916 void DoTexImageIOSurface2DCHROMIUM(
917 GLenum target,
918 GLsizei width,
919 GLsizei height,
920 GLuint io_surface_id,
921 GLuint plane);
923 void DoCopyTextureCHROMIUM(
924 GLenum target,
925 GLuint source_id,
926 GLuint target_id,
927 GLint level,
928 GLenum internal_format,
929 GLenum dest_type);
931 // Wrapper for TexStorage2DEXT.
932 void DoTexStorage2DEXT(
933 GLenum target,
934 GLint levels,
935 GLenum internal_format,
936 GLsizei width,
937 GLsizei height);
939 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
940 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
941 const GLbyte* key);
942 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
943 GLenum target, const GLbyte* data);
945 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
946 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
947 GLuint client_id);
949 void DoBindTexImage2DCHROMIUM(
950 GLenum target,
951 GLint image_id);
952 void DoReleaseTexImage2DCHROMIUM(
953 GLenum target,
954 GLint image_id);
956 void DoTraceEndCHROMIUM(void);
958 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
960 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
962 // Creates a Program for the given program.
963 Program* CreateProgram(
964 GLuint client_id, GLuint service_id) {
965 return program_manager()->CreateProgram(client_id, service_id);
968 // Gets the program info for the given program. Returns NULL if none exists.
969 Program* GetProgram(GLuint client_id) {
970 return program_manager()->GetProgram(client_id);
973 #if defined(NDEBUG)
974 void LogClientServiceMapping(
975 const char* /* function_name */,
976 GLuint /* client_id */,
977 GLuint /* service_id */) {
979 template<typename T>
980 void LogClientServiceForInfo(
981 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
983 #else
984 void LogClientServiceMapping(
985 const char* function_name, GLuint client_id, GLuint service_id) {
986 if (service_logging_) {
987 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
988 << ": client_id = " << client_id
989 << ", service_id = " << service_id;
992 template<typename T>
993 void LogClientServiceForInfo(
994 T* info, GLuint client_id, const char* function_name) {
995 if (info) {
996 LogClientServiceMapping(function_name, client_id, info->service_id());
999 #endif
1001 // Gets the program info for the given program. If it's not a program
1002 // generates a GL error. Returns NULL if not program.
1003 Program* GetProgramInfoNotShader(
1004 GLuint client_id, const char* function_name) {
1005 Program* program = GetProgram(client_id);
1006 if (!program) {
1007 if (GetShader(client_id)) {
1008 LOCAL_SET_GL_ERROR(
1009 GL_INVALID_OPERATION, function_name, "shader passed for program");
1010 } else {
1011 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1014 LogClientServiceForInfo(program, client_id, function_name);
1015 return program;
1019 // Creates a Shader for the given shader.
1020 Shader* CreateShader(
1021 GLuint client_id,
1022 GLuint service_id,
1023 GLenum shader_type) {
1024 return shader_manager()->CreateShader(
1025 client_id, service_id, shader_type);
1028 // Gets the shader info for the given shader. Returns NULL if none exists.
1029 Shader* GetShader(GLuint client_id) {
1030 return shader_manager()->GetShader(client_id);
1033 // Gets the shader info for the given shader. If it's not a shader generates a
1034 // GL error. Returns NULL if not shader.
1035 Shader* GetShaderInfoNotProgram(
1036 GLuint client_id, const char* function_name) {
1037 Shader* shader = GetShader(client_id);
1038 if (!shader) {
1039 if (GetProgram(client_id)) {
1040 LOCAL_SET_GL_ERROR(
1041 GL_INVALID_OPERATION, function_name, "program passed for shader");
1042 } else {
1043 LOCAL_SET_GL_ERROR(
1044 GL_INVALID_VALUE, function_name, "unknown shader");
1047 LogClientServiceForInfo(shader, client_id, function_name);
1048 return shader;
1051 // Creates a buffer info for the given buffer.
1052 void CreateBuffer(GLuint client_id, GLuint service_id) {
1053 return buffer_manager()->CreateBuffer(client_id, service_id);
1056 // Gets the buffer info for the given buffer.
1057 Buffer* GetBuffer(GLuint client_id) {
1058 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1059 return buffer;
1062 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1063 // on glDeleteBuffers so we can make sure the user does not try to render
1064 // with deleted buffers.
1065 void RemoveBuffer(GLuint client_id);
1067 // Creates a framebuffer info for the given framebuffer.
1068 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1069 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1072 // Gets the framebuffer info for the given framebuffer.
1073 Framebuffer* GetFramebuffer(GLuint client_id) {
1074 return framebuffer_manager()->GetFramebuffer(client_id);
1077 // Removes the framebuffer info for the given framebuffer.
1078 void RemoveFramebuffer(GLuint client_id) {
1079 framebuffer_manager()->RemoveFramebuffer(client_id);
1082 // Creates a renderbuffer info for the given renderbuffer.
1083 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1084 return renderbuffer_manager()->CreateRenderbuffer(
1085 client_id, service_id);
1088 // Gets the renderbuffer info for the given renderbuffer.
1089 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1090 return renderbuffer_manager()->GetRenderbuffer(client_id);
1093 // Removes the renderbuffer info for the given renderbuffer.
1094 void RemoveRenderbuffer(GLuint client_id) {
1095 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1098 // Gets the vertex attrib manager for the given vertex array.
1099 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1100 VertexAttribManager* info =
1101 vertex_array_manager()->GetVertexAttribManager(client_id);
1102 return info;
1105 // Removes the vertex attrib manager for the given vertex array.
1106 void RemoveVertexAttribManager(GLuint client_id) {
1107 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1110 // Creates a vertex attrib manager for the given vertex array.
1111 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1112 GLuint client_id,
1113 GLuint service_id,
1114 bool client_visible) {
1115 return vertex_array_manager()->CreateVertexAttribManager(
1116 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1119 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1120 void DoBindUniformLocationCHROMIUM(
1121 GLuint client_id, GLint location, const char* name);
1123 error::Error GetAttribLocationHelper(
1124 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1125 const std::string& name_str);
1127 error::Error GetUniformLocationHelper(
1128 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1129 const std::string& name_str);
1131 // Helper for glShaderSource.
1132 error::Error ShaderSourceHelper(
1133 GLuint client_id, const char* data, uint32 data_size);
1135 // Clear any textures used by the current program.
1136 bool ClearUnclearedTextures();
1138 // Clears any uncleared attachments attached to the given frame buffer.
1139 // Returns false if there was a generated GL error.
1140 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1142 // overridden from GLES2Decoder
1143 virtual bool ClearLevel(unsigned service_id,
1144 unsigned bind_target,
1145 unsigned target,
1146 int level,
1147 unsigned internal_format,
1148 unsigned format,
1149 unsigned type,
1150 int width,
1151 int height,
1152 bool is_texture_immutable) OVERRIDE;
1154 // Restore all GL state that affects clearing.
1155 void RestoreClearState();
1157 // Remembers the state of some capabilities.
1158 // Returns: true if glEnable/glDisable should actually be called.
1159 bool SetCapabilityState(GLenum cap, bool enabled);
1161 // Check that the currently bound framebuffers are valid.
1162 // Generates GL error if not.
1163 bool CheckBoundFramebuffersValid(const char* func_name);
1165 // Check if a framebuffer meets our requirements.
1166 bool CheckFramebufferValid(
1167 Framebuffer* framebuffer,
1168 GLenum target,
1169 const char* func_name);
1171 // Checks if the current program exists and is valid. If not generates the
1172 // appropriate GL error. Returns true if the current program is in a usable
1173 // state.
1174 bool CheckCurrentProgram(const char* function_name);
1176 // Checks if the current program exists and is valid and that location is not
1177 // -1. If the current program is not valid generates the appropriate GL
1178 // error. Returns true if the current program is in a usable state and
1179 // location is not -1.
1180 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1182 // Gets the type of a uniform for a location in the current program. Sets GL
1183 // errors if the current program is not valid. Returns true if the current
1184 // program is valid and the location exists. Adjusts count so it
1185 // does not overflow the uniform.
1186 bool PrepForSetUniformByLocation(GLint fake_location,
1187 const char* function_name,
1188 Program::UniformApiType api_type,
1189 GLint* real_location,
1190 GLenum* type,
1191 GLsizei* count);
1193 // Gets the service id for any simulated backbuffer fbo.
1194 GLuint GetBackbufferServiceId() const;
1196 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1197 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1199 // Helper for glGetVertexAttrib
1200 void GetVertexAttribHelper(
1201 const VertexAttrib* attrib, GLenum pname, GLint* param);
1203 // Wrapper for glCreateProgram
1204 bool CreateProgramHelper(GLuint client_id);
1206 // Wrapper for glCreateShader
1207 bool CreateShaderHelper(GLenum type, GLuint client_id);
1209 // Wrapper for glActiveTexture
1210 void DoActiveTexture(GLenum texture_unit);
1212 // Wrapper for glAttachShader
1213 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1215 // Wrapper for glBindBuffer since we need to track the current targets.
1216 void DoBindBuffer(GLenum target, GLuint buffer);
1218 // Wrapper for glBindFramebuffer since we need to track the current targets.
1219 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1221 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1222 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1224 // Wrapper for glBindTexture since we need to track the current targets.
1225 void DoBindTexture(GLenum target, GLuint texture);
1227 // Wrapper for glBindVertexArrayOES
1228 void DoBindVertexArrayOES(GLuint array);
1229 void EmulateVertexArrayState();
1231 // Wrapper for glBlitFramebufferCHROMIUM.
1232 void DoBlitFramebufferCHROMIUM(
1233 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1234 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1235 GLbitfield mask, GLenum filter);
1237 // Wrapper for glBufferSubData.
1238 void DoBufferSubData(
1239 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1241 // Wrapper for glCheckFramebufferStatus
1242 GLenum DoCheckFramebufferStatus(GLenum target);
1244 // Wrapper for glClear
1245 error::Error DoClear(GLbitfield mask);
1247 // Wrappers for various state.
1248 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1249 void DoSampleCoverage(GLclampf value, GLboolean invert);
1251 // Wrapper for glCompileShader.
1252 void DoCompileShader(GLuint shader);
1254 // Helper for DeleteSharedIdsCHROMIUM commands.
1255 void DoDeleteSharedIdsCHROMIUM(
1256 GLuint namespace_id, GLsizei n, const GLuint* ids);
1258 // Wrapper for glDetachShader
1259 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1261 // Wrapper for glDisable
1262 void DoDisable(GLenum cap);
1264 // Wrapper for glDisableVertexAttribArray.
1265 void DoDisableVertexAttribArray(GLuint index);
1267 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1268 // attachments.
1269 void DoDiscardFramebufferEXT(GLenum target,
1270 GLsizei numAttachments,
1271 const GLenum* attachments);
1273 // Wrapper for glEnable
1274 void DoEnable(GLenum cap);
1276 // Wrapper for glEnableVertexAttribArray.
1277 void DoEnableVertexAttribArray(GLuint index);
1279 // Wrapper for glFinish.
1280 void DoFinish();
1282 // Wrapper for glFlush.
1283 void DoFlush();
1285 // Wrapper for glFramebufferRenderbufffer.
1286 void DoFramebufferRenderbuffer(
1287 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1288 GLuint renderbuffer);
1290 // Wrapper for glFramebufferTexture2D.
1291 void DoFramebufferTexture2D(
1292 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1293 GLint level);
1295 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1296 void DoFramebufferTexture2DMultisample(
1297 GLenum target, GLenum attachment, GLenum textarget,
1298 GLuint texture, GLint level, GLsizei samples);
1300 // Common implementation for both DoFramebufferTexture2D wrappers.
1301 void DoFramebufferTexture2DCommon(const char* name,
1302 GLenum target, GLenum attachment, GLenum textarget,
1303 GLuint texture, GLint level, GLsizei samples);
1305 // Wrapper for glGenerateMipmap
1306 void DoGenerateMipmap(GLenum target);
1308 // Helper for GenSharedIdsCHROMIUM commands.
1309 void DoGenSharedIdsCHROMIUM(
1310 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1312 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1313 // to account for different pname values defined in different extension
1314 // variants.
1315 GLenum AdjustGetPname(GLenum pname);
1317 // Wrapper for DoGetBooleanv.
1318 void DoGetBooleanv(GLenum pname, GLboolean* params);
1320 // Wrapper for DoGetFloatv.
1321 void DoGetFloatv(GLenum pname, GLfloat* params);
1323 // Wrapper for glGetFramebufferAttachmentParameteriv.
1324 void DoGetFramebufferAttachmentParameteriv(
1325 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1327 // Wrapper for glGetIntegerv.
1328 void DoGetIntegerv(GLenum pname, GLint* params);
1330 // Gets the max value in a range in a buffer.
1331 GLuint DoGetMaxValueInBufferCHROMIUM(
1332 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1334 // Wrapper for glGetBufferParameteriv.
1335 void DoGetBufferParameteriv(
1336 GLenum target, GLenum pname, GLint* params);
1338 // Wrapper for glGetProgramiv.
1339 void DoGetProgramiv(
1340 GLuint program_id, GLenum pname, GLint* params);
1342 // Wrapper for glRenderbufferParameteriv.
1343 void DoGetRenderbufferParameteriv(
1344 GLenum target, GLenum pname, GLint* params);
1346 // Wrapper for glGetShaderiv
1347 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1349 // Wrappers for glGetTexParameter.
1350 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1351 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1352 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1354 // Wrappers for glGetVertexAttrib.
1355 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1356 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1358 // Wrappers for glIsXXX functions.
1359 bool DoIsEnabled(GLenum cap);
1360 bool DoIsBuffer(GLuint client_id);
1361 bool DoIsFramebuffer(GLuint client_id);
1362 bool DoIsProgram(GLuint client_id);
1363 bool DoIsRenderbuffer(GLuint client_id);
1364 bool DoIsShader(GLuint client_id);
1365 bool DoIsTexture(GLuint client_id);
1366 bool DoIsVertexArrayOES(GLuint client_id);
1368 // Wrapper for glLinkProgram
1369 void DoLinkProgram(GLuint program);
1371 // Helper for RegisterSharedIdsCHROMIUM.
1372 void DoRegisterSharedIdsCHROMIUM(
1373 GLuint namespace_id, GLsizei n, const GLuint* ids);
1375 // Wrapper for glRenderbufferStorage.
1376 void DoRenderbufferStorage(
1377 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1379 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1380 void DoRenderbufferStorageMultisampleCHROMIUM(
1381 GLenum target, GLsizei samples, GLenum internalformat,
1382 GLsizei width, GLsizei height);
1384 // Handler for glRenderbufferStorageMultisampleEXT
1385 // (multisampled_render_to_texture).
1386 void DoRenderbufferStorageMultisampleEXT(
1387 GLenum target, GLsizei samples, GLenum internalformat,
1388 GLsizei width, GLsizei height);
1390 // Common validation for multisample extensions.
1391 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1392 GLenum internalformat,
1393 GLsizei width,
1394 GLsizei height);
1396 // Verifies that the currently bound multisample renderbuffer is valid
1397 // Very slow! Only done on platforms with driver bugs that return invalid
1398 // buffers under memory pressure
1399 bool VerifyMultisampleRenderbufferIntegrity(
1400 GLuint renderbuffer, GLenum format);
1402 // Wrapper for glReleaseShaderCompiler.
1403 void DoReleaseShaderCompiler() { }
1405 // Wrappers for glTexParameter functions.
1406 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1407 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1408 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1409 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1411 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1412 // spec only these 2 functions can be used to set sampler uniforms.
1413 void DoUniform1i(GLint fake_location, GLint v0);
1414 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1415 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1416 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1417 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1419 // Wrappers for glUniformfv because some drivers don't correctly accept
1420 // bool uniforms.
1421 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1422 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1423 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1424 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1426 void DoUniformMatrix2fv(
1427 GLint fake_location, GLsizei count, GLboolean transpose,
1428 const GLfloat* value);
1429 void DoUniformMatrix3fv(
1430 GLint fake_location, GLsizei count, GLboolean transpose,
1431 const GLfloat* value);
1432 void DoUniformMatrix4fv(
1433 GLint fake_location, GLsizei count, GLboolean transpose,
1434 const GLfloat* value);
1436 bool SetVertexAttribValue(
1437 const char* function_name, GLuint index, const GLfloat* value);
1439 // Wrappers for glVertexAttrib??
1440 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1441 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1442 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1443 void DoVertexAttrib4f(
1444 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1445 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1446 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1447 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1448 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1450 // Wrapper for glViewport
1451 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1453 // Wrapper for glUseProgram
1454 void DoUseProgram(GLuint program);
1456 // Wrapper for glValidateProgram.
1457 void DoValidateProgram(GLuint program_client_id);
1459 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1460 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1461 void DoPopGroupMarkerEXT(void);
1463 // Gets the number of values that will be returned by glGetXXX. Returns
1464 // false if pname is unknown.
1465 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1467 // Checks if the current program and vertex attributes are valid for drawing.
1468 bool IsDrawValid(
1469 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
1471 // Returns true if successful, simulated will be true if attrib0 was
1472 // simulated.
1473 bool SimulateAttrib0(
1474 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1475 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1477 // If an image is bound to texture, this will call Will/DidUseTexImage
1478 // if needed.
1479 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1480 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1482 // Returns false if textures were replaced.
1483 bool PrepareTexturesForRender();
1484 void RestoreStateForTextures();
1486 // Returns true if GL_FIXED attribs were simulated.
1487 bool SimulateFixedAttribs(
1488 const char* function_name,
1489 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1490 void RestoreStateForSimulatedFixedAttribs();
1492 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1493 // cases (primcount is 0 for non-instanced).
1494 error::Error DoDrawArrays(
1495 const char* function_name,
1496 bool instanced, GLenum mode, GLint first, GLsizei count,
1497 GLsizei primcount);
1498 error::Error DoDrawElements(
1499 const char* function_name,
1500 bool instanced, GLenum mode, GLsizei count, GLenum type,
1501 int32 offset, GLsizei primcount);
1503 GLenum GetBindTargetForSamplerType(GLenum type) {
1504 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1505 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1506 switch (type) {
1507 case GL_SAMPLER_2D:
1508 return GL_TEXTURE_2D;
1509 case GL_SAMPLER_CUBE:
1510 return GL_TEXTURE_CUBE_MAP;
1511 case GL_SAMPLER_EXTERNAL_OES:
1512 return GL_TEXTURE_EXTERNAL_OES;
1513 case GL_SAMPLER_2D_RECT_ARB:
1514 return GL_TEXTURE_RECTANGLE_ARB;
1517 NOTREACHED();
1518 return 0;
1521 // Gets the framebuffer info for a particular target.
1522 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1523 Framebuffer* framebuffer = NULL;
1524 switch (target) {
1525 case GL_FRAMEBUFFER:
1526 case GL_DRAW_FRAMEBUFFER_EXT:
1527 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1528 break;
1529 case GL_READ_FRAMEBUFFER_EXT:
1530 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1531 break;
1532 default:
1533 NOTREACHED();
1534 break;
1536 return framebuffer;
1539 Renderbuffer* GetRenderbufferInfoForTarget(
1540 GLenum target) {
1541 Renderbuffer* renderbuffer = NULL;
1542 switch (target) {
1543 case GL_RENDERBUFFER:
1544 renderbuffer = state_.bound_renderbuffer.get();
1545 break;
1546 default:
1547 NOTREACHED();
1548 break;
1550 return renderbuffer;
1553 // Validates the program and location for a glGetUniform call and returns
1554 // a SizeResult setup to receive the result. Returns true if glGetUniform
1555 // should be called.
1556 bool GetUniformSetup(
1557 GLuint program, GLint fake_location,
1558 uint32 shm_id, uint32 shm_offset,
1559 error::Error* error, GLint* real_location, GLuint* service_id,
1560 void** result, GLenum* result_type);
1562 virtual bool WasContextLost() OVERRIDE;
1563 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1564 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1566 #if defined(OS_MACOSX)
1567 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1568 #endif
1570 bool ValidateCompressedTexDimensions(
1571 const char* function_name,
1572 GLint level, GLsizei width, GLsizei height, GLenum format);
1573 bool ValidateCompressedTexFuncData(
1574 const char* function_name,
1575 GLsizei width, GLsizei height, GLenum format, size_t size);
1576 bool ValidateCompressedTexSubDimensions(
1577 const char* function_name,
1578 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1579 GLsizei width, GLsizei height, GLenum format,
1580 Texture* texture);
1582 void RenderWarning(const char* filename, int line, const std::string& msg);
1583 void PerformanceWarning(
1584 const char* filename, int line, const std::string& msg);
1586 const FeatureInfo::FeatureFlags& features() const {
1587 return feature_info_->feature_flags();
1590 const FeatureInfo::Workarounds& workarounds() const {
1591 return feature_info_->workarounds();
1594 bool ShouldDeferDraws() {
1595 return !offscreen_target_frame_buffer_.get() &&
1596 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1597 surface_->DeferDraws();
1600 bool ShouldDeferReads() {
1601 return !offscreen_target_frame_buffer_.get() &&
1602 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1603 surface_->DeferDraws();
1606 error::Error WillAccessBoundFramebufferForDraw() {
1607 if (ShouldDeferDraws())
1608 return error::kDeferCommandUntilLater;
1609 if (!offscreen_target_frame_buffer_.get() &&
1610 !framebuffer_state_.bound_draw_framebuffer.get() &&
1611 !surface_->SetBackbufferAllocation(true))
1612 return error::kLostContext;
1613 return error::kNoError;
1616 error::Error WillAccessBoundFramebufferForRead() {
1617 if (ShouldDeferReads())
1618 return error::kDeferCommandUntilLater;
1619 if (!offscreen_target_frame_buffer_.get() &&
1620 !framebuffer_state_.bound_read_framebuffer.get() &&
1621 !surface_->SetBackbufferAllocation(true))
1622 return error::kLostContext;
1623 return error::kNoError;
1626 void ProcessPendingReadPixels();
1627 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1629 // Generate a member function prototype for each command in an automated and
1630 // typesafe way.
1631 #define GLES2_CMD_OP(name) \
1632 Error Handle ## name( \
1633 uint32 immediate_data_size, \
1634 const cmds::name& args); \
1636 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1638 #undef GLES2_CMD_OP
1640 // The GL context this decoder renders to on behalf of the client.
1641 scoped_refptr<gfx::GLSurface> surface_;
1642 scoped_refptr<gfx::GLContext> context_;
1644 // The ContextGroup for this decoder uses to track resources.
1645 scoped_refptr<ContextGroup> group_;
1647 DebugMarkerManager debug_marker_manager_;
1648 Logger logger_;
1650 // All the state for this context.
1651 ContextState state_;
1653 // Current width and height of the offscreen frame buffer.
1654 gfx::Size offscreen_size_;
1656 // Util to help with GL.
1657 GLES2Util util_;
1659 // unpack flip y as last set by glPixelStorei
1660 bool unpack_flip_y_;
1662 // unpack (un)premultiply alpha as last set by glPixelStorei
1663 bool unpack_premultiply_alpha_;
1664 bool unpack_unpremultiply_alpha_;
1666 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1667 GLuint attrib_0_buffer_id_;
1669 // The value currently in attrib_0.
1670 Vec4 attrib_0_value_;
1672 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1673 bool attrib_0_buffer_matches_value_;
1675 // The size of attrib 0.
1676 GLsizei attrib_0_size_;
1678 // The buffer used to simulate GL_FIXED attribs.
1679 GLuint fixed_attrib_buffer_id_;
1681 // The size of fiixed attrib buffer.
1682 GLsizei fixed_attrib_buffer_size_;
1684 // The offscreen frame buffer that the client renders to. With EGL, the
1685 // depth and stencil buffers are separate. With regular GL there is a single
1686 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1687 // offscreen_target_stencil_render_buffer_ is unused.
1688 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1689 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1690 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1691 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1692 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1693 GLenum offscreen_target_color_format_;
1694 GLenum offscreen_target_depth_format_;
1695 GLenum offscreen_target_stencil_format_;
1696 GLsizei offscreen_target_samples_;
1697 GLboolean offscreen_target_buffer_preserved_;
1699 // The copy that is saved when SwapBuffers is called.
1700 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1701 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1702 scoped_refptr<TextureRef>
1703 offscreen_saved_color_texture_info_;
1705 // The copy that is used as the destination for multi-sample resolves.
1706 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1707 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1708 GLenum offscreen_saved_color_format_;
1710 scoped_ptr<QueryManager> query_manager_;
1712 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1714 base::Callback<void(gfx::Size, float)> resize_callback_;
1716 WaitSyncPointCallback wait_sync_point_callback_;
1718 ShaderCacheCallback shader_cache_callback_;
1720 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1722 // The format of the back buffer_
1723 GLenum back_buffer_color_format_;
1724 bool back_buffer_has_depth_;
1725 bool back_buffer_has_stencil_;
1727 // Backbuffer attachments that are currently undefined.
1728 uint32 backbuffer_needs_clear_bits_;
1730 // The current decoder error communicates the decoder error through command
1731 // processing functions that do not return the error value. Should be set only
1732 // if not returning an error.
1733 error::Error current_decoder_error_;
1735 bool use_shader_translator_;
1736 scoped_refptr<ShaderTranslator> vertex_translator_;
1737 scoped_refptr<ShaderTranslator> fragment_translator_;
1739 DisallowedFeatures disallowed_features_;
1741 // Cached from ContextGroup
1742 const Validators* validators_;
1743 scoped_refptr<FeatureInfo> feature_info_;
1745 int frame_number_;
1747 bool has_robustness_extension_;
1748 GLenum reset_status_;
1749 bool reset_by_robustness_extension_;
1750 bool supports_post_sub_buffer_;
1752 // These flags are used to override the state of the shared feature_info_
1753 // member. Because the same FeatureInfo instance may be shared among many
1754 // contexts, the assumptions on the availablity of extensions in WebGL
1755 // contexts may be broken. These flags override the shared state to preserve
1756 // WebGL semantics.
1757 bool force_webgl_glsl_validation_;
1758 bool derivatives_explicitly_enabled_;
1759 bool frag_depth_explicitly_enabled_;
1760 bool draw_buffers_explicitly_enabled_;
1761 bool shader_texture_lod_explicitly_enabled_;
1763 bool compile_shader_always_succeeds_;
1765 // An optional behaviour to lose the context and group when OOM.
1766 bool lose_context_when_out_of_memory_;
1768 // Log extra info.
1769 bool service_logging_;
1771 #if defined(OS_MACOSX)
1772 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1773 TextureToIOSurfaceMap texture_to_io_surface_map_;
1774 #endif
1776 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1778 // Cached values of the currently assigned viewport dimensions.
1779 GLsizei viewport_max_width_;
1780 GLsizei viewport_max_height_;
1782 // Command buffer stats.
1783 base::TimeDelta total_processing_commands_time_;
1785 // States related to each manager.
1786 DecoderTextureState texture_state_;
1787 DecoderFramebufferState framebuffer_state_;
1789 scoped_ptr<GPUTracer> gpu_tracer_;
1790 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1791 int gpu_trace_level_;
1792 bool gpu_trace_commands_;
1794 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1796 // Used to validate multisample renderbuffers if needed
1797 GLuint validation_texture_;
1798 GLuint validation_fbo_multisample_;
1799 GLuint validation_fbo_;
1801 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1804 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1805 const char* function_name, ErrorState* error_state)
1806 : function_name_(function_name),
1807 error_state_(error_state) {
1808 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1811 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1812 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1815 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1816 TextureUnit& info = state->texture_units[0];
1817 GLuint last_id;
1818 scoped_refptr<TextureRef> texture_ref;
1819 switch (target) {
1820 case GL_TEXTURE_2D:
1821 texture_ref = info.bound_texture_2d;
1822 break;
1823 case GL_TEXTURE_CUBE_MAP:
1824 texture_ref = info.bound_texture_cube_map;
1825 break;
1826 case GL_TEXTURE_EXTERNAL_OES:
1827 texture_ref = info.bound_texture_external_oes;
1828 break;
1829 case GL_TEXTURE_RECTANGLE_ARB:
1830 texture_ref = info.bound_texture_rectangle_arb;
1831 break;
1832 default:
1833 NOTREACHED();
1834 break;
1836 if (texture_ref.get()) {
1837 last_id = texture_ref->service_id();
1838 } else {
1839 last_id = 0;
1842 glBindTexture(target, last_id);
1843 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1846 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1847 GLuint id,
1848 GLenum target)
1849 : state_(state),
1850 target_(target) {
1851 ScopedGLErrorSuppressor suppressor(
1852 "ScopedTextureBinder::ctor", state_->GetErrorState());
1854 // TODO(apatrick): Check if there are any other states that need to be reset
1855 // before binding a new texture.
1856 glActiveTexture(GL_TEXTURE0);
1857 glBindTexture(target, id);
1860 ScopedTextureBinder::~ScopedTextureBinder() {
1861 ScopedGLErrorSuppressor suppressor(
1862 "ScopedTextureBinder::dtor", state_->GetErrorState());
1863 RestoreCurrentTextureBindings(state_, target_);
1866 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1867 GLuint id)
1868 : state_(state) {
1869 ScopedGLErrorSuppressor suppressor(
1870 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1871 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1874 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1875 ScopedGLErrorSuppressor suppressor(
1876 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1877 state_->RestoreRenderbufferBindings();
1880 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1881 GLuint id)
1882 : decoder_(decoder) {
1883 ScopedGLErrorSuppressor suppressor(
1884 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1885 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1886 decoder->OnFboChanged();
1889 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1890 ScopedGLErrorSuppressor suppressor(
1891 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1892 decoder_->RestoreCurrentFramebufferBindings();
1895 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1896 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1897 : decoder_(decoder) {
1898 resolve_and_bind_ = (
1899 decoder_->offscreen_target_frame_buffer_.get() &&
1900 decoder_->IsOffscreenBufferMultisampled() &&
1901 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1902 enforce_internal_framebuffer));
1903 if (!resolve_and_bind_)
1904 return;
1906 ScopedGLErrorSuppressor suppressor(
1907 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1908 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1909 decoder_->offscreen_target_frame_buffer_->id());
1910 GLuint targetid;
1911 if (internal) {
1912 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1913 decoder_->offscreen_resolved_frame_buffer_.reset(
1914 new BackFramebuffer(decoder_));
1915 decoder_->offscreen_resolved_frame_buffer_->Create();
1916 decoder_->offscreen_resolved_color_texture_.reset(
1917 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1918 decoder_->offscreen_resolved_color_texture_->Create();
1920 DCHECK(decoder_->offscreen_saved_color_format_);
1921 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1922 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1923 false);
1924 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1925 decoder_->offscreen_resolved_color_texture_.get());
1926 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1927 GL_FRAMEBUFFER_COMPLETE) {
1928 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1929 << "because offscreen resolved FBO was incomplete.";
1930 return;
1933 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1934 } else {
1935 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1937 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1938 const int width = decoder_->offscreen_size_.width();
1939 const int height = decoder_->offscreen_size_.height();
1940 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
1941 decoder->BlitFramebufferHelper(0,
1943 width,
1944 height,
1947 width,
1948 height,
1949 GL_COLOR_BUFFER_BIT,
1950 GL_NEAREST);
1951 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1954 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1955 if (!resolve_and_bind_)
1956 return;
1958 ScopedGLErrorSuppressor suppressor(
1959 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
1960 decoder_->RestoreCurrentFramebufferBindings();
1961 if (decoder_->state_.enable_flags.scissor_test) {
1962 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
1966 BackTexture::BackTexture(
1967 MemoryTracker* memory_tracker,
1968 ContextState* state)
1969 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1970 state_(state),
1971 bytes_allocated_(0),
1972 id_(0) {
1975 BackTexture::~BackTexture() {
1976 // This does not destroy the render texture because that would require that
1977 // the associated GL context was current. Just check that it was explicitly
1978 // destroyed.
1979 DCHECK_EQ(id_, 0u);
1982 void BackTexture::Create() {
1983 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
1984 state_->GetErrorState());
1985 Destroy();
1986 glGenTextures(1, &id_);
1987 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1988 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1989 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1990 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1991 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1993 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1994 // never called on an offscreen context, no data will ever be uploaded to the
1995 // saved offscreen color texture (it is deferred until to when SwapBuffers
1996 // is called). My idea is that some nvidia drivers might have a bug where
1997 // deleting a texture that has never been populated might cause a
1998 // crash.
1999 glTexImage2D(
2000 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2002 bytes_allocated_ = 16u * 16u * 4u;
2003 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2006 bool BackTexture::AllocateStorage(
2007 const gfx::Size& size, GLenum format, bool zero) {
2008 DCHECK_NE(id_, 0u);
2009 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2010 state_->GetErrorState());
2011 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2012 uint32 image_size = 0;
2013 GLES2Util::ComputeImageDataSizes(
2014 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
2015 NULL, NULL);
2017 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2018 return false;
2021 scoped_ptr<char[]> zero_data;
2022 if (zero) {
2023 zero_data.reset(new char[image_size]);
2024 memset(zero_data.get(), 0, image_size);
2027 glTexImage2D(GL_TEXTURE_2D,
2028 0, // mip level
2029 format,
2030 size.width(),
2031 size.height(),
2032 0, // border
2033 format,
2034 GL_UNSIGNED_BYTE,
2035 zero_data.get());
2037 size_ = size;
2039 bool success = glGetError() == GL_NO_ERROR;
2040 if (success) {
2041 memory_tracker_.TrackMemFree(bytes_allocated_);
2042 bytes_allocated_ = image_size;
2043 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2045 return success;
2048 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2049 DCHECK_NE(id_, 0u);
2050 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2051 state_->GetErrorState());
2052 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2053 glCopyTexImage2D(GL_TEXTURE_2D,
2054 0, // level
2055 format,
2056 0, 0,
2057 size.width(),
2058 size.height(),
2059 0); // border
2062 void BackTexture::Destroy() {
2063 if (id_ != 0) {
2064 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2065 state_->GetErrorState());
2066 glDeleteTextures(1, &id_);
2067 id_ = 0;
2069 memory_tracker_.TrackMemFree(bytes_allocated_);
2070 bytes_allocated_ = 0;
2073 void BackTexture::Invalidate() {
2074 id_ = 0;
2077 BackRenderbuffer::BackRenderbuffer(
2078 RenderbufferManager* renderbuffer_manager,
2079 MemoryTracker* memory_tracker,
2080 ContextState* state)
2081 : renderbuffer_manager_(renderbuffer_manager),
2082 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2083 state_(state),
2084 bytes_allocated_(0),
2085 id_(0) {
2088 BackRenderbuffer::~BackRenderbuffer() {
2089 // This does not destroy the render buffer because that would require that
2090 // the associated GL context was current. Just check that it was explicitly
2091 // destroyed.
2092 DCHECK_EQ(id_, 0u);
2095 void BackRenderbuffer::Create() {
2096 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2097 state_->GetErrorState());
2098 Destroy();
2099 glGenRenderbuffersEXT(1, &id_);
2102 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2103 const gfx::Size& size,
2104 GLenum format,
2105 GLsizei samples) {
2106 ScopedGLErrorSuppressor suppressor(
2107 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2108 ScopedRenderBufferBinder binder(state_, id_);
2110 uint32 estimated_size = 0;
2111 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2112 size.width(), size.height(), samples, format, &estimated_size)) {
2113 return false;
2116 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2117 return false;
2120 if (samples <= 1) {
2121 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2122 format,
2123 size.width(),
2124 size.height());
2125 } else {
2126 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2127 GL_RENDERBUFFER,
2128 samples,
2129 format,
2130 size.width(),
2131 size.height());
2133 bool success = glGetError() == GL_NO_ERROR;
2134 if (success) {
2135 // Mark the previously allocated bytes as free.
2136 memory_tracker_.TrackMemFree(bytes_allocated_);
2137 bytes_allocated_ = estimated_size;
2138 // Track the newly allocated bytes.
2139 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2141 return success;
2144 void BackRenderbuffer::Destroy() {
2145 if (id_ != 0) {
2146 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2147 state_->GetErrorState());
2148 glDeleteRenderbuffersEXT(1, &id_);
2149 id_ = 0;
2151 memory_tracker_.TrackMemFree(bytes_allocated_);
2152 bytes_allocated_ = 0;
2155 void BackRenderbuffer::Invalidate() {
2156 id_ = 0;
2159 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2160 : decoder_(decoder),
2161 id_(0) {
2164 BackFramebuffer::~BackFramebuffer() {
2165 // This does not destroy the frame buffer because that would require that
2166 // the associated GL context was current. Just check that it was explicitly
2167 // destroyed.
2168 DCHECK_EQ(id_, 0u);
2171 void BackFramebuffer::Create() {
2172 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2173 decoder_->GetErrorState());
2174 Destroy();
2175 glGenFramebuffersEXT(1, &id_);
2178 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2179 DCHECK_NE(id_, 0u);
2180 ScopedGLErrorSuppressor suppressor(
2181 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2182 ScopedFrameBufferBinder binder(decoder_, id_);
2183 GLuint attach_id = texture ? texture->id() : 0;
2184 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2185 GL_COLOR_ATTACHMENT0,
2186 GL_TEXTURE_2D,
2187 attach_id,
2191 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2192 BackRenderbuffer* render_buffer) {
2193 DCHECK_NE(id_, 0u);
2194 ScopedGLErrorSuppressor suppressor(
2195 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2196 ScopedFrameBufferBinder binder(decoder_, id_);
2197 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2198 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2199 target,
2200 GL_RENDERBUFFER,
2201 attach_id);
2204 void BackFramebuffer::Destroy() {
2205 if (id_ != 0) {
2206 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2207 decoder_->GetErrorState());
2208 glDeleteFramebuffersEXT(1, &id_);
2209 id_ = 0;
2213 void BackFramebuffer::Invalidate() {
2214 id_ = 0;
2217 GLenum BackFramebuffer::CheckStatus() {
2218 DCHECK_NE(id_, 0u);
2219 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2220 decoder_->GetErrorState());
2221 ScopedFrameBufferBinder binder(decoder_, id_);
2222 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2225 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2226 return new GLES2DecoderImpl(group);
2229 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2230 : GLES2Decoder(),
2231 group_(group),
2232 logger_(&debug_marker_manager_),
2233 state_(group_->feature_info(), this, &logger_),
2234 unpack_flip_y_(false),
2235 unpack_premultiply_alpha_(false),
2236 unpack_unpremultiply_alpha_(false),
2237 attrib_0_buffer_id_(0),
2238 attrib_0_buffer_matches_value_(true),
2239 attrib_0_size_(0),
2240 fixed_attrib_buffer_id_(0),
2241 fixed_attrib_buffer_size_(0),
2242 offscreen_target_color_format_(0),
2243 offscreen_target_depth_format_(0),
2244 offscreen_target_stencil_format_(0),
2245 offscreen_target_samples_(0),
2246 offscreen_target_buffer_preserved_(true),
2247 offscreen_saved_color_format_(0),
2248 back_buffer_color_format_(0),
2249 back_buffer_has_depth_(false),
2250 back_buffer_has_stencil_(false),
2251 backbuffer_needs_clear_bits_(0),
2252 current_decoder_error_(error::kNoError),
2253 use_shader_translator_(true),
2254 validators_(group_->feature_info()->validators()),
2255 feature_info_(group_->feature_info()),
2256 frame_number_(0),
2257 has_robustness_extension_(false),
2258 reset_status_(GL_NO_ERROR),
2259 reset_by_robustness_extension_(false),
2260 supports_post_sub_buffer_(false),
2261 force_webgl_glsl_validation_(false),
2262 derivatives_explicitly_enabled_(false),
2263 frag_depth_explicitly_enabled_(false),
2264 draw_buffers_explicitly_enabled_(false),
2265 shader_texture_lod_explicitly_enabled_(false),
2266 compile_shader_always_succeeds_(false),
2267 lose_context_when_out_of_memory_(false),
2268 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2269 switches::kEnableGPUServiceLoggingGPU)),
2270 viewport_max_width_(0),
2271 viewport_max_height_(0),
2272 texture_state_(group_->feature_info()
2273 ->workarounds()
2274 .texsubimage2d_faster_than_teximage2d),
2275 validation_texture_(0),
2276 validation_fbo_multisample_(0),
2277 validation_fbo_(0) {
2278 DCHECK(group);
2280 attrib_0_value_.v[0] = 0.0f;
2281 attrib_0_value_.v[1] = 0.0f;
2282 attrib_0_value_.v[2] = 0.0f;
2283 attrib_0_value_.v[3] = 1.0f;
2285 // The shader translator is used for WebGL even when running on EGL
2286 // because additional restrictions are needed (like only enabling
2287 // GL_OES_standard_derivatives on demand). It is used for the unit
2288 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2289 // the empty string to CompileShader and this is not a valid shader.
2290 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2291 CommandLine::ForCurrentProcess()->HasSwitch(
2292 switches::kDisableGLSLTranslator)) {
2293 use_shader_translator_ = false;
2297 GLES2DecoderImpl::~GLES2DecoderImpl() {
2300 bool GLES2DecoderImpl::Initialize(
2301 const scoped_refptr<gfx::GLSurface>& surface,
2302 const scoped_refptr<gfx::GLContext>& context,
2303 bool offscreen,
2304 const gfx::Size& size,
2305 const DisallowedFeatures& disallowed_features,
2306 const std::vector<int32>& attribs) {
2307 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2308 DCHECK(context->IsCurrent(surface.get()));
2309 DCHECK(!context_.get());
2311 set_initialized();
2312 gpu_tracer_ = GPUTracer::Create(this);
2313 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2314 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2315 gpu_trace_level_ = 2;
2316 gpu_trace_commands_ = false;
2318 if (CommandLine::ForCurrentProcess()->HasSwitch(
2319 switches::kEnableGPUDebugging)) {
2320 set_debug(true);
2323 if (CommandLine::ForCurrentProcess()->HasSwitch(
2324 switches::kEnableGPUCommandLogging)) {
2325 set_log_commands(true);
2328 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2329 switches::kCompileShaderAlwaysSucceeds);
2332 // Take ownership of the context and surface. The surface can be replaced with
2333 // SetSurface.
2334 context_ = context;
2335 surface_ = surface;
2337 ContextCreationAttribHelper attrib_parser;
2338 if (!attrib_parser.Parse(attribs))
2339 return false;
2341 // Save the loseContextWhenOutOfMemory context creation attribute.
2342 lose_context_when_out_of_memory_ =
2343 attrib_parser.lose_context_when_out_of_memory_;
2345 // If the failIfMajorPerformanceCaveat context creation attribute was true
2346 // and we are using a software renderer, fail.
2347 if (attrib_parser.fail_if_major_perf_caveat_ &&
2348 feature_info_->feature_flags().is_swiftshader) {
2349 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2350 Destroy(true);
2351 return false;
2354 if (!group_->Initialize(this, disallowed_features)) {
2355 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2356 << "failed to initialize.";
2357 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2358 Destroy(true);
2359 return false;
2361 CHECK_GL_ERROR();
2363 disallowed_features_ = disallowed_features;
2365 state_.attrib_values.resize(group_->max_vertex_attribs());
2366 vertex_array_manager_.reset(new VertexArrayManager());
2368 GLuint default_vertex_attrib_service_id = 0;
2369 if (features().native_vertex_array_object) {
2370 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2371 glBindVertexArrayOES(default_vertex_attrib_service_id);
2374 state_.default_vertex_attrib_manager =
2375 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2377 state_.default_vertex_attrib_manager->Initialize(
2378 group_->max_vertex_attribs(),
2379 feature_info_->workarounds().init_vertex_attributes);
2381 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2382 DoBindVertexArrayOES(0);
2384 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2386 util_.set_num_compressed_texture_formats(
2387 validators_->compressed_texture_format.GetValues().size());
2389 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2390 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2391 // OpenGL ES 2.0 does not have this issue.
2392 glEnableVertexAttribArray(0);
2394 glGenBuffersARB(1, &attrib_0_buffer_id_);
2395 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2396 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2397 glBindBuffer(GL_ARRAY_BUFFER, 0);
2398 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2400 state_.texture_units.resize(group_->max_texture_units());
2401 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2402 glActiveTexture(GL_TEXTURE0 + tt);
2403 // We want the last bind to be 2D.
2404 TextureRef* ref;
2405 if (features().oes_egl_image_external) {
2406 ref = texture_manager()->GetDefaultTextureInfo(
2407 GL_TEXTURE_EXTERNAL_OES);
2408 state_.texture_units[tt].bound_texture_external_oes = ref;
2409 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2411 if (features().arb_texture_rectangle) {
2412 ref = texture_manager()->GetDefaultTextureInfo(
2413 GL_TEXTURE_RECTANGLE_ARB);
2414 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2415 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2417 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2418 state_.texture_units[tt].bound_texture_cube_map = ref;
2419 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2420 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2421 state_.texture_units[tt].bound_texture_2d = ref;
2422 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2424 glActiveTexture(GL_TEXTURE0);
2425 CHECK_GL_ERROR();
2427 if (offscreen) {
2428 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
2429 features().chromium_framebuffer_multisample) {
2430 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2431 // max_sample_count must be initialized to a sane value. If
2432 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2433 GLint max_sample_count = 1;
2434 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2435 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2436 max_sample_count);
2437 } else {
2438 offscreen_target_samples_ = 1;
2440 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
2442 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2443 const bool rgb8_supported =
2444 context_->HasExtension("GL_OES_rgb8_rgba8");
2445 // The only available default render buffer formats in GLES2 have very
2446 // little precision. Don't enable multisampling unless 8-bit render
2447 // buffer formats are available--instead fall back to 8-bit textures.
2448 if (rgb8_supported && offscreen_target_samples_ > 1) {
2449 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2450 GL_RGBA8 : GL_RGB8;
2451 } else {
2452 offscreen_target_samples_ = 1;
2453 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2454 GL_RGBA : GL_RGB;
2457 // ANGLE only supports packed depth/stencil formats, so use it if it is
2458 // available.
2459 const bool depth24_stencil8_supported =
2460 feature_info_->feature_flags().packed_depth24_stencil8;
2461 VLOG(1) << "GL_OES_packed_depth_stencil "
2462 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2463 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2464 depth24_stencil8_supported) {
2465 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2466 offscreen_target_stencil_format_ = 0;
2467 } else {
2468 // It may be the case that this depth/stencil combination is not
2469 // supported, but this will be checked later by CheckFramebufferStatus.
2470 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2471 GL_DEPTH_COMPONENT16 : 0;
2472 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2473 GL_STENCIL_INDEX8 : 0;
2475 } else {
2476 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2477 GL_RGBA : GL_RGB;
2479 // If depth is requested at all, use the packed depth stencil format if
2480 // it's available, as some desktop GL drivers don't support any non-packed
2481 // formats for depth attachments.
2482 const bool depth24_stencil8_supported =
2483 feature_info_->feature_flags().packed_depth24_stencil8;
2484 VLOG(1) << "GL_EXT_packed_depth_stencil "
2485 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2487 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2488 depth24_stencil8_supported) {
2489 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2490 offscreen_target_stencil_format_ = 0;
2491 } else {
2492 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2493 GL_DEPTH_COMPONENT : 0;
2494 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2495 GL_STENCIL_INDEX : 0;
2499 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2500 GL_RGBA : GL_RGB;
2502 // Create the target frame buffer. This is the one that the client renders
2503 // directly to.
2504 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2505 offscreen_target_frame_buffer_->Create();
2506 // Due to GLES2 format limitations, either the color texture (for
2507 // non-multisampling) or the color render buffer (for multisampling) will be
2508 // attached to the offscreen frame buffer. The render buffer has more
2509 // limited formats available to it, but the texture can't do multisampling.
2510 if (IsOffscreenBufferMultisampled()) {
2511 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2512 renderbuffer_manager(), memory_tracker(), &state_));
2513 offscreen_target_color_render_buffer_->Create();
2514 } else {
2515 offscreen_target_color_texture_.reset(new BackTexture(
2516 memory_tracker(), &state_));
2517 offscreen_target_color_texture_->Create();
2519 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2520 renderbuffer_manager(), memory_tracker(), &state_));
2521 offscreen_target_depth_render_buffer_->Create();
2522 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2523 renderbuffer_manager(), memory_tracker(), &state_));
2524 offscreen_target_stencil_render_buffer_->Create();
2526 // Create the saved offscreen texture. The target frame buffer is copied
2527 // here when SwapBuffers is called.
2528 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2529 offscreen_saved_frame_buffer_->Create();
2531 offscreen_saved_color_texture_.reset(new BackTexture(
2532 memory_tracker(), &state_));
2533 offscreen_saved_color_texture_->Create();
2535 // Allocate the render buffers at their initial size and check the status
2536 // of the frame buffers is okay.
2537 if (!ResizeOffscreenFrameBuffer(size)) {
2538 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2539 Destroy(true);
2540 return false;
2543 // Allocate the offscreen saved color texture.
2544 DCHECK(offscreen_saved_color_format_);
2545 offscreen_saved_color_texture_->AllocateStorage(
2546 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2548 offscreen_saved_frame_buffer_->AttachRenderTexture(
2549 offscreen_saved_color_texture_.get());
2550 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2551 GL_FRAMEBUFFER_COMPLETE) {
2552 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2553 Destroy(true);
2554 return false;
2557 // Bind to the new default frame buffer (the offscreen target frame buffer).
2558 // This should now be associated with ID zero.
2559 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2560 } else {
2561 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2562 // These are NOT if the back buffer has these proprorties. They are
2563 // if we want the command buffer to enforce them regardless of what
2564 // the real backbuffer is assuming the real back buffer gives us more than
2565 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2566 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2567 // can't do anything about that.
2569 GLint v = 0;
2570 glGetIntegerv(GL_ALPHA_BITS, &v);
2571 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2572 // user requested RGB then RGB. If the user did not specify a preference
2573 // than use whatever we were given. Same for DEPTH and STENCIL.
2574 back_buffer_color_format_ =
2575 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2576 glGetIntegerv(GL_DEPTH_BITS, &v);
2577 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2578 glGetIntegerv(GL_STENCIL_BITS, &v);
2579 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2582 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2583 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2584 // isn't well documented; it was discovered in the Khronos OpenGL ES
2585 // mailing list archives. It also implicitly enables the desktop GL
2586 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2587 // variable in fragment shaders.
2588 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2589 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2590 glEnable(GL_POINT_SPRITE);
2593 has_robustness_extension_ =
2594 context->HasExtension("GL_ARB_robustness") ||
2595 context->HasExtension("GL_EXT_robustness");
2597 if (!InitializeShaderTranslator()) {
2598 return false;
2601 state_.viewport_width = size.width();
2602 state_.viewport_height = size.height();
2604 GLint viewport_params[4] = { 0 };
2605 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2606 viewport_max_width_ = viewport_params[0];
2607 viewport_max_height_ = viewport_params[1];
2609 state_.scissor_width = state_.viewport_width;
2610 state_.scissor_height = state_.viewport_height;
2612 // Set all the default state because some GL drivers get it wrong.
2613 state_.InitCapabilities(NULL);
2614 state_.InitState(NULL);
2615 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2617 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2618 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2619 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2620 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2622 bool call_gl_clear = true;
2623 #if defined(OS_ANDROID)
2624 // Temporary workaround for Android WebView because this clear ignores the
2625 // clip and corrupts that external UI of the App. Not calling glClear is ok
2626 // because the system already clears the buffer before each draw. Proper
2627 // fix might be setting the scissor clip properly before initialize. See
2628 // crbug.com/259023 for details.
2629 call_gl_clear = surface_->GetHandle();
2630 #endif
2631 if (call_gl_clear) {
2632 // Clear the backbuffer.
2633 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2636 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2637 if (feature_info_->workarounds()
2638 .disable_post_sub_buffers_for_onscreen_surfaces &&
2639 !surface->IsOffscreen())
2640 supports_post_sub_buffer_ = false;
2642 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2643 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2646 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2647 context_->SetUnbindFboOnMakeCurrent();
2650 if (feature_info_->workarounds().release_image_after_use) {
2651 image_manager()->SetReleaseAfterUse();
2654 // Only compositor contexts are known to use only the subset of GL
2655 // that can be safely migrated between the iGPU and the dGPU. Mark
2656 // those contexts as safe to forcibly transition between the GPUs.
2657 // http://crbug.com/180876, http://crbug.com/227228
2658 if (!offscreen)
2659 context_->SetSafeToForceGpuSwitch();
2661 async_pixel_transfer_manager_.reset(
2662 AsyncPixelTransferManager::Create(context.get()));
2663 async_pixel_transfer_manager_->Initialize(texture_manager());
2665 framebuffer_manager()->AddObserver(this);
2667 return true;
2670 Capabilities GLES2DecoderImpl::GetCapabilities() {
2671 DCHECK(initialized());
2673 Capabilities caps;
2675 caps.fast_npot_mo8_textures =
2676 feature_info_->workarounds().enable_chromium_fast_npot_mo8_textures;
2677 caps.egl_image_external =
2678 feature_info_->feature_flags().oes_egl_image_external;
2679 caps.texture_format_bgra8888 =
2680 feature_info_->feature_flags().ext_texture_format_bgra8888;
2681 caps.texture_format_etc1 =
2682 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2683 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2684 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2685 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2686 caps.discard_framebuffer =
2687 feature_info_->feature_flags().ext_discard_framebuffer;
2688 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
2690 #if defined(OS_MACOSX)
2691 // This is unconditionally true on mac, no need to test for it at runtime.
2692 caps.iosurface = true;
2693 #endif
2695 caps.post_sub_buffer = supports_post_sub_buffer_;
2696 caps.map_image = !!image_manager();
2698 return caps;
2701 void GLES2DecoderImpl::UpdateCapabilities() {
2702 util_.set_num_compressed_texture_formats(
2703 validators_->compressed_texture_format.GetValues().size());
2704 util_.set_num_shader_binary_formats(
2705 validators_->shader_binary_format.GetValues().size());
2708 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2709 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2711 if (!use_shader_translator_) {
2712 return true;
2714 ShBuiltInResources resources;
2715 ShInitBuiltInResources(&resources);
2716 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2717 resources.MaxVertexUniformVectors =
2718 group_->max_vertex_uniform_vectors();
2719 resources.MaxVaryingVectors = group_->max_varying_vectors();
2720 resources.MaxVertexTextureImageUnits =
2721 group_->max_vertex_texture_image_units();
2722 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2723 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2724 resources.MaxFragmentUniformVectors =
2725 group_->max_fragment_uniform_vectors();
2726 resources.MaxDrawBuffers = group_->max_draw_buffers();
2727 resources.MaxExpressionComplexity = 256;
2728 resources.MaxCallStackDepth = 256;
2730 #if (ANGLE_SH_VERSION >= 110)
2731 GLint range[2] = { 0, 0 };
2732 GLint precision = 0;
2733 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2734 range, &precision);
2735 resources.FragmentPrecisionHigh =
2736 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2737 #endif
2739 if (force_webgl_glsl_validation_) {
2740 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2741 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2742 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2743 if (!draw_buffers_explicitly_enabled_)
2744 resources.MaxDrawBuffers = 1;
2745 #if (ANGLE_SH_VERSION >= 123)
2746 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
2747 #endif
2748 } else {
2749 resources.OES_standard_derivatives =
2750 features().oes_standard_derivatives ? 1 : 0;
2751 resources.ARB_texture_rectangle =
2752 features().arb_texture_rectangle ? 1 : 0;
2753 resources.OES_EGL_image_external =
2754 features().oes_egl_image_external ? 1 : 0;
2755 resources.EXT_draw_buffers =
2756 features().ext_draw_buffers ? 1 : 0;
2757 resources.EXT_frag_depth =
2758 features().ext_frag_depth ? 1 : 0;
2759 #if (ANGLE_SH_VERSION >= 123)
2760 resources.EXT_shader_texture_lod =
2761 features().ext_shader_texture_lod ? 1 : 0;
2762 #endif
2765 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2766 : SH_GLES2_SPEC;
2767 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2768 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2769 resources.HashFunction = &CityHashForAngle;
2770 #else
2771 resources.HashFunction = &CityHash64;
2772 #endif
2773 else
2774 resources.HashFunction = NULL;
2775 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2776 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2777 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2778 int driver_bug_workarounds = 0;
2779 if (workarounds().needs_glsl_built_in_function_emulation)
2780 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2781 if (workarounds().init_gl_position_in_vertex_shader)
2782 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2783 if (workarounds().unfold_short_circuit_as_ternary_operation)
2784 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2785 if (workarounds().init_varyings_without_static_use)
2786 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2787 if (workarounds().unroll_for_loop_with_sampler_array_index)
2788 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2790 vertex_translator_ = shader_translator_cache()->GetTranslator(
2791 SH_VERTEX_SHADER,
2792 shader_spec,
2793 &resources,
2794 implementation_type,
2795 static_cast<ShCompileOptions>(driver_bug_workarounds));
2796 if (!vertex_translator_.get()) {
2797 LOG(ERROR) << "Could not initialize vertex shader translator.";
2798 Destroy(true);
2799 return false;
2802 fragment_translator_ = shader_translator_cache()->GetTranslator(
2803 SH_FRAGMENT_SHADER,
2804 shader_spec,
2805 &resources,
2806 implementation_type,
2807 static_cast<ShCompileOptions>(driver_bug_workarounds));
2808 if (!fragment_translator_.get()) {
2809 LOG(ERROR) << "Could not initialize fragment shader translator.";
2810 Destroy(true);
2811 return false;
2813 return true;
2816 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2817 for (GLsizei ii = 0; ii < n; ++ii) {
2818 if (GetBuffer(client_ids[ii])) {
2819 return false;
2822 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2823 glGenBuffersARB(n, service_ids.get());
2824 for (GLsizei ii = 0; ii < n; ++ii) {
2825 CreateBuffer(client_ids[ii], service_ids[ii]);
2827 return true;
2830 bool GLES2DecoderImpl::GenFramebuffersHelper(
2831 GLsizei n, const GLuint* client_ids) {
2832 for (GLsizei ii = 0; ii < n; ++ii) {
2833 if (GetFramebuffer(client_ids[ii])) {
2834 return false;
2837 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2838 glGenFramebuffersEXT(n, service_ids.get());
2839 for (GLsizei ii = 0; ii < n; ++ii) {
2840 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2842 return true;
2845 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2846 GLsizei n, const GLuint* client_ids) {
2847 for (GLsizei ii = 0; ii < n; ++ii) {
2848 if (GetRenderbuffer(client_ids[ii])) {
2849 return false;
2852 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2853 glGenRenderbuffersEXT(n, service_ids.get());
2854 for (GLsizei ii = 0; ii < n; ++ii) {
2855 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2857 return true;
2860 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2861 for (GLsizei ii = 0; ii < n; ++ii) {
2862 if (GetTexture(client_ids[ii])) {
2863 return false;
2866 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2867 glGenTextures(n, service_ids.get());
2868 for (GLsizei ii = 0; ii < n; ++ii) {
2869 CreateTexture(client_ids[ii], service_ids[ii]);
2871 return true;
2874 void GLES2DecoderImpl::DeleteBuffersHelper(
2875 GLsizei n, const GLuint* client_ids) {
2876 for (GLsizei ii = 0; ii < n; ++ii) {
2877 Buffer* buffer = GetBuffer(client_ids[ii]);
2878 if (buffer && !buffer->IsDeleted()) {
2879 state_.vertex_attrib_manager->Unbind(buffer);
2880 if (state_.bound_array_buffer.get() == buffer) {
2881 state_.bound_array_buffer = NULL;
2883 RemoveBuffer(client_ids[ii]);
2888 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2889 GLsizei n, const GLuint* client_ids) {
2890 bool supports_separate_framebuffer_binds =
2891 features().chromium_framebuffer_multisample;
2893 for (GLsizei ii = 0; ii < n; ++ii) {
2894 Framebuffer* framebuffer =
2895 GetFramebuffer(client_ids[ii]);
2896 if (framebuffer && !framebuffer->IsDeleted()) {
2897 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2898 framebuffer_state_.bound_draw_framebuffer = NULL;
2899 framebuffer_state_.clear_state_dirty = true;
2900 GLenum target = supports_separate_framebuffer_binds ?
2901 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2902 glBindFramebufferEXT(target, GetBackbufferServiceId());
2904 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2905 framebuffer_state_.bound_read_framebuffer = NULL;
2906 GLenum target = supports_separate_framebuffer_binds ?
2907 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2908 glBindFramebufferEXT(target, GetBackbufferServiceId());
2910 OnFboChanged();
2911 RemoveFramebuffer(client_ids[ii]);
2916 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2917 GLsizei n, const GLuint* client_ids) {
2918 bool supports_separate_framebuffer_binds =
2919 features().chromium_framebuffer_multisample;
2920 for (GLsizei ii = 0; ii < n; ++ii) {
2921 Renderbuffer* renderbuffer =
2922 GetRenderbuffer(client_ids[ii]);
2923 if (renderbuffer && !renderbuffer->IsDeleted()) {
2924 if (state_.bound_renderbuffer.get() == renderbuffer) {
2925 state_.bound_renderbuffer = NULL;
2927 // Unbind from current framebuffers.
2928 if (supports_separate_framebuffer_binds) {
2929 if (framebuffer_state_.bound_read_framebuffer.get()) {
2930 framebuffer_state_.bound_read_framebuffer
2931 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2933 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2934 framebuffer_state_.bound_draw_framebuffer
2935 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2937 } else {
2938 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2939 framebuffer_state_.bound_draw_framebuffer
2940 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2943 framebuffer_state_.clear_state_dirty = true;
2944 RemoveRenderbuffer(client_ids[ii]);
2949 void GLES2DecoderImpl::DeleteTexturesHelper(
2950 GLsizei n, const GLuint* client_ids) {
2951 bool supports_separate_framebuffer_binds =
2952 features().chromium_framebuffer_multisample;
2953 for (GLsizei ii = 0; ii < n; ++ii) {
2954 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2955 if (texture_ref) {
2956 Texture* texture = texture_ref->texture();
2957 if (texture->IsAttachedToFramebuffer()) {
2958 framebuffer_state_.clear_state_dirty = true;
2960 // Unbind texture_ref from texture_ref units.
2961 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
2962 state_.texture_units[jj].Unbind(texture_ref);
2964 // Unbind from current framebuffers.
2965 if (supports_separate_framebuffer_binds) {
2966 if (framebuffer_state_.bound_read_framebuffer.get()) {
2967 framebuffer_state_.bound_read_framebuffer
2968 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
2970 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2971 framebuffer_state_.bound_draw_framebuffer
2972 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
2974 } else {
2975 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2976 framebuffer_state_.bound_draw_framebuffer
2977 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
2980 #if defined(OS_MACOSX)
2981 GLuint service_id = texture->service_id();
2982 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2983 ReleaseIOSurfaceForTexture(service_id);
2985 #endif
2986 RemoveTexture(client_ids[ii]);
2991 // } // anonymous namespace
2993 bool GLES2DecoderImpl::MakeCurrent() {
2994 if (!context_.get())
2995 return false;
2997 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
2998 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3000 // Some D3D drivers cannot recover from device lost in the GPU process
3001 // sandbox. Allow a new GPU process to launch.
3002 if (workarounds().exit_on_context_lost) {
3003 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
3004 << " a D3D device in the Chrome GPU process sandbox.";
3005 #if defined(OS_WIN)
3006 base::win::SetShouldCrashOnProcessDetach(false);
3007 #endif
3008 exit(0);
3011 return false;
3014 ProcessFinishedAsyncTransfers();
3016 // Rebind the FBO if it was unbound by the context.
3017 if (workarounds().unbind_fbo_on_context_switch)
3018 RestoreFramebufferBindings();
3020 framebuffer_state_.clear_state_dirty = true;
3022 return true;
3025 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3026 ProcessPendingReadPixels();
3027 if (engine() && query_manager_.get())
3028 query_manager_->ProcessPendingTransferQueries();
3030 // TODO(epenner): Is there a better place to do this?
3031 // This needs to occur before we execute any batch of commands
3032 // from the client, as the client may have recieved an async
3033 // completion while issuing those commands.
3034 // "DidFlushStart" would be ideal if we had such a callback.
3035 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3038 static void RebindCurrentFramebuffer(
3039 GLenum target,
3040 Framebuffer* framebuffer,
3041 GLuint back_buffer_service_id) {
3042 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3044 if (framebuffer_id == 0) {
3045 framebuffer_id = back_buffer_service_id;
3048 glBindFramebufferEXT(target, framebuffer_id);
3051 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3052 framebuffer_state_.clear_state_dirty = true;
3054 if (!features().chromium_framebuffer_multisample) {
3055 RebindCurrentFramebuffer(
3056 GL_FRAMEBUFFER,
3057 framebuffer_state_.bound_draw_framebuffer.get(),
3058 GetBackbufferServiceId());
3059 } else {
3060 RebindCurrentFramebuffer(
3061 GL_READ_FRAMEBUFFER_EXT,
3062 framebuffer_state_.bound_read_framebuffer.get(),
3063 GetBackbufferServiceId());
3064 RebindCurrentFramebuffer(
3065 GL_DRAW_FRAMEBUFFER_EXT,
3066 framebuffer_state_.bound_draw_framebuffer.get(),
3067 GetBackbufferServiceId());
3069 OnFboChanged();
3072 bool GLES2DecoderImpl::CheckFramebufferValid(
3073 Framebuffer* framebuffer,
3074 GLenum target, const char* func_name) {
3075 if (!framebuffer) {
3076 if (backbuffer_needs_clear_bits_) {
3077 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3078 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3079 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3080 glClearStencil(0);
3081 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
3082 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
3083 glClearDepth(1.0f);
3084 state_.SetDeviceDepthMask(GL_TRUE);
3085 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3086 bool reset_draw_buffer = false;
3087 if ((backbuffer_needs_clear_bits_ | GL_COLOR_BUFFER_BIT) != 0 &&
3088 group_->draw_buffer() == GL_NONE) {
3089 reset_draw_buffer = true;
3090 GLenum buf = GL_BACK;
3091 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3092 buf = GL_COLOR_ATTACHMENT0;
3093 glDrawBuffersARB(1, &buf);
3095 glClear(backbuffer_needs_clear_bits_);
3096 if (reset_draw_buffer) {
3097 GLenum buf = GL_NONE;
3098 glDrawBuffersARB(1, &buf);
3100 backbuffer_needs_clear_bits_ = 0;
3101 RestoreClearState();
3103 return true;
3106 if (framebuffer_manager()->IsComplete(framebuffer)) {
3107 return true;
3110 GLenum completeness = framebuffer->IsPossiblyComplete();
3111 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3112 LOCAL_SET_GL_ERROR(
3113 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3114 return false;
3117 // Are all the attachments cleared?
3118 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3119 texture_manager()->HaveUnclearedMips()) {
3120 if (!framebuffer->IsCleared()) {
3121 // Can we clear them?
3122 if (framebuffer->GetStatus(texture_manager(), target) !=
3123 GL_FRAMEBUFFER_COMPLETE) {
3124 LOCAL_SET_GL_ERROR(
3125 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3126 "framebuffer incomplete (clear)");
3127 return false;
3129 ClearUnclearedAttachments(target, framebuffer);
3133 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3134 if (framebuffer->GetStatus(texture_manager(), target) !=
3135 GL_FRAMEBUFFER_COMPLETE) {
3136 LOCAL_SET_GL_ERROR(
3137 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3138 "framebuffer incomplete (check)");
3139 return false;
3141 framebuffer_manager()->MarkAsComplete(framebuffer);
3144 // NOTE: At this point we don't know if the framebuffer is complete but
3145 // we DO know that everything that needs to be cleared has been cleared.
3146 return true;
3149 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3150 if (!features().chromium_framebuffer_multisample) {
3151 bool valid = CheckFramebufferValid(
3152 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3153 func_name);
3155 if (valid)
3156 OnUseFramebuffer();
3158 return valid;
3160 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3161 GL_DRAW_FRAMEBUFFER_EXT,
3162 func_name) &&
3163 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3164 GL_READ_FRAMEBUFFER_EXT,
3165 func_name);
3168 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3169 Framebuffer* framebuffer =
3170 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3171 if (framebuffer != NULL) {
3172 const Framebuffer::Attachment* attachment =
3173 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3174 if (attachment) {
3175 return gfx::Size(attachment->width(), attachment->height());
3177 return gfx::Size(0, 0);
3178 } else if (offscreen_target_frame_buffer_.get()) {
3179 return offscreen_size_;
3180 } else {
3181 return surface_->GetSize();
3185 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3186 Framebuffer* framebuffer =
3187 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3188 if (framebuffer != NULL) {
3189 return framebuffer->GetColorAttachmentTextureType();
3190 } else {
3191 return GL_UNSIGNED_BYTE;
3195 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3196 Framebuffer* framebuffer =
3197 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3198 if (framebuffer != NULL) {
3199 return framebuffer->GetColorAttachmentFormat();
3200 } else if (offscreen_target_frame_buffer_.get()) {
3201 return offscreen_target_color_format_;
3202 } else {
3203 return back_buffer_color_format_;
3207 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3208 Framebuffer* framebuffer =
3209 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3210 if (framebuffer != NULL) {
3211 return framebuffer->GetColorAttachmentFormat();
3212 } else if (offscreen_target_frame_buffer_.get()) {
3213 return offscreen_target_color_format_;
3214 } else {
3215 return back_buffer_color_format_;
3219 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3220 if (!offscreen_saved_color_texture_info_.get())
3221 return;
3222 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3223 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3224 texture_manager()->SetLevelInfo(
3225 offscreen_saved_color_texture_info_.get(),
3226 GL_TEXTURE_2D,
3227 0, // level
3228 GL_RGBA,
3229 offscreen_size_.width(),
3230 offscreen_size_.height(),
3231 1, // depth
3232 0, // border
3233 GL_RGBA,
3234 GL_UNSIGNED_BYTE,
3235 true);
3236 texture_manager()->SetParameteri(
3237 "UpdateParentTextureInfo",
3238 GetErrorState(),
3239 offscreen_saved_color_texture_info_.get(),
3240 GL_TEXTURE_MAG_FILTER,
3241 GL_NEAREST);
3242 texture_manager()->SetParameteri(
3243 "UpdateParentTextureInfo",
3244 GetErrorState(),
3245 offscreen_saved_color_texture_info_.get(),
3246 GL_TEXTURE_MIN_FILTER,
3247 GL_NEAREST);
3248 texture_manager()->SetParameteri(
3249 "UpdateParentTextureInfo",
3250 GetErrorState(),
3251 offscreen_saved_color_texture_info_.get(),
3252 GL_TEXTURE_WRAP_S,
3253 GL_CLAMP_TO_EDGE);
3254 texture_manager()->SetParameteri(
3255 "UpdateParentTextureInfo",
3256 GetErrorState(),
3257 offscreen_saved_color_texture_info_.get(),
3258 GL_TEXTURE_WRAP_T,
3259 GL_CLAMP_TO_EDGE);
3260 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3261 &state_, target);
3262 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3265 void GLES2DecoderImpl::SetResizeCallback(
3266 const base::Callback<void(gfx::Size, float)>& callback) {
3267 resize_callback_ = callback;
3270 Logger* GLES2DecoderImpl::GetLogger() {
3271 return &logger_;
3274 void GLES2DecoderImpl::BeginDecoding() {
3275 gpu_tracer_->BeginDecoding();
3276 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3279 void GLES2DecoderImpl::EndDecoding() {
3280 gpu_tracer_->EndDecoding();
3283 ErrorState* GLES2DecoderImpl::GetErrorState() {
3284 return state_.GetErrorState();
3287 void GLES2DecoderImpl::SetShaderCacheCallback(
3288 const ShaderCacheCallback& callback) {
3289 shader_cache_callback_ = callback;
3292 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3293 const WaitSyncPointCallback& callback) {
3294 wait_sync_point_callback_ = callback;
3297 AsyncPixelTransferManager*
3298 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3299 return async_pixel_transfer_manager_.get();
3302 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3303 async_pixel_transfer_manager_.reset();
3306 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3307 AsyncPixelTransferManager* manager) {
3308 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3311 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3312 uint32* service_texture_id) {
3313 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3314 if (texture_ref) {
3315 *service_texture_id = texture_ref->service_id();
3316 return true;
3318 return false;
3321 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3322 return texture_state_.texture_upload_count +
3323 async_pixel_transfer_manager_->GetTextureUploadCount();
3326 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3327 return texture_state_.total_texture_upload_time +
3328 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3331 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3332 return total_processing_commands_time_;
3335 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3336 total_processing_commands_time_ += time;
3339 void GLES2DecoderImpl::Destroy(bool have_context) {
3340 if (!initialized())
3341 return;
3343 DCHECK(!have_context || context_->IsCurrent(NULL));
3345 // Unbind everything.
3346 state_.vertex_attrib_manager = NULL;
3347 state_.default_vertex_attrib_manager = NULL;
3348 state_.texture_units.clear();
3349 state_.bound_array_buffer = NULL;
3350 state_.current_queries.clear();
3351 framebuffer_state_.bound_read_framebuffer = NULL;
3352 framebuffer_state_.bound_draw_framebuffer = NULL;
3353 state_.bound_renderbuffer = NULL;
3355 if (offscreen_saved_color_texture_info_.get()) {
3356 DCHECK(offscreen_target_color_texture_);
3357 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3358 offscreen_saved_color_texture_->id());
3359 offscreen_saved_color_texture_->Invalidate();
3360 offscreen_saved_color_texture_info_ = NULL;
3362 if (have_context) {
3363 if (copy_texture_CHROMIUM_.get()) {
3364 copy_texture_CHROMIUM_->Destroy();
3365 copy_texture_CHROMIUM_.reset();
3368 if (state_.current_program.get()) {
3369 program_manager()->UnuseProgram(shader_manager(),
3370 state_.current_program.get());
3373 if (attrib_0_buffer_id_) {
3374 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3376 if (fixed_attrib_buffer_id_) {
3377 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3380 if (validation_texture_) {
3381 glDeleteTextures(1, &validation_texture_);
3382 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3383 glDeleteFramebuffersEXT(1, &validation_fbo_);
3386 if (offscreen_target_frame_buffer_.get())
3387 offscreen_target_frame_buffer_->Destroy();
3388 if (offscreen_target_color_texture_.get())
3389 offscreen_target_color_texture_->Destroy();
3390 if (offscreen_target_color_render_buffer_.get())
3391 offscreen_target_color_render_buffer_->Destroy();
3392 if (offscreen_target_depth_render_buffer_.get())
3393 offscreen_target_depth_render_buffer_->Destroy();
3394 if (offscreen_target_stencil_render_buffer_.get())
3395 offscreen_target_stencil_render_buffer_->Destroy();
3396 if (offscreen_saved_frame_buffer_.get())
3397 offscreen_saved_frame_buffer_->Destroy();
3398 if (offscreen_saved_color_texture_.get())
3399 offscreen_saved_color_texture_->Destroy();
3400 if (offscreen_resolved_frame_buffer_.get())
3401 offscreen_resolved_frame_buffer_->Destroy();
3402 if (offscreen_resolved_color_texture_.get())
3403 offscreen_resolved_color_texture_->Destroy();
3404 } else {
3405 if (offscreen_target_frame_buffer_.get())
3406 offscreen_target_frame_buffer_->Invalidate();
3407 if (offscreen_target_color_texture_.get())
3408 offscreen_target_color_texture_->Invalidate();
3409 if (offscreen_target_color_render_buffer_.get())
3410 offscreen_target_color_render_buffer_->Invalidate();
3411 if (offscreen_target_depth_render_buffer_.get())
3412 offscreen_target_depth_render_buffer_->Invalidate();
3413 if (offscreen_target_stencil_render_buffer_.get())
3414 offscreen_target_stencil_render_buffer_->Invalidate();
3415 if (offscreen_saved_frame_buffer_.get())
3416 offscreen_saved_frame_buffer_->Invalidate();
3417 if (offscreen_saved_color_texture_.get())
3418 offscreen_saved_color_texture_->Invalidate();
3419 if (offscreen_resolved_frame_buffer_.get())
3420 offscreen_resolved_frame_buffer_->Invalidate();
3421 if (offscreen_resolved_color_texture_.get())
3422 offscreen_resolved_color_texture_->Invalidate();
3425 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3426 // Otherwise, we can leak objects. http://crbug.com/258772.
3427 // state_.current_program must be reset before group_ is reset because
3428 // the later deletes the ProgramManager object that referred by
3429 // state_.current_program object.
3430 state_.current_program = NULL;
3432 copy_texture_CHROMIUM_.reset();
3434 if (query_manager_.get()) {
3435 query_manager_->Destroy(have_context);
3436 query_manager_.reset();
3439 if (vertex_array_manager_ .get()) {
3440 vertex_array_manager_->Destroy(have_context);
3441 vertex_array_manager_.reset();
3444 offscreen_target_frame_buffer_.reset();
3445 offscreen_target_color_texture_.reset();
3446 offscreen_target_color_render_buffer_.reset();
3447 offscreen_target_depth_render_buffer_.reset();
3448 offscreen_target_stencil_render_buffer_.reset();
3449 offscreen_saved_frame_buffer_.reset();
3450 offscreen_saved_color_texture_.reset();
3451 offscreen_resolved_frame_buffer_.reset();
3452 offscreen_resolved_color_texture_.reset();
3454 // Need to release these before releasing |group_| which may own the
3455 // ShaderTranslatorCache.
3456 fragment_translator_ = NULL;
3457 vertex_translator_ = NULL;
3459 // Should destroy the transfer manager before the texture manager held
3460 // by the context group.
3461 async_pixel_transfer_manager_.reset();
3463 if (group_.get()) {
3464 framebuffer_manager()->RemoveObserver(this);
3465 group_->Destroy(this, have_context);
3466 group_ = NULL;
3469 if (context_.get()) {
3470 context_->ReleaseCurrent(NULL);
3471 context_ = NULL;
3474 #if defined(OS_MACOSX)
3475 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3476 it != texture_to_io_surface_map_.end(); ++it) {
3477 CFRelease(it->second);
3479 texture_to_io_surface_map_.clear();
3480 #endif
3483 void GLES2DecoderImpl::SetSurface(
3484 const scoped_refptr<gfx::GLSurface>& surface) {
3485 DCHECK(context_->IsCurrent(NULL));
3486 DCHECK(surface_.get());
3487 surface_ = surface;
3488 RestoreCurrentFramebufferBindings();
3491 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3492 if (!offscreen_saved_color_texture_.get()) {
3493 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3494 return;
3496 if (!offscreen_saved_color_texture_info_.get()) {
3497 GLuint service_id = offscreen_saved_color_texture_->id();
3498 offscreen_saved_color_texture_info_ = TextureRef::Create(
3499 texture_manager(), 0, service_id);
3500 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3501 GL_TEXTURE_2D);
3502 UpdateParentTextureInfo();
3504 mailbox_manager()->ProduceTexture(
3505 GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
3508 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3509 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3510 if (!is_offscreen) {
3511 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3512 << " with an onscreen framebuffer.";
3513 return false;
3516 if (offscreen_size_ == size)
3517 return true;
3519 offscreen_size_ = size;
3520 int w = offscreen_size_.width();
3521 int h = offscreen_size_.height();
3522 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3523 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3524 << "to allocate storage due to excessive dimensions.";
3525 return false;
3528 // Reallocate the offscreen target buffers.
3529 DCHECK(offscreen_target_color_format_);
3530 if (IsOffscreenBufferMultisampled()) {
3531 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3532 feature_info_, offscreen_size_, offscreen_target_color_format_,
3533 offscreen_target_samples_)) {
3534 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3535 << "to allocate storage for offscreen target color buffer.";
3536 return false;
3538 } else {
3539 if (!offscreen_target_color_texture_->AllocateStorage(
3540 offscreen_size_, offscreen_target_color_format_, false)) {
3541 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3542 << "to allocate storage for offscreen target color texture.";
3543 return false;
3546 if (offscreen_target_depth_format_ &&
3547 !offscreen_target_depth_render_buffer_->AllocateStorage(
3548 feature_info_, offscreen_size_, offscreen_target_depth_format_,
3549 offscreen_target_samples_)) {
3550 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3551 << "to allocate storage for offscreen target depth buffer.";
3552 return false;
3554 if (offscreen_target_stencil_format_ &&
3555 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3556 feature_info_, offscreen_size_, offscreen_target_stencil_format_,
3557 offscreen_target_samples_)) {
3558 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3559 << "to allocate storage for offscreen target stencil buffer.";
3560 return false;
3563 // Attach the offscreen target buffers to the target frame buffer.
3564 if (IsOffscreenBufferMultisampled()) {
3565 offscreen_target_frame_buffer_->AttachRenderBuffer(
3566 GL_COLOR_ATTACHMENT0,
3567 offscreen_target_color_render_buffer_.get());
3568 } else {
3569 offscreen_target_frame_buffer_->AttachRenderTexture(
3570 offscreen_target_color_texture_.get());
3572 if (offscreen_target_depth_format_) {
3573 offscreen_target_frame_buffer_->AttachRenderBuffer(
3574 GL_DEPTH_ATTACHMENT,
3575 offscreen_target_depth_render_buffer_.get());
3577 const bool packed_depth_stencil =
3578 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3579 if (packed_depth_stencil) {
3580 offscreen_target_frame_buffer_->AttachRenderBuffer(
3581 GL_STENCIL_ATTACHMENT,
3582 offscreen_target_depth_render_buffer_.get());
3583 } else if (offscreen_target_stencil_format_) {
3584 offscreen_target_frame_buffer_->AttachRenderBuffer(
3585 GL_STENCIL_ATTACHMENT,
3586 offscreen_target_stencil_render_buffer_.get());
3589 if (offscreen_target_frame_buffer_->CheckStatus() !=
3590 GL_FRAMEBUFFER_COMPLETE) {
3591 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3592 << "because offscreen FBO was incomplete.";
3593 return false;
3596 // Clear the target frame buffer.
3598 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3599 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3600 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3601 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3602 glClearStencil(0);
3603 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
3604 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
3605 glClearDepth(0);
3606 state_.SetDeviceDepthMask(GL_TRUE);
3607 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3608 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3609 RestoreClearState();
3612 // Destroy the offscreen resolved framebuffers.
3613 if (offscreen_resolved_frame_buffer_.get())
3614 offscreen_resolved_frame_buffer_->Destroy();
3615 if (offscreen_resolved_color_texture_.get())
3616 offscreen_resolved_color_texture_->Destroy();
3617 offscreen_resolved_color_texture_.reset();
3618 offscreen_resolved_frame_buffer_.reset();
3620 return true;
3623 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3624 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3625 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3626 return error::kDeferCommandUntilLater;
3628 GLuint width = static_cast<GLuint>(c.width);
3629 GLuint height = static_cast<GLuint>(c.height);
3630 GLfloat scale_factor = c.scale_factor;
3631 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3633 width = std::max(1U, width);
3634 height = std::max(1U, height);
3636 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3637 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3638 // Make sure that we are done drawing to the back buffer before resizing.
3639 glFinish();
3640 #endif
3641 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3642 if (is_offscreen) {
3643 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3644 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3645 << "ResizeOffscreenFrameBuffer failed.";
3646 return error::kLostContext;
3650 if (!resize_callback_.is_null()) {
3651 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3652 DCHECK(context_->IsCurrent(surface_.get()));
3653 if (!context_->IsCurrent(surface_.get())) {
3654 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3655 << "current after resize callback.";
3656 return error::kLostContext;
3660 return error::kNoError;
3663 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3664 if (command_id > kStartPoint && command_id < kNumCommands) {
3665 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3667 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3670 // Decode command with its arguments, and call the corresponding GL function.
3671 // Note: args is a pointer to the command buffer. As such, it could be changed
3672 // by a (malicious) client at any time, so if validation has to happen, it
3673 // should operate on a copy of them.
3674 error::Error GLES2DecoderImpl::DoCommand(
3675 unsigned int command,
3676 unsigned int arg_count,
3677 const void* cmd_data) {
3678 error::Error result = error::kNoError;
3679 if (log_commands()) {
3680 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3681 // VLOG(1), no luck.
3682 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
3683 << GetCommandName(command);
3685 unsigned int command_index = command - kStartPoint - 1;
3686 if (command_index < arraysize(g_command_info)) {
3687 const CommandInfo& info = g_command_info[command_index];
3688 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3689 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3690 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3691 bool doing_gpu_trace = false;
3692 if (gpu_trace_commands_) {
3693 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3694 doing_gpu_trace = true;
3695 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3699 uint32 immediate_data_size =
3700 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3701 switch (command) {
3702 #define GLES2_CMD_OP(name) \
3703 case cmds::name::kCmdId: \
3704 result = Handle ## name( \
3705 immediate_data_size, \
3706 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3707 break; \
3709 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3710 #undef GLES2_CMD_OP
3713 if (doing_gpu_trace)
3714 gpu_tracer_->End(kTraceDecoder);
3716 if (debug()) {
3717 GLenum error;
3718 while ((error = glGetError()) != GL_NO_ERROR) {
3719 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3720 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3721 << GetCommandName(command);
3722 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3725 } else {
3726 result = error::kInvalidArguments;
3728 } else {
3729 result = DoCommonCommand(command, arg_count, cmd_data);
3731 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3732 result = current_decoder_error_;
3733 current_decoder_error_ = error::kNoError;
3735 return result;
3738 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3739 buffer_manager()->RemoveBuffer(client_id);
3742 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3743 if (GetProgram(client_id)) {
3744 return false;
3746 GLuint service_id = glCreateProgram();
3747 if (service_id != 0) {
3748 CreateProgram(client_id, service_id);
3750 return true;
3753 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3754 if (GetShader(client_id)) {
3755 return false;
3757 GLuint service_id = glCreateShader(type);
3758 if (service_id != 0) {
3759 CreateShader(client_id, service_id, type);
3761 return true;
3764 void GLES2DecoderImpl::DoFinish() {
3765 glFinish();
3766 ProcessPendingReadPixels();
3767 ProcessPendingQueries();
3770 void GLES2DecoderImpl::DoFlush() {
3771 glFlush();
3772 ProcessPendingQueries();
3775 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3776 GLuint texture_index = texture_unit - GL_TEXTURE0;
3777 if (texture_index >= state_.texture_units.size()) {
3778 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3779 "glActiveTexture", texture_unit, "texture_unit");
3780 return;
3782 state_.active_texture_unit = texture_index;
3783 glActiveTexture(texture_unit);
3786 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3787 Buffer* buffer = NULL;
3788 GLuint service_id = 0;
3789 if (client_id != 0) {
3790 buffer = GetBuffer(client_id);
3791 if (!buffer) {
3792 if (!group_->bind_generates_resource()) {
3793 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3794 "glBindBuffer",
3795 "id not generated by glGenBuffers");
3796 return;
3799 // It's a new id so make a buffer buffer for it.
3800 glGenBuffersARB(1, &service_id);
3801 CreateBuffer(client_id, service_id);
3802 buffer = GetBuffer(client_id);
3803 IdAllocatorInterface* id_allocator =
3804 group_->GetIdAllocator(id_namespaces::kBuffers);
3805 id_allocator->MarkAsUsed(client_id);
3808 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3809 if (buffer) {
3810 if (!buffer_manager()->SetTarget(buffer, target)) {
3811 LOCAL_SET_GL_ERROR(
3812 GL_INVALID_OPERATION,
3813 "glBindBuffer", "buffer bound to more than 1 target");
3814 return;
3816 service_id = buffer->service_id();
3818 switch (target) {
3819 case GL_ARRAY_BUFFER:
3820 state_.bound_array_buffer = buffer;
3821 break;
3822 case GL_ELEMENT_ARRAY_BUFFER:
3823 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3824 break;
3825 default:
3826 NOTREACHED(); // Validation should prevent us getting here.
3827 break;
3829 glBindBuffer(target, service_id);
3832 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3833 bool all_draw_buffers) {
3834 Framebuffer* framebuffer =
3835 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3836 if (!all_draw_buffers || !framebuffer) {
3837 return (GLES2Util::GetChannelsForFormat(
3838 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3840 return framebuffer->HasAlphaMRT();
3843 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3844 Framebuffer* framebuffer =
3845 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3846 if (framebuffer) {
3847 return framebuffer->HasDepthAttachment();
3849 if (offscreen_target_frame_buffer_.get()) {
3850 return offscreen_target_depth_format_ != 0;
3852 return back_buffer_has_depth_;
3855 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3856 Framebuffer* framebuffer =
3857 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3858 if (framebuffer) {
3859 return framebuffer->HasStencilAttachment();
3861 if (offscreen_target_frame_buffer_.get()) {
3862 return offscreen_target_stencil_format_ != 0 ||
3863 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3865 return back_buffer_has_stencil_;
3868 void GLES2DecoderImpl::ApplyDirtyState() {
3869 if (framebuffer_state_.clear_state_dirty) {
3870 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
3871 state_.SetDeviceColorMask(state_.color_mask_red,
3872 state_.color_mask_green,
3873 state_.color_mask_blue,
3874 state_.color_mask_alpha && have_alpha);
3876 bool have_depth = BoundFramebufferHasDepthAttachment();
3877 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
3879 bool have_stencil = BoundFramebufferHasStencilAttachment();
3880 state_.SetDeviceStencilMaskSeparate(
3881 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3882 state_.SetDeviceStencilMaskSeparate(
3883 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3885 state_.SetDeviceCapabilityState(
3886 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3887 state_.SetDeviceCapabilityState(
3888 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3889 framebuffer_state_.clear_state_dirty = false;
3893 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
3894 return (offscreen_target_frame_buffer_.get())
3895 ? offscreen_target_frame_buffer_->id()
3896 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
3899 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) const {
3900 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3901 "context", logger_.GetLogPrefix());
3902 // Restore the Framebuffer first because of bugs in Intel drivers.
3903 // Intel drivers incorrectly clip the viewport settings to
3904 // the size of the current framebuffer object.
3905 RestoreFramebufferBindings();
3906 state_.RestoreState(prev_state);
3909 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3910 GLuint service_id =
3911 framebuffer_state_.bound_draw_framebuffer.get()
3912 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3913 : GetBackbufferServiceId();
3914 if (!features().chromium_framebuffer_multisample) {
3915 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3916 } else {
3917 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
3918 service_id = framebuffer_state_.bound_read_framebuffer.get()
3919 ? framebuffer_state_.bound_read_framebuffer->service_id()
3920 : GetBackbufferServiceId();
3921 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3923 OnFboChanged();
3926 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
3927 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3928 if (texture) {
3929 GLenum target = texture->target();
3930 glBindTexture(target, service_id);
3931 glTexParameteri(
3932 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
3933 glTexParameteri(
3934 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
3935 glTexParameteri(
3936 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
3937 glTexParameteri(
3938 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
3939 RestoreTextureUnitBindings(state_.active_texture_unit);
3943 void GLES2DecoderImpl::ClearAllAttributes() const {
3944 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
3945 // other VAOs.
3946 if (feature_info_->feature_flags().native_vertex_array_object)
3947 glBindVertexArrayOES(0);
3949 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
3950 if (i != 0) // Never disable attribute 0
3951 glDisableVertexAttribArray(i);
3952 if(features().angle_instanced_arrays)
3953 glVertexAttribDivisorANGLE(i, 0);
3957 void GLES2DecoderImpl::RestoreAllAttributes() const {
3958 state_.RestoreVertexAttribs();
3961 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
3962 state_.SetIgnoreCachedStateForTest(ignore);
3965 void GLES2DecoderImpl::OnFboChanged() const {
3966 if (workarounds().restore_scissor_on_fbo_change)
3967 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3970 // Called after the FBO is checked for completeness.
3971 void GLES2DecoderImpl::OnUseFramebuffer() const {
3972 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3973 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
3974 // The driver forgets the correct scissor when modifying the FBO binding.
3975 glScissor(state_.scissor_x,
3976 state_.scissor_y,
3977 state_.scissor_width,
3978 state_.scissor_height);
3980 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3981 // it's unclear how this bug works.
3982 glFlush();
3986 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3987 Framebuffer* framebuffer = NULL;
3988 GLuint service_id = 0;
3989 if (client_id != 0) {
3990 framebuffer = GetFramebuffer(client_id);
3991 if (!framebuffer) {
3992 if (!group_->bind_generates_resource()) {
3993 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3994 "glBindFramebuffer",
3995 "id not generated by glGenFramebuffers");
3996 return;
3999 // It's a new id so make a framebuffer framebuffer for it.
4000 glGenFramebuffersEXT(1, &service_id);
4001 CreateFramebuffer(client_id, service_id);
4002 framebuffer = GetFramebuffer(client_id);
4003 IdAllocatorInterface* id_allocator =
4004 group_->GetIdAllocator(id_namespaces::kFramebuffers);
4005 id_allocator->MarkAsUsed(client_id);
4006 } else {
4007 service_id = framebuffer->service_id();
4009 framebuffer->MarkAsValid();
4011 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4013 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4014 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4017 // vmiura: This looks like dup code
4018 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4019 framebuffer_state_.bound_read_framebuffer = framebuffer;
4022 framebuffer_state_.clear_state_dirty = true;
4024 // If we are rendering to the backbuffer get the FBO id for any simulated
4025 // backbuffer.
4026 if (framebuffer == NULL) {
4027 service_id = GetBackbufferServiceId();
4030 glBindFramebufferEXT(target, service_id);
4031 OnFboChanged();
4034 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4035 Renderbuffer* renderbuffer = NULL;
4036 GLuint service_id = 0;
4037 if (client_id != 0) {
4038 renderbuffer = GetRenderbuffer(client_id);
4039 if (!renderbuffer) {
4040 if (!group_->bind_generates_resource()) {
4041 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4042 "glBindRenderbuffer",
4043 "id not generated by glGenRenderbuffers");
4044 return;
4047 // It's a new id so make a renderbuffer renderbuffer for it.
4048 glGenRenderbuffersEXT(1, &service_id);
4049 CreateRenderbuffer(client_id, service_id);
4050 renderbuffer = GetRenderbuffer(client_id);
4051 IdAllocatorInterface* id_allocator =
4052 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
4053 id_allocator->MarkAsUsed(client_id);
4054 } else {
4055 service_id = renderbuffer->service_id();
4057 renderbuffer->MarkAsValid();
4059 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4060 state_.bound_renderbuffer = renderbuffer;
4061 glBindRenderbufferEXT(target, service_id);
4064 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4065 TextureRef* texture_ref = NULL;
4066 GLuint service_id = 0;
4067 if (client_id != 0) {
4068 texture_ref = GetTexture(client_id);
4069 if (!texture_ref) {
4070 if (!group_->bind_generates_resource()) {
4071 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4072 "glBindTexture",
4073 "id not generated by glGenTextures");
4074 return;
4077 // It's a new id so make a texture texture for it.
4078 glGenTextures(1, &service_id);
4079 DCHECK_NE(0u, service_id);
4080 CreateTexture(client_id, service_id);
4081 texture_ref = GetTexture(client_id);
4082 IdAllocatorInterface* id_allocator =
4083 group_->GetIdAllocator(id_namespaces::kTextures);
4084 id_allocator->MarkAsUsed(client_id);
4086 } else {
4087 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4090 // Check the texture exists
4091 if (texture_ref) {
4092 Texture* texture = texture_ref->texture();
4093 // Check that we are not trying to bind it to a different target.
4094 if (texture->target() != 0 && texture->target() != target) {
4095 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4096 "glBindTexture",
4097 "texture bound to more than 1 target.");
4098 return;
4100 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4101 if (texture->target() == 0) {
4102 texture_manager()->SetTarget(texture_ref, target);
4104 glBindTexture(target, texture->service_id());
4105 } else {
4106 glBindTexture(target, 0);
4109 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4110 unit.bind_target = target;
4111 switch (target) {
4112 case GL_TEXTURE_2D:
4113 unit.bound_texture_2d = texture_ref;
4114 break;
4115 case GL_TEXTURE_CUBE_MAP:
4116 unit.bound_texture_cube_map = texture_ref;
4117 break;
4118 case GL_TEXTURE_EXTERNAL_OES:
4119 unit.bound_texture_external_oes = texture_ref;
4120 break;
4121 case GL_TEXTURE_RECTANGLE_ARB:
4122 unit.bound_texture_rectangle_arb = texture_ref;
4123 break;
4124 default:
4125 NOTREACHED(); // Validation should prevent us getting here.
4126 break;
4130 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4131 if (state_.vertex_attrib_manager->Enable(index, false)) {
4132 if (index != 0 ||
4133 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4134 glDisableVertexAttribArray(index);
4136 } else {
4137 LOCAL_SET_GL_ERROR(
4138 GL_INVALID_VALUE,
4139 "glDisableVertexAttribArray", "index out of range");
4143 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4144 GLsizei numAttachments,
4145 const GLenum* attachments) {
4146 Framebuffer* framebuffer =
4147 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4149 // Validates the attachments. If one of them fails
4150 // the whole command fails.
4151 for (GLsizei i = 0; i < numAttachments; ++i) {
4152 if ((framebuffer &&
4153 !validators_->attachment.IsValid(attachments[i])) ||
4154 (!framebuffer &&
4155 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4156 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4157 "glDiscardFramebufferEXT", attachments[i], "attachments");
4158 return;
4162 // Marks each one of them as not cleared
4163 for (GLsizei i = 0; i < numAttachments; ++i) {
4164 if (framebuffer) {
4165 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4166 texture_manager(),
4167 attachments[i],
4168 false);
4169 } else {
4170 switch (attachments[i]) {
4171 case GL_COLOR_EXT:
4172 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4173 break;
4174 case GL_DEPTH_EXT:
4175 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4176 case GL_STENCIL_EXT:
4177 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4178 break;
4179 default:
4180 NOTREACHED();
4181 break;
4186 // If the default framebuffer is bound but we are still rendering to an
4187 // FBO, translate attachment names that refer to default framebuffer
4188 // channels to corresponding framebuffer attachments.
4189 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4190 for (GLsizei i = 0; i < numAttachments; ++i) {
4191 GLenum attachment = attachments[i];
4192 if (!framebuffer && GetBackbufferServiceId()) {
4193 switch (attachment) {
4194 case GL_COLOR_EXT:
4195 attachment = GL_COLOR_ATTACHMENT0;
4196 break;
4197 case GL_DEPTH_EXT:
4198 attachment = GL_DEPTH_ATTACHMENT;
4199 break;
4200 case GL_STENCIL_EXT:
4201 attachment = GL_STENCIL_ATTACHMENT;
4202 break;
4203 default:
4204 NOTREACHED();
4205 return;
4208 translated_attachments[i] = attachment;
4211 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4214 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4215 if (state_.vertex_attrib_manager->Enable(index, true)) {
4216 glEnableVertexAttribArray(index);
4217 } else {
4218 LOCAL_SET_GL_ERROR(
4219 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4223 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4224 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4225 &state_, target);
4226 if (!texture_ref ||
4227 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4228 LOCAL_SET_GL_ERROR(
4229 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4230 return;
4233 if (target == GL_TEXTURE_CUBE_MAP) {
4234 for (int i = 0; i < 6; ++i) {
4235 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4236 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4237 LOCAL_SET_GL_ERROR(
4238 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4239 return;
4242 } else {
4243 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4244 LOCAL_SET_GL_ERROR(
4245 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4246 return;
4250 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4251 // Workaround for Mac driver bug. In the large scheme of things setting
4252 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4253 // hit so there's probably no need to make this conditional. The bug appears
4254 // to be that if the filtering mode is set to something that doesn't require
4255 // mipmaps for rendering, or is never set to something other than the default,
4256 // then glGenerateMipmap misbehaves.
4257 if (workarounds().set_texture_filter_before_generating_mipmap) {
4258 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4260 glGenerateMipmapEXT(target);
4261 if (workarounds().set_texture_filter_before_generating_mipmap) {
4262 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4263 texture_ref->texture()->min_filter());
4265 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4266 if (error == GL_NO_ERROR) {
4267 texture_manager()->MarkMipmapsGenerated(texture_ref);
4271 bool GLES2DecoderImpl::GetHelper(
4272 GLenum pname, GLint* params, GLsizei* num_written) {
4273 DCHECK(num_written);
4274 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4275 switch (pname) {
4276 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4277 *num_written = 1;
4278 // Return the GL implementation's preferred format and (see below type)
4279 // if we have the GL extension that exposes this. This allows the GPU
4280 // client to use the implementation's preferred format for glReadPixels
4281 // for optimisation.
4283 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4284 // case when requested on integer/floating point buffers but which is
4285 // acceptable on GLES2 and with the GL_OES_read_format extension.
4287 // Therefore if an error occurs we swallow the error and use the
4288 // internal implementation.
4289 if (params) {
4290 if (context_->HasExtension("GL_OES_read_format")) {
4291 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4292 GetErrorState());
4293 glGetIntegerv(pname, params);
4294 if (glGetError() == GL_NO_ERROR)
4295 return true;
4297 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4298 GetBoundReadFrameBufferInternalFormat());
4300 return true;
4301 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4302 *num_written = 1;
4303 if (params) {
4304 if (context_->HasExtension("GL_OES_read_format")) {
4305 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4306 GetErrorState());
4307 glGetIntegerv(pname, params);
4308 if (glGetError() == GL_NO_ERROR)
4309 return true;
4311 *params = GLES2Util::GetPreferredGLReadPixelsType(
4312 GetBoundReadFrameBufferInternalFormat(),
4313 GetBoundReadFrameBufferTextureType());
4315 return true;
4316 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4317 *num_written = 1;
4318 if (params) {
4319 *params = group_->max_fragment_uniform_vectors();
4321 return true;
4322 case GL_MAX_VARYING_VECTORS:
4323 *num_written = 1;
4324 if (params) {
4325 *params = group_->max_varying_vectors();
4327 return true;
4328 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4329 *num_written = 1;
4330 if (params) {
4331 *params = group_->max_vertex_uniform_vectors();
4333 return true;
4336 switch (pname) {
4337 case GL_MAX_VIEWPORT_DIMS:
4338 if (offscreen_target_frame_buffer_.get()) {
4339 *num_written = 2;
4340 if (params) {
4341 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4342 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4344 return true;
4346 return false;
4347 case GL_MAX_SAMPLES:
4348 *num_written = 1;
4349 if (params) {
4350 params[0] = renderbuffer_manager()->max_samples();
4352 return true;
4353 case GL_MAX_RENDERBUFFER_SIZE:
4354 *num_written = 1;
4355 if (params) {
4356 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4358 return true;
4359 case GL_MAX_TEXTURE_SIZE:
4360 *num_written = 1;
4361 if (params) {
4362 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4364 return true;
4365 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4366 *num_written = 1;
4367 if (params) {
4368 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4370 return true;
4371 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4372 *num_written = 1;
4373 if (params) {
4374 params[0] = group_->max_color_attachments();
4376 return true;
4377 case GL_MAX_DRAW_BUFFERS_ARB:
4378 *num_written = 1;
4379 if (params) {
4380 params[0] = group_->max_draw_buffers();
4382 return true;
4383 case GL_ALPHA_BITS:
4384 *num_written = 1;
4385 if (params) {
4386 GLint v = 0;
4387 glGetIntegerv(GL_ALPHA_BITS, &v);
4388 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4390 return true;
4391 case GL_DEPTH_BITS:
4392 *num_written = 1;
4393 if (params) {
4394 GLint v = 0;
4395 glGetIntegerv(GL_DEPTH_BITS, &v);
4396 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4398 return true;
4399 case GL_STENCIL_BITS:
4400 *num_written = 1;
4401 if (params) {
4402 GLint v = 0;
4403 glGetIntegerv(GL_STENCIL_BITS, &v);
4404 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4406 return true;
4407 case GL_COMPRESSED_TEXTURE_FORMATS:
4408 *num_written = validators_->compressed_texture_format.GetValues().size();
4409 if (params) {
4410 for (GLint ii = 0; ii < *num_written; ++ii) {
4411 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4414 return true;
4415 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4416 *num_written = 1;
4417 if (params) {
4418 *params = validators_->compressed_texture_format.GetValues().size();
4420 return true;
4421 case GL_NUM_SHADER_BINARY_FORMATS:
4422 *num_written = 1;
4423 if (params) {
4424 *params = validators_->shader_binary_format.GetValues().size();
4426 return true;
4427 case GL_SHADER_BINARY_FORMATS:
4428 *num_written = validators_->shader_binary_format.GetValues().size();
4429 if (params) {
4430 for (GLint ii = 0; ii < *num_written; ++ii) {
4431 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4434 return true;
4435 case GL_SHADER_COMPILER:
4436 *num_written = 1;
4437 if (params) {
4438 *params = GL_TRUE;
4440 return true;
4441 case GL_ARRAY_BUFFER_BINDING:
4442 *num_written = 1;
4443 if (params) {
4444 if (state_.bound_array_buffer.get()) {
4445 GLuint client_id = 0;
4446 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4447 &client_id);
4448 *params = client_id;
4449 } else {
4450 *params = 0;
4453 return true;
4454 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4455 *num_written = 1;
4456 if (params) {
4457 if (state_.vertex_attrib_manager->element_array_buffer()) {
4458 GLuint client_id = 0;
4459 buffer_manager()->GetClientId(
4460 state_.vertex_attrib_manager->element_array_buffer()->
4461 service_id(), &client_id);
4462 *params = client_id;
4463 } else {
4464 *params = 0;
4467 return true;
4468 case GL_FRAMEBUFFER_BINDING:
4469 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4470 *num_written = 1;
4471 if (params) {
4472 Framebuffer* framebuffer =
4473 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4474 if (framebuffer) {
4475 GLuint client_id = 0;
4476 framebuffer_manager()->GetClientId(
4477 framebuffer->service_id(), &client_id);
4478 *params = client_id;
4479 } else {
4480 *params = 0;
4483 return true;
4484 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4485 *num_written = 1;
4486 if (params) {
4487 Framebuffer* framebuffer =
4488 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4489 if (framebuffer) {
4490 GLuint client_id = 0;
4491 framebuffer_manager()->GetClientId(
4492 framebuffer->service_id(), &client_id);
4493 *params = client_id;
4494 } else {
4495 *params = 0;
4498 return true;
4499 case GL_RENDERBUFFER_BINDING:
4500 *num_written = 1;
4501 if (params) {
4502 Renderbuffer* renderbuffer =
4503 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4504 if (renderbuffer) {
4505 *params = renderbuffer->client_id();
4506 } else {
4507 *params = 0;
4510 return true;
4511 case GL_CURRENT_PROGRAM:
4512 *num_written = 1;
4513 if (params) {
4514 if (state_.current_program.get()) {
4515 GLuint client_id = 0;
4516 program_manager()->GetClientId(
4517 state_.current_program->service_id(), &client_id);
4518 *params = client_id;
4519 } else {
4520 *params = 0;
4523 return true;
4524 case GL_VERTEX_ARRAY_BINDING_OES:
4525 *num_written = 1;
4526 if (params) {
4527 if (state_.vertex_attrib_manager.get() !=
4528 state_.default_vertex_attrib_manager.get()) {
4529 GLuint client_id = 0;
4530 vertex_array_manager_->GetClientId(
4531 state_.vertex_attrib_manager->service_id(), &client_id);
4532 *params = client_id;
4533 } else {
4534 *params = 0;
4537 return true;
4538 case GL_TEXTURE_BINDING_2D:
4539 *num_written = 1;
4540 if (params) {
4541 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4542 if (unit.bound_texture_2d.get()) {
4543 *params = unit.bound_texture_2d->client_id();
4544 } else {
4545 *params = 0;
4548 return true;
4549 case GL_TEXTURE_BINDING_CUBE_MAP:
4550 *num_written = 1;
4551 if (params) {
4552 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4553 if (unit.bound_texture_cube_map.get()) {
4554 *params = unit.bound_texture_cube_map->client_id();
4555 } else {
4556 *params = 0;
4559 return true;
4560 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4561 *num_written = 1;
4562 if (params) {
4563 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4564 if (unit.bound_texture_external_oes.get()) {
4565 *params = unit.bound_texture_external_oes->client_id();
4566 } else {
4567 *params = 0;
4570 return true;
4571 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4572 *num_written = 1;
4573 if (params) {
4574 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4575 if (unit.bound_texture_rectangle_arb.get()) {
4576 *params = unit.bound_texture_rectangle_arb->client_id();
4577 } else {
4578 *params = 0;
4581 return true;
4582 case GL_UNPACK_FLIP_Y_CHROMIUM:
4583 *num_written = 1;
4584 if (params) {
4585 params[0] = unpack_flip_y_;
4587 return true;
4588 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4589 *num_written = 1;
4590 if (params) {
4591 params[0] = unpack_premultiply_alpha_;
4593 return true;
4594 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4595 *num_written = 1;
4596 if (params) {
4597 params[0] = unpack_unpremultiply_alpha_;
4599 return true;
4600 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
4601 *num_written = 1;
4602 if (params) {
4603 params[0] = group_->bind_generates_resource() ? 1 : 0;
4605 return true;
4606 default:
4607 if (pname >= GL_DRAW_BUFFER0_ARB &&
4608 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4609 *num_written = 1;
4610 if (params) {
4611 Framebuffer* framebuffer =
4612 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4613 if (framebuffer) {
4614 params[0] = framebuffer->GetDrawBuffer(pname);
4615 } else { // backbuffer
4616 if (pname == GL_DRAW_BUFFER0_ARB)
4617 params[0] = group_->draw_buffer();
4618 else
4619 params[0] = GL_NONE;
4622 return true;
4624 *num_written = util_.GLGetNumValuesReturned(pname);
4625 return false;
4629 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4630 GLenum pname, GLsizei* num_values) {
4631 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4632 return true;
4634 return GetHelper(pname, NULL, num_values);
4637 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4638 if (GL_MAX_SAMPLES == pname &&
4639 features().use_img_for_multisampled_render_to_texture) {
4640 return GL_MAX_SAMPLES_IMG;
4642 return pname;
4645 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4646 DCHECK(params);
4647 GLsizei num_written = 0;
4648 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4649 scoped_ptr<GLint[]> values(new GLint[num_written]);
4650 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4651 GetHelper(pname, values.get(), &num_written);
4653 for (GLsizei ii = 0; ii < num_written; ++ii) {
4654 params[ii] = static_cast<GLboolean>(values[ii]);
4656 } else {
4657 pname = AdjustGetPname(pname);
4658 glGetBooleanv(pname, params);
4662 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4663 DCHECK(params);
4664 GLsizei num_written = 0;
4665 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4666 if (GetHelper(pname, NULL, &num_written)) {
4667 scoped_ptr<GLint[]> values(new GLint[num_written]);
4668 GetHelper(pname, values.get(), &num_written);
4669 for (GLsizei ii = 0; ii < num_written; ++ii) {
4670 params[ii] = static_cast<GLfloat>(values[ii]);
4672 } else {
4673 pname = AdjustGetPname(pname);
4674 glGetFloatv(pname, params);
4679 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4680 DCHECK(params);
4681 GLsizei num_written;
4682 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4683 !GetHelper(pname, params, &num_written)) {
4684 pname = AdjustGetPname(pname);
4685 glGetIntegerv(pname, params);
4689 void GLES2DecoderImpl::DoGetProgramiv(
4690 GLuint program_id, GLenum pname, GLint* params) {
4691 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4692 if (!program) {
4693 return;
4695 program->GetProgramiv(pname, params);
4698 void GLES2DecoderImpl::DoGetBufferParameteriv(
4699 GLenum target, GLenum pname, GLint* params) {
4700 // Just delegate it. Some validation is actually done before this.
4701 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4702 &state_, target, pname, params);
4705 void GLES2DecoderImpl::DoBindAttribLocation(
4706 GLuint program_id, GLuint index, const char* name) {
4707 if (!StringIsValidForGLES(name)) {
4708 LOCAL_SET_GL_ERROR(
4709 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4710 return;
4712 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4713 LOCAL_SET_GL_ERROR(
4714 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4715 return;
4717 if (index >= group_->max_vertex_attribs()) {
4718 LOCAL_SET_GL_ERROR(
4719 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4720 return;
4722 Program* program = GetProgramInfoNotShader(
4723 program_id, "glBindAttribLocation");
4724 if (!program) {
4725 return;
4727 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4728 glBindAttribLocation(program->service_id(), index, name);
4731 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4732 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
4733 GLuint program = static_cast<GLuint>(c.program);
4734 GLuint index = static_cast<GLuint>(c.index);
4735 Bucket* bucket = GetBucket(c.name_bucket_id);
4736 if (!bucket || bucket->size() == 0) {
4737 return error::kInvalidArguments;
4739 std::string name_str;
4740 if (!bucket->GetAsString(&name_str)) {
4741 return error::kInvalidArguments;
4743 DoBindAttribLocation(program, index, name_str.c_str());
4744 return error::kNoError;
4747 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4748 GLuint program_id, GLint location, const char* name) {
4749 if (!StringIsValidForGLES(name)) {
4750 LOCAL_SET_GL_ERROR(
4751 GL_INVALID_VALUE,
4752 "glBindUniformLocationCHROMIUM", "Invalid character");
4753 return;
4755 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4756 LOCAL_SET_GL_ERROR(
4757 GL_INVALID_OPERATION,
4758 "glBindUniformLocationCHROMIUM", "reserved prefix");
4759 return;
4761 if (location < 0 || static_cast<uint32>(location) >=
4762 (group_->max_fragment_uniform_vectors() +
4763 group_->max_vertex_uniform_vectors()) * 4) {
4764 LOCAL_SET_GL_ERROR(
4765 GL_INVALID_VALUE,
4766 "glBindUniformLocationCHROMIUM", "location out of range");
4767 return;
4769 Program* program = GetProgramInfoNotShader(
4770 program_id, "glBindUniformLocationCHROMIUM");
4771 if (!program) {
4772 return;
4774 if (!program->SetUniformLocationBinding(name, location)) {
4775 LOCAL_SET_GL_ERROR(
4776 GL_INVALID_VALUE,
4777 "glBindUniformLocationCHROMIUM", "location out of range");
4781 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4782 uint32 immediate_data_size,
4783 const cmds::BindUniformLocationCHROMIUMBucket& c) {
4784 GLuint program = static_cast<GLuint>(c.program);
4785 GLint location = static_cast<GLint>(c.location);
4786 Bucket* bucket = GetBucket(c.name_bucket_id);
4787 if (!bucket || bucket->size() == 0) {
4788 return error::kInvalidArguments;
4790 std::string name_str;
4791 if (!bucket->GetAsString(&name_str)) {
4792 return error::kInvalidArguments;
4794 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4795 return error::kNoError;
4798 error::Error GLES2DecoderImpl::HandleDeleteShader(
4799 uint32 immediate_data_size, const cmds::DeleteShader& c) {
4800 GLuint client_id = c.shader;
4801 if (client_id) {
4802 Shader* shader = GetShader(client_id);
4803 if (shader) {
4804 if (!shader->IsDeleted()) {
4805 glDeleteShader(shader->service_id());
4806 shader_manager()->MarkAsDeleted(shader);
4808 } else {
4809 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4812 return error::kNoError;
4815 error::Error GLES2DecoderImpl::HandleDeleteProgram(
4816 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
4817 GLuint client_id = c.program;
4818 if (client_id) {
4819 Program* program = GetProgram(client_id);
4820 if (program) {
4821 if (!program->IsDeleted()) {
4822 program_manager()->MarkAsDeleted(shader_manager(), program);
4824 } else {
4825 LOCAL_SET_GL_ERROR(
4826 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4829 return error::kNoError;
4832 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4833 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4834 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4835 for (GLsizei ii = 0; ii < n; ++ii) {
4836 id_allocator->FreeID(ids[ii]);
4840 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4841 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
4842 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4843 GLsizei n = static_cast<GLsizei>(c.n);
4844 uint32 data_size;
4845 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4846 return error::kOutOfBounds;
4848 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4849 c.ids_shm_id, c.ids_shm_offset, data_size);
4850 if (n < 0) {
4851 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
4852 return error::kNoError;
4854 if (ids == NULL) {
4855 return error::kOutOfBounds;
4857 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4858 return error::kNoError;
4861 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4862 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4863 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4864 if (id_offset == 0) {
4865 for (GLsizei ii = 0; ii < n; ++ii) {
4866 ids[ii] = id_allocator->AllocateID();
4868 } else {
4869 for (GLsizei ii = 0; ii < n; ++ii) {
4870 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4871 id_offset = ids[ii] + 1;
4876 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4877 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
4878 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4879 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4880 GLsizei n = static_cast<GLsizei>(c.n);
4881 uint32 data_size;
4882 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4883 return error::kOutOfBounds;
4885 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4886 c.ids_shm_id, c.ids_shm_offset, data_size);
4887 if (n < 0) {
4888 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
4889 return error::kNoError;
4891 if (ids == NULL) {
4892 return error::kOutOfBounds;
4894 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4895 return error::kNoError;
4898 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4899 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4900 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4901 for (GLsizei ii = 0; ii < n; ++ii) {
4902 if (!id_allocator->MarkAsUsed(ids[ii])) {
4903 for (GLsizei jj = 0; jj < ii; ++jj) {
4904 id_allocator->FreeID(ids[jj]);
4906 LOCAL_SET_GL_ERROR(
4907 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4908 "attempt to register id that already exists");
4909 return;
4914 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4915 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
4916 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4917 GLsizei n = static_cast<GLsizei>(c.n);
4918 uint32 data_size;
4919 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4920 return error::kOutOfBounds;
4922 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4923 c.ids_shm_id, c.ids_shm_offset, data_size);
4924 if (n < 0) {
4925 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
4926 return error::kNoError;
4928 if (ids == NULL) {
4929 return error::kOutOfBounds;
4931 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
4932 return error::kNoError;
4935 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
4936 DCHECK(!ShouldDeferDraws());
4937 if (CheckBoundFramebuffersValid("glClear")) {
4938 ApplyDirtyState();
4939 glClear(mask);
4941 return error::kNoError;
4944 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4945 GLenum target, GLenum attachment, GLenum renderbuffertarget,
4946 GLuint client_renderbuffer_id) {
4947 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4948 if (!framebuffer) {
4949 LOCAL_SET_GL_ERROR(
4950 GL_INVALID_OPERATION,
4951 "glFramebufferRenderbuffer", "no framebuffer bound");
4952 return;
4954 GLuint service_id = 0;
4955 Renderbuffer* renderbuffer = NULL;
4956 if (client_renderbuffer_id) {
4957 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4958 if (!renderbuffer) {
4959 LOCAL_SET_GL_ERROR(
4960 GL_INVALID_OPERATION,
4961 "glFramebufferRenderbuffer", "unknown renderbuffer");
4962 return;
4964 service_id = renderbuffer->service_id();
4966 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4967 glFramebufferRenderbufferEXT(
4968 target, attachment, renderbuffertarget, service_id);
4969 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4970 if (error == GL_NO_ERROR) {
4971 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
4973 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
4974 framebuffer_state_.clear_state_dirty = true;
4976 OnFboChanged();
4979 void GLES2DecoderImpl::DoDisable(GLenum cap) {
4980 if (SetCapabilityState(cap, false)) {
4981 glDisable(cap);
4985 void GLES2DecoderImpl::DoEnable(GLenum cap) {
4986 if (SetCapabilityState(cap, true)) {
4987 glEnable(cap);
4991 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4992 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4993 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4994 glDepthRange(znear, zfar);
4997 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
4998 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4999 state_.sample_coverage_invert = (invert != 0);
5000 glSampleCoverage(state_.sample_coverage_value, invert);
5003 // Assumes framebuffer is complete.
5004 void GLES2DecoderImpl::ClearUnclearedAttachments(
5005 GLenum target, Framebuffer* framebuffer) {
5006 if (target == GL_READ_FRAMEBUFFER_EXT) {
5007 // bind this to the DRAW point, clear then bind back to READ
5008 // TODO(gman): I don't think there is any guarantee that an FBO that
5009 // is complete on the READ attachment will be complete as a DRAW
5010 // attachment.
5011 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5012 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5014 GLbitfield clear_bits = 0;
5015 if (framebuffer->HasUnclearedColorAttachments()) {
5016 glClearColor(
5017 0.0f, 0.0f, 0.0f,
5018 (GLES2Util::GetChannelsForFormat(
5019 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5020 1.0f);
5021 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5022 clear_bits |= GL_COLOR_BUFFER_BIT;
5023 framebuffer->PrepareDrawBuffersForClear();
5026 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5027 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5028 glClearStencil(0);
5029 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
5030 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
5031 clear_bits |= GL_STENCIL_BUFFER_BIT;
5034 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5035 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5036 glClearDepth(1.0f);
5037 state_.SetDeviceDepthMask(GL_TRUE);
5038 clear_bits |= GL_DEPTH_BUFFER_BIT;
5041 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5042 glClear(clear_bits);
5044 if ((clear_bits | GL_COLOR_BUFFER_BIT) != 0)
5045 framebuffer->RestoreDrawBuffersAfterClear();
5047 framebuffer_manager()->MarkAttachmentsAsCleared(
5048 framebuffer, renderbuffer_manager(), texture_manager());
5050 RestoreClearState();
5052 if (target == GL_READ_FRAMEBUFFER_EXT) {
5053 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5054 Framebuffer* draw_framebuffer =
5055 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5056 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5057 GetBackbufferServiceId();
5058 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5062 void GLES2DecoderImpl::RestoreClearState() {
5063 framebuffer_state_.clear_state_dirty = true;
5064 glClearColor(
5065 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5066 state_.color_clear_alpha);
5067 glClearStencil(state_.stencil_clear);
5068 glClearDepth(state_.depth_clear);
5069 if (state_.enable_flags.scissor_test) {
5070 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5074 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5075 Framebuffer* framebuffer =
5076 GetFramebufferInfoForTarget(target);
5077 if (!framebuffer) {
5078 return GL_FRAMEBUFFER_COMPLETE;
5080 GLenum completeness = framebuffer->IsPossiblyComplete();
5081 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5082 return completeness;
5084 return framebuffer->GetStatus(texture_manager(), target);
5087 void GLES2DecoderImpl::DoFramebufferTexture2D(
5088 GLenum target, GLenum attachment, GLenum textarget,
5089 GLuint client_texture_id, GLint level) {
5090 DoFramebufferTexture2DCommon(
5091 "glFramebufferTexture2D", target, attachment,
5092 textarget, client_texture_id, level, 0);
5095 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5096 GLenum target, GLenum attachment, GLenum textarget,
5097 GLuint client_texture_id, GLint level, GLsizei samples) {
5098 DoFramebufferTexture2DCommon(
5099 "glFramebufferTexture2DMultisample", target, attachment,
5100 textarget, client_texture_id, level, samples);
5103 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5104 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5105 GLuint client_texture_id, GLint level, GLsizei samples) {
5106 if (samples > renderbuffer_manager()->max_samples()) {
5107 LOCAL_SET_GL_ERROR(
5108 GL_INVALID_VALUE,
5109 "glFramebufferTexture2DMultisample", "samples too large");
5110 return;
5112 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5113 if (!framebuffer) {
5114 LOCAL_SET_GL_ERROR(
5115 GL_INVALID_OPERATION,
5116 name, "no framebuffer bound.");
5117 return;
5119 GLuint service_id = 0;
5120 TextureRef* texture_ref = NULL;
5121 if (client_texture_id) {
5122 texture_ref = GetTexture(client_texture_id);
5123 if (!texture_ref) {
5124 LOCAL_SET_GL_ERROR(
5125 GL_INVALID_OPERATION,
5126 name, "unknown texture_ref");
5127 return;
5129 service_id = texture_ref->service_id();
5132 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5133 LOCAL_SET_GL_ERROR(
5134 GL_INVALID_VALUE,
5135 name, "level out of range");
5136 return;
5139 if (texture_ref)
5140 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5142 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5143 if (0 == samples) {
5144 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5145 } else {
5146 if (features().use_img_for_multisampled_render_to_texture) {
5147 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5148 service_id, level, samples);
5149 } else {
5150 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5151 service_id, level, samples);
5154 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5155 if (error == GL_NO_ERROR) {
5156 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5157 samples);
5159 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5160 framebuffer_state_.clear_state_dirty = true;
5163 if (texture_ref)
5164 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5166 OnFboChanged();
5169 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5170 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5171 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5172 if (!framebuffer) {
5173 LOCAL_SET_GL_ERROR(
5174 GL_INVALID_OPERATION,
5175 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5176 return;
5178 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5179 const Framebuffer::Attachment* attachment_object =
5180 framebuffer->GetAttachment(attachment);
5181 *params = attachment_object ? attachment_object->object_name() : 0;
5182 } else {
5183 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5184 features().use_img_for_multisampled_render_to_texture) {
5185 pname = GL_TEXTURE_SAMPLES_IMG;
5187 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5191 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5192 GLenum target, GLenum pname, GLint* params) {
5193 Renderbuffer* renderbuffer =
5194 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5195 if (!renderbuffer) {
5196 LOCAL_SET_GL_ERROR(
5197 GL_INVALID_OPERATION,
5198 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5199 return;
5201 switch (pname) {
5202 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5203 *params = renderbuffer->internal_format();
5204 break;
5205 case GL_RENDERBUFFER_WIDTH:
5206 *params = renderbuffer->width();
5207 break;
5208 case GL_RENDERBUFFER_HEIGHT:
5209 *params = renderbuffer->height();
5210 break;
5211 case GL_RENDERBUFFER_SAMPLES_EXT:
5212 if (features().use_img_for_multisampled_render_to_texture) {
5213 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5214 params);
5215 } else {
5216 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5217 params);
5219 default:
5220 glGetRenderbufferParameterivEXT(target, pname, params);
5221 break;
5225 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5226 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5227 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5228 GLbitfield mask, GLenum filter) {
5229 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5231 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5232 return;
5235 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5236 BlitFramebufferHelper(
5237 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5238 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5239 state_.enable_flags.scissor_test);
5242 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5243 const FeatureInfo* feature_info,
5244 GLenum target,
5245 GLsizei samples,
5246 GLenum internal_format,
5247 GLsizei width,
5248 GLsizei height) {
5249 // TODO(sievers): This could be resolved at the GL binding level, but the
5250 // binding process is currently a bit too 'brute force'.
5251 if (feature_info->feature_flags().is_angle) {
5252 glRenderbufferStorageMultisampleANGLE(
5253 target, samples, internal_format, width, height);
5254 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5255 glRenderbufferStorageMultisample(
5256 target, samples, internal_format, width, height);
5257 } else {
5258 glRenderbufferStorageMultisampleEXT(
5259 target, samples, internal_format, width, height);
5263 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5264 GLint srcY0,
5265 GLint srcX1,
5266 GLint srcY1,
5267 GLint dstX0,
5268 GLint dstY0,
5269 GLint dstX1,
5270 GLint dstY1,
5271 GLbitfield mask,
5272 GLenum filter) {
5273 // TODO(sievers): This could be resolved at the GL binding level, but the
5274 // binding process is currently a bit too 'brute force'.
5275 if (feature_info_->feature_flags().is_angle) {
5276 glBlitFramebufferANGLE(
5277 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5278 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5279 glBlitFramebuffer(
5280 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5281 } else {
5282 glBlitFramebufferEXT(
5283 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5287 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5288 GLsizei samples,
5289 GLenum internalformat,
5290 GLsizei width,
5291 GLsizei height) {
5292 if (samples > renderbuffer_manager()->max_samples()) {
5293 LOCAL_SET_GL_ERROR(
5294 GL_INVALID_VALUE,
5295 "glRenderbufferStorageMultisample", "samples too large");
5296 return false;
5299 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5300 height > renderbuffer_manager()->max_renderbuffer_size()) {
5301 LOCAL_SET_GL_ERROR(
5302 GL_INVALID_VALUE,
5303 "glRenderbufferStorageMultisample", "dimensions too large");
5304 return false;
5307 uint32 estimated_size = 0;
5308 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5309 width, height, samples, internalformat, &estimated_size)) {
5310 LOCAL_SET_GL_ERROR(
5311 GL_OUT_OF_MEMORY,
5312 "glRenderbufferStorageMultisample", "dimensions too large");
5313 return false;
5316 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5317 LOCAL_SET_GL_ERROR(
5318 GL_OUT_OF_MEMORY,
5319 "glRenderbufferStorageMultisample", "out of memory");
5320 return false;
5323 return true;
5326 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5327 GLenum target, GLsizei samples, GLenum internalformat,
5328 GLsizei width, GLsizei height) {
5329 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5330 if (!renderbuffer) {
5331 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5332 "glRenderbufferStorageMultisampleCHROMIUM",
5333 "no renderbuffer bound");
5334 return;
5337 if (!ValidateRenderbufferStorageMultisample(
5338 samples, internalformat, width, height)) {
5339 return;
5342 GLenum impl_format =
5343 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5344 internalformat);
5345 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5346 "glRenderbufferStorageMultisampleCHROMIUM");
5347 RenderbufferStorageMultisampleHelper(
5348 feature_info_, target, samples, impl_format, width, height);
5349 GLenum error =
5350 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5351 if (error == GL_NO_ERROR) {
5353 if (workarounds().validate_multisample_buffer_allocation) {
5354 if (!VerifyMultisampleRenderbufferIntegrity(
5355 renderbuffer->service_id(), impl_format)) {
5356 LOCAL_SET_GL_ERROR(
5357 GL_OUT_OF_MEMORY,
5358 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5359 return;
5363 // TODO(gman): If renderbuffers tracked which framebuffers they were
5364 // attached to we could just mark those framebuffers as not complete.
5365 framebuffer_manager()->IncFramebufferStateChangeCount();
5366 renderbuffer_manager()->SetInfo(
5367 renderbuffer, samples, internalformat, width, height);
5371 // This is the handler for multisampled_render_to_texture extensions.
5372 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5373 GLenum target, GLsizei samples, GLenum internalformat,
5374 GLsizei width, GLsizei height) {
5375 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5376 if (!renderbuffer) {
5377 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5378 "glRenderbufferStorageMultisampleEXT",
5379 "no renderbuffer bound");
5380 return;
5383 if (!ValidateRenderbufferStorageMultisample(
5384 samples, internalformat, width, height)) {
5385 return;
5388 GLenum impl_format =
5389 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5390 internalformat);
5391 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5392 if (features().use_img_for_multisampled_render_to_texture) {
5393 glRenderbufferStorageMultisampleIMG(
5394 target, samples, impl_format, width, height);
5395 } else {
5396 glRenderbufferStorageMultisampleEXT(
5397 target, samples, impl_format, width, height);
5399 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5400 if (error == GL_NO_ERROR) {
5401 // TODO(gman): If renderbuffers tracked which framebuffers they were
5402 // attached to we could just mark those framebuffers as not complete.
5403 framebuffer_manager()->IncFramebufferStateChangeCount();
5404 renderbuffer_manager()->SetInfo(
5405 renderbuffer, samples, internalformat, width, height);
5409 // This function validates the allocation of a multisampled renderbuffer
5410 // by clearing it to a key color, blitting the contents to a texture, and
5411 // reading back the color to ensure it matches the key.
5412 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5413 GLuint renderbuffer, GLenum format) {
5415 // Only validate color buffers.
5416 // These formats have been selected because they are very common or are known
5417 // to be used by the WebGL backbuffer. If problems are observed with other
5418 // color formats they can be added here.
5419 switch(format) {
5420 case GL_RGB:
5421 case GL_RGB8:
5422 case GL_RGBA:
5423 case GL_RGBA8:
5424 break;
5425 default:
5426 return true;
5429 GLint draw_framebuffer, read_framebuffer;
5431 // Cache framebuffer and texture bindings.
5432 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5433 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5435 if (!validation_texture_) {
5436 GLint bound_texture;
5437 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5439 // Create additional resources needed for the verification.
5440 glGenTextures(1, &validation_texture_);
5441 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5442 glGenFramebuffersEXT(1, &validation_fbo_);
5444 // Texture only needs to be 1x1.
5445 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5446 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5447 GL_UNSIGNED_BYTE, NULL);
5449 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5450 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5451 GL_TEXTURE_2D, validation_texture_, 0);
5453 glBindTexture(GL_TEXTURE_2D, bound_texture);
5456 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5457 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5458 GL_RENDERBUFFER, renderbuffer);
5460 // Cache current state and reset it to the values we require.
5461 GLboolean scissor_enabled = false;
5462 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5463 if (scissor_enabled)
5464 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5466 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5467 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5468 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5470 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5471 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5472 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5474 // Clear the buffer to the desired key color.
5475 glClear(GL_COLOR_BUFFER_BIT);
5477 // Blit from the multisample buffer to a standard texture.
5478 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5479 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5481 BlitFramebufferHelper(
5482 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5484 // Read a pixel from the buffer.
5485 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5487 unsigned char pixel[3] = {0, 0, 0};
5488 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5490 // Detach the renderbuffer.
5491 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5492 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5493 GL_RENDERBUFFER, 0);
5495 // Restore cached state.
5496 if (scissor_enabled)
5497 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5499 state_.SetDeviceColorMask(
5500 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5501 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5502 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5503 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5505 // Return true if the pixel matched the desired key color.
5506 return (pixel[0] == 0xFF &&
5507 pixel[1] == 0x00 &&
5508 pixel[2] == 0xFF);
5511 void GLES2DecoderImpl::DoRenderbufferStorage(
5512 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5513 Renderbuffer* renderbuffer =
5514 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5515 if (!renderbuffer) {
5516 LOCAL_SET_GL_ERROR(
5517 GL_INVALID_OPERATION,
5518 "glRenderbufferStorage", "no renderbuffer bound");
5519 return;
5522 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5523 height > renderbuffer_manager()->max_renderbuffer_size()) {
5524 LOCAL_SET_GL_ERROR(
5525 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5526 return;
5529 uint32 estimated_size = 0;
5530 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5531 width, height, 1, internalformat, &estimated_size)) {
5532 LOCAL_SET_GL_ERROR(
5533 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5534 return;
5537 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5538 LOCAL_SET_GL_ERROR(
5539 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5540 return;
5543 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5544 glRenderbufferStorageEXT(
5545 target,
5546 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5547 internalformat),
5548 width,
5549 height);
5550 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5551 if (error == GL_NO_ERROR) {
5552 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5553 // we could just mark those framebuffers as not complete.
5554 framebuffer_manager()->IncFramebufferStateChangeCount();
5555 renderbuffer_manager()->SetInfo(
5556 renderbuffer, 1, internalformat, width, height);
5560 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5561 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5562 Program* program = GetProgramInfoNotShader(
5563 program_id, "glLinkProgram");
5564 if (!program) {
5565 return;
5568 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5569 ShaderTranslator* vertex_translator = NULL;
5570 ShaderTranslator* fragment_translator = NULL;
5571 if (use_shader_translator_) {
5572 vertex_translator = vertex_translator_.get();
5573 fragment_translator = fragment_translator_.get();
5575 if (program->Link(shader_manager(),
5576 vertex_translator,
5577 fragment_translator,
5578 workarounds().count_all_in_varyings_packing ?
5579 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5580 shader_cache_callback_)) {
5581 if (program == state_.current_program.get()) {
5582 if (workarounds().use_current_program_after_successful_link)
5583 glUseProgram(program->service_id());
5584 if (workarounds().clear_uniforms_before_first_program_use)
5585 program_manager()->ClearUniforms(program);
5590 void GLES2DecoderImpl::DoTexParameterf(
5591 GLenum target, GLenum pname, GLfloat param) {
5592 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5593 &state_, target);
5594 if (!texture) {
5595 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5596 return;
5599 texture_manager()->SetParameterf(
5600 "glTexParameterf", GetErrorState(), texture, pname, param);
5603 void GLES2DecoderImpl::DoTexParameteri(
5604 GLenum target, GLenum pname, GLint param) {
5605 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5606 &state_, target);
5607 if (!texture) {
5608 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5609 return;
5612 texture_manager()->SetParameteri(
5613 "glTexParameteri", GetErrorState(), texture, pname, param);
5616 void GLES2DecoderImpl::DoTexParameterfv(
5617 GLenum target, GLenum pname, const GLfloat* params) {
5618 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5619 &state_, target);
5620 if (!texture) {
5621 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5622 return;
5625 texture_manager()->SetParameterf(
5626 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5629 void GLES2DecoderImpl::DoTexParameteriv(
5630 GLenum target, GLenum pname, const GLint* params) {
5631 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5632 &state_, target);
5633 if (!texture) {
5634 LOCAL_SET_GL_ERROR(
5635 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5636 return;
5639 texture_manager()->SetParameteri(
5640 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5643 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5644 if (!state_.current_program.get()) {
5645 // The program does not exist.
5646 LOCAL_SET_GL_ERROR(
5647 GL_INVALID_OPERATION, function_name, "no program in use");
5648 return false;
5650 if (!state_.current_program->InUse()) {
5651 LOCAL_SET_GL_ERROR(
5652 GL_INVALID_OPERATION, function_name, "program not linked");
5653 return false;
5655 return true;
5658 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5659 GLint location, const char* function_name) {
5660 if (!CheckCurrentProgram(function_name)) {
5661 return false;
5663 return location != -1;
5666 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5667 GLint fake_location,
5668 const char* function_name,
5669 Program::UniformApiType api_type,
5670 GLint* real_location,
5671 GLenum* type,
5672 GLsizei* count) {
5673 DCHECK(type);
5674 DCHECK(count);
5675 DCHECK(real_location);
5677 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5678 return false;
5680 GLint array_index = -1;
5681 const Program::UniformInfo* info =
5682 state_.current_program->GetUniformInfoByFakeLocation(
5683 fake_location, real_location, &array_index);
5684 if (!info) {
5685 LOCAL_SET_GL_ERROR(
5686 GL_INVALID_OPERATION, function_name, "unknown location");
5687 return false;
5690 if ((api_type & info->accepts_api_type) == 0) {
5691 LOCAL_SET_GL_ERROR(
5692 GL_INVALID_OPERATION, function_name,
5693 "wrong uniform function for type");
5694 return false;
5696 if (*count > 1 && !info->is_array) {
5697 LOCAL_SET_GL_ERROR(
5698 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5699 return false;
5701 *count = std::min(info->size - array_index, *count);
5702 if (*count <= 0) {
5703 return false;
5705 *type = info->type;
5706 return true;
5709 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5710 GLenum type = 0;
5711 GLsizei count = 1;
5712 GLint real_location = -1;
5713 if (!PrepForSetUniformByLocation(fake_location,
5714 "glUniform1i",
5715 Program::kUniform1i,
5716 &real_location,
5717 &type,
5718 &count)) {
5719 return;
5721 if (!state_.current_program->SetSamplers(
5722 state_.texture_units.size(), fake_location, 1, &v0)) {
5723 LOCAL_SET_GL_ERROR(
5724 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5725 return;
5727 glUniform1i(real_location, v0);
5730 void GLES2DecoderImpl::DoUniform1iv(
5731 GLint fake_location, GLsizei count, const GLint *value) {
5732 GLenum type = 0;
5733 GLint real_location = -1;
5734 if (!PrepForSetUniformByLocation(fake_location,
5735 "glUniform1iv",
5736 Program::kUniform1i,
5737 &real_location,
5738 &type,
5739 &count)) {
5740 return;
5742 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5743 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5744 if (!state_.current_program->SetSamplers(
5745 state_.texture_units.size(), fake_location, count, value)) {
5746 LOCAL_SET_GL_ERROR(
5747 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5748 return;
5751 glUniform1iv(real_location, count, value);
5754 void GLES2DecoderImpl::DoUniform1fv(
5755 GLint fake_location, GLsizei count, const GLfloat* value) {
5756 GLenum type = 0;
5757 GLint real_location = -1;
5758 if (!PrepForSetUniformByLocation(fake_location,
5759 "glUniform1fv",
5760 Program::kUniform1f,
5761 &real_location,
5762 &type,
5763 &count)) {
5764 return;
5766 if (type == GL_BOOL) {
5767 scoped_ptr<GLint[]> temp(new GLint[count]);
5768 for (GLsizei ii = 0; ii < count; ++ii) {
5769 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5771 DoUniform1iv(real_location, count, temp.get());
5772 } else {
5773 glUniform1fv(real_location, count, value);
5777 void GLES2DecoderImpl::DoUniform2fv(
5778 GLint fake_location, GLsizei count, const GLfloat* value) {
5779 GLenum type = 0;
5780 GLint real_location = -1;
5781 if (!PrepForSetUniformByLocation(fake_location,
5782 "glUniform2fv",
5783 Program::kUniform2f,
5784 &real_location,
5785 &type,
5786 &count)) {
5787 return;
5789 if (type == GL_BOOL_VEC2) {
5790 GLsizei num_values = count * 2;
5791 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5792 for (GLsizei ii = 0; ii < num_values; ++ii) {
5793 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5795 glUniform2iv(real_location, count, temp.get());
5796 } else {
5797 glUniform2fv(real_location, count, value);
5801 void GLES2DecoderImpl::DoUniform3fv(
5802 GLint fake_location, GLsizei count, const GLfloat* value) {
5803 GLenum type = 0;
5804 GLint real_location = -1;
5805 if (!PrepForSetUniformByLocation(fake_location,
5806 "glUniform3fv",
5807 Program::kUniform3f,
5808 &real_location,
5809 &type,
5810 &count)) {
5811 return;
5813 if (type == GL_BOOL_VEC3) {
5814 GLsizei num_values = count * 3;
5815 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5816 for (GLsizei ii = 0; ii < num_values; ++ii) {
5817 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5819 glUniform3iv(real_location, count, temp.get());
5820 } else {
5821 glUniform3fv(real_location, count, value);
5825 void GLES2DecoderImpl::DoUniform4fv(
5826 GLint fake_location, GLsizei count, const GLfloat* value) {
5827 GLenum type = 0;
5828 GLint real_location = -1;
5829 if (!PrepForSetUniformByLocation(fake_location,
5830 "glUniform4fv",
5831 Program::kUniform4f,
5832 &real_location,
5833 &type,
5834 &count)) {
5835 return;
5837 if (type == GL_BOOL_VEC4) {
5838 GLsizei num_values = count * 4;
5839 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5840 for (GLsizei ii = 0; ii < num_values; ++ii) {
5841 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5843 glUniform4iv(real_location, count, temp.get());
5844 } else {
5845 glUniform4fv(real_location, count, value);
5849 void GLES2DecoderImpl::DoUniform2iv(
5850 GLint fake_location, GLsizei count, const GLint* value) {
5851 GLenum type = 0;
5852 GLint real_location = -1;
5853 if (!PrepForSetUniformByLocation(fake_location,
5854 "glUniform2iv",
5855 Program::kUniform2i,
5856 &real_location,
5857 &type,
5858 &count)) {
5859 return;
5861 glUniform2iv(real_location, count, value);
5864 void GLES2DecoderImpl::DoUniform3iv(
5865 GLint fake_location, GLsizei count, const GLint* value) {
5866 GLenum type = 0;
5867 GLint real_location = -1;
5868 if (!PrepForSetUniformByLocation(fake_location,
5869 "glUniform3iv",
5870 Program::kUniform3i,
5871 &real_location,
5872 &type,
5873 &count)) {
5874 return;
5876 glUniform3iv(real_location, count, value);
5879 void GLES2DecoderImpl::DoUniform4iv(
5880 GLint fake_location, GLsizei count, const GLint* value) {
5881 GLenum type = 0;
5882 GLint real_location = -1;
5883 if (!PrepForSetUniformByLocation(fake_location,
5884 "glUniform4iv",
5885 Program::kUniform4i,
5886 &real_location,
5887 &type,
5888 &count)) {
5889 return;
5891 glUniform4iv(real_location, count, value);
5894 void GLES2DecoderImpl::DoUniformMatrix2fv(
5895 GLint fake_location, GLsizei count, GLboolean transpose,
5896 const GLfloat* value) {
5897 GLenum type = 0;
5898 GLint real_location = -1;
5899 if (!PrepForSetUniformByLocation(fake_location,
5900 "glUniformMatrix2fv",
5901 Program::kUniformMatrix2f,
5902 &real_location,
5903 &type,
5904 &count)) {
5905 return;
5907 glUniformMatrix2fv(real_location, count, transpose, value);
5910 void GLES2DecoderImpl::DoUniformMatrix3fv(
5911 GLint fake_location, GLsizei count, GLboolean transpose,
5912 const GLfloat* value) {
5913 GLenum type = 0;
5914 GLint real_location = -1;
5915 if (!PrepForSetUniformByLocation(fake_location,
5916 "glUniformMatrix3fv",
5917 Program::kUniformMatrix3f,
5918 &real_location,
5919 &type,
5920 &count)) {
5921 return;
5923 glUniformMatrix3fv(real_location, count, transpose, value);
5926 void GLES2DecoderImpl::DoUniformMatrix4fv(
5927 GLint fake_location, GLsizei count, GLboolean transpose,
5928 const GLfloat* value) {
5929 GLenum type = 0;
5930 GLint real_location = -1;
5931 if (!PrepForSetUniformByLocation(fake_location,
5932 "glUniformMatrix4fv",
5933 Program::kUniformMatrix4f,
5934 &real_location,
5935 &type,
5936 &count)) {
5937 return;
5939 glUniformMatrix4fv(real_location, count, transpose, value);
5942 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
5943 GLuint service_id = 0;
5944 Program* program = NULL;
5945 if (program_id) {
5946 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5947 if (!program) {
5948 return;
5950 if (!program->IsValid()) {
5951 // Program was not linked successfully. (ie, glLinkProgram)
5952 LOCAL_SET_GL_ERROR(
5953 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
5954 return;
5956 service_id = program->service_id();
5958 if (state_.current_program.get()) {
5959 program_manager()->UnuseProgram(shader_manager(),
5960 state_.current_program.get());
5962 state_.current_program = program;
5963 LogClientServiceMapping("glUseProgram", program_id, service_id);
5964 glUseProgram(service_id);
5965 if (state_.current_program.get()) {
5966 program_manager()->UseProgram(state_.current_program.get());
5967 if (workarounds().clear_uniforms_before_first_program_use)
5968 program_manager()->ClearUniforms(program);
5972 void GLES2DecoderImpl::RenderWarning(
5973 const char* filename, int line, const std::string& msg) {
5974 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
5977 void GLES2DecoderImpl::PerformanceWarning(
5978 const char* filename, int line, const std::string& msg) {
5979 logger_.LogMessage(filename, line,
5980 std::string("PERFORMANCE WARNING: ") + msg);
5983 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
5984 Texture* texture, GLenum textarget) {
5985 // Image is already in use if texture is attached to a framebuffer.
5986 if (texture && !texture->IsAttachedToFramebuffer()) {
5987 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
5988 if (image) {
5989 ScopedGLErrorSuppressor suppressor(
5990 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
5991 GetErrorState());
5992 glBindTexture(textarget, texture->service_id());
5993 image->WillUseTexImage();
5994 RestoreCurrentTextureBindings(&state_, textarget);
5999 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6000 Texture* texture, GLenum textarget) {
6001 // Image is still in use if texture is attached to a framebuffer.
6002 if (texture && !texture->IsAttachedToFramebuffer()) {
6003 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6004 if (image) {
6005 ScopedGLErrorSuppressor suppressor(
6006 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6007 GetErrorState());
6008 glBindTexture(textarget, texture->service_id());
6009 image->DidUseTexImage();
6010 RestoreCurrentTextureBindings(&state_, textarget);
6015 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6016 DCHECK(state_.current_program.get());
6017 if (!texture_manager()->HaveUnrenderableTextures() &&
6018 !texture_manager()->HaveImages()) {
6019 return true;
6022 bool textures_set = false;
6023 const Program::SamplerIndices& sampler_indices =
6024 state_.current_program->sampler_indices();
6025 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6026 const Program::UniformInfo* uniform_info =
6027 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6028 DCHECK(uniform_info);
6029 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6030 GLuint texture_unit_index = uniform_info->texture_units[jj];
6031 if (texture_unit_index < state_.texture_units.size()) {
6032 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6033 TextureRef* texture_ref =
6034 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6035 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6036 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6037 textures_set = true;
6038 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6039 glBindTexture(
6040 textarget,
6041 texture_manager()->black_texture_id(uniform_info->type));
6042 LOCAL_RENDER_WARNING(
6043 std::string("texture bound to texture unit ") +
6044 base::IntToString(texture_unit_index) +
6045 " is not renderable. It maybe non-power-of-2 and have"
6046 " incompatible texture filtering or is not"
6047 " 'texture complete'");
6048 continue;
6051 if (textarget != GL_TEXTURE_CUBE_MAP) {
6052 Texture* texture = texture_ref->texture();
6053 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6054 if (image && !texture->IsAttachedToFramebuffer()) {
6055 ScopedGLErrorSuppressor suppressor(
6056 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6057 textures_set = true;
6058 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6059 image->WillUseTexImage();
6060 continue;
6064 // else: should this be an error?
6067 return !textures_set;
6070 void GLES2DecoderImpl::RestoreStateForTextures() {
6071 DCHECK(state_.current_program.get());
6072 const Program::SamplerIndices& sampler_indices =
6073 state_.current_program->sampler_indices();
6074 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6075 const Program::UniformInfo* uniform_info =
6076 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6077 DCHECK(uniform_info);
6078 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6079 GLuint texture_unit_index = uniform_info->texture_units[jj];
6080 if (texture_unit_index < state_.texture_units.size()) {
6081 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6082 TextureRef* texture_ref =
6083 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6084 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6085 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6086 // Get the texture_ref info that was previously bound here.
6087 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6088 ? texture_unit.bound_texture_2d.get()
6089 : texture_unit.bound_texture_cube_map.get();
6090 glBindTexture(texture_unit.bind_target,
6091 texture_ref ? texture_ref->service_id() : 0);
6092 continue;
6095 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6096 Texture* texture = texture_ref->texture();
6097 gfx::GLImage* image =
6098 texture->GetLevelImage(texture_unit.bind_target, 0);
6099 if (image && !texture->IsAttachedToFramebuffer()) {
6100 ScopedGLErrorSuppressor suppressor(
6101 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6102 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6103 image->DidUseTexImage();
6104 continue;
6110 // Set the active texture back to whatever the user had it as.
6111 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6114 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6115 // Only check if there are some uncleared textures.
6116 if (!texture_manager()->HaveUnsafeTextures()) {
6117 return true;
6120 // 1: Check all textures we are about to render with.
6121 if (state_.current_program.get()) {
6122 const Program::SamplerIndices& sampler_indices =
6123 state_.current_program->sampler_indices();
6124 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6125 const Program::UniformInfo* uniform_info =
6126 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6127 DCHECK(uniform_info);
6128 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6129 GLuint texture_unit_index = uniform_info->texture_units[jj];
6130 if (texture_unit_index < state_.texture_units.size()) {
6131 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6132 TextureRef* texture_ref =
6133 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6134 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6135 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6136 return false;
6143 return true;
6146 bool GLES2DecoderImpl::IsDrawValid(
6147 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
6148 // NOTE: We specifically do not check current_program->IsValid() because
6149 // it could never be invalid since glUseProgram would have failed. While
6150 // glLinkProgram could later mark the program as invalid the previous
6151 // valid program will still function if it is still the current program.
6152 if (!state_.current_program.get()) {
6153 // The program does not exist.
6154 // But GL says no ERROR.
6155 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6156 return false;
6159 return state_.vertex_attrib_manager
6160 ->ValidateBindings(function_name,
6161 this,
6162 feature_info_.get(),
6163 state_.current_program.get(),
6164 max_vertex_accessed,
6165 primcount);
6168 bool GLES2DecoderImpl::SimulateAttrib0(
6169 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6170 DCHECK(simulated);
6171 *simulated = false;
6173 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6174 return true;
6176 const VertexAttrib* attrib =
6177 state_.vertex_attrib_manager->GetVertexAttrib(0);
6178 // If it's enabled or it's not used then we don't need to do anything.
6179 bool attrib_0_used =
6180 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6181 if (attrib->enabled() && attrib_0_used) {
6182 return true;
6185 // Make a buffer with a single repeated vec4 value enough to
6186 // simulate the constant value that is supposed to be here.
6187 // This is required to emulate GLES2 on GL.
6188 GLuint num_vertices = max_vertex_accessed + 1;
6189 uint32 size_needed = 0;
6191 if (num_vertices == 0 ||
6192 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6193 size_needed > 0x7FFFFFFFU) {
6194 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6195 return false;
6198 LOCAL_PERFORMANCE_WARNING(
6199 "Attribute 0 is disabled. This has signficant performance penalty");
6201 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6202 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6204 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6205 if (new_buffer) {
6206 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6207 GLenum error = glGetError();
6208 if (error != GL_NO_ERROR) {
6209 LOCAL_SET_GL_ERROR(
6210 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6211 return false;
6215 const Vec4& value = state_.attrib_values[0];
6216 if (new_buffer ||
6217 (attrib_0_used &&
6218 (!attrib_0_buffer_matches_value_ ||
6219 (value.v[0] != attrib_0_value_.v[0] ||
6220 value.v[1] != attrib_0_value_.v[1] ||
6221 value.v[2] != attrib_0_value_.v[2] ||
6222 value.v[3] != attrib_0_value_.v[3])))) {
6223 std::vector<Vec4> temp(num_vertices, value);
6224 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6225 attrib_0_buffer_matches_value_ = true;
6226 attrib_0_value_ = value;
6227 attrib_0_size_ = size_needed;
6230 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6232 if (attrib->divisor())
6233 glVertexAttribDivisorANGLE(0, 0);
6235 *simulated = true;
6236 return true;
6239 void GLES2DecoderImpl::RestoreStateForAttrib(
6240 GLuint attrib_index, bool restore_array_binding) {
6241 const VertexAttrib* attrib =
6242 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6243 if (restore_array_binding) {
6244 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6245 Buffer* buffer = attrib->buffer();
6246 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6247 glVertexAttribPointer(
6248 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6249 attrib->gl_stride(), ptr);
6251 if (attrib->divisor())
6252 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6253 glBindBuffer(
6254 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6255 state_.bound_array_buffer->service_id() : 0);
6257 // Never touch vertex attribute 0's state (in particular, never
6258 // disable it) when running on desktop GL because it will never be
6259 // re-enabled.
6260 if (attrib_index != 0 ||
6261 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6262 if (attrib->enabled()) {
6263 glEnableVertexAttribArray(attrib_index);
6264 } else {
6265 glDisableVertexAttribArray(attrib_index);
6270 bool GLES2DecoderImpl::SimulateFixedAttribs(
6271 const char* function_name,
6272 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6273 DCHECK(simulated);
6274 *simulated = false;
6275 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6276 return true;
6278 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6279 return true;
6282 LOCAL_PERFORMANCE_WARNING(
6283 "GL_FIXED attributes have a signficant performance penalty");
6285 // NOTE: we could be smart and try to check if a buffer is used
6286 // twice in 2 different attribs, find the overlapping parts and therefore
6287 // duplicate the minimum amount of data but this whole code path is not meant
6288 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6289 // tests so we just add to the buffer attrib used.
6291 GLuint elements_needed = 0;
6292 const VertexAttribManager::VertexAttribList& enabled_attribs =
6293 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6294 for (VertexAttribManager::VertexAttribList::const_iterator it =
6295 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6296 const VertexAttrib* attrib = *it;
6297 const Program::VertexAttrib* attrib_info =
6298 state_.current_program->GetAttribInfoByLocation(attrib->index());
6299 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6300 max_vertex_accessed);
6301 GLuint num_vertices = max_accessed + 1;
6302 if (num_vertices == 0) {
6303 LOCAL_SET_GL_ERROR(
6304 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6305 return false;
6307 if (attrib_info &&
6308 attrib->CanAccess(max_accessed) &&
6309 attrib->type() == GL_FIXED) {
6310 uint32 elements_used = 0;
6311 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6312 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6313 LOCAL_SET_GL_ERROR(
6314 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6315 return false;
6320 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6321 uint32 size_needed = 0;
6322 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6323 size_needed > 0x7FFFFFFFU) {
6324 LOCAL_SET_GL_ERROR(
6325 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6326 return false;
6329 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6331 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6332 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6333 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6334 GLenum error = glGetError();
6335 if (error != GL_NO_ERROR) {
6336 LOCAL_SET_GL_ERROR(
6337 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6338 return false;
6342 // Copy the elements and convert to float
6343 GLintptr offset = 0;
6344 for (VertexAttribManager::VertexAttribList::const_iterator it =
6345 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6346 const VertexAttrib* attrib = *it;
6347 const Program::VertexAttrib* attrib_info =
6348 state_.current_program->GetAttribInfoByLocation(attrib->index());
6349 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6350 max_vertex_accessed);
6351 GLuint num_vertices = max_accessed + 1;
6352 if (num_vertices == 0) {
6353 LOCAL_SET_GL_ERROR(
6354 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6355 return false;
6357 if (attrib_info &&
6358 attrib->CanAccess(max_accessed) &&
6359 attrib->type() == GL_FIXED) {
6360 int num_elements = attrib->size() * kSizeOfFloat;
6361 int size = num_elements * num_vertices;
6362 scoped_ptr<float[]> data(new float[size]);
6363 const int32* src = reinterpret_cast<const int32 *>(
6364 attrib->buffer()->GetRange(attrib->offset(), size));
6365 const int32* end = src + num_elements;
6366 float* dst = data.get();
6367 while (src != end) {
6368 *dst++ = static_cast<float>(*src++) / 65536.0f;
6370 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6371 glVertexAttribPointer(
6372 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6373 reinterpret_cast<GLvoid*>(offset));
6374 offset += size;
6377 *simulated = true;
6378 return true;
6381 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6382 // There's no need to call glVertexAttribPointer because we shadow all the
6383 // settings and passing GL_FIXED to it will not work.
6384 glBindBuffer(
6385 GL_ARRAY_BUFFER,
6386 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6387 : 0);
6390 error::Error GLES2DecoderImpl::DoDrawArrays(
6391 const char* function_name,
6392 bool instanced,
6393 GLenum mode,
6394 GLint first,
6395 GLsizei count,
6396 GLsizei primcount) {
6397 error::Error error = WillAccessBoundFramebufferForDraw();
6398 if (error != error::kNoError)
6399 return error;
6400 if (!validators_->draw_mode.IsValid(mode)) {
6401 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6402 return error::kNoError;
6404 if (count < 0) {
6405 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6406 return error::kNoError;
6408 if (primcount < 0) {
6409 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6410 return error::kNoError;
6412 if (!CheckBoundFramebuffersValid(function_name)) {
6413 return error::kNoError;
6415 // We have to check this here because the prototype for glDrawArrays
6416 // is GLint not GLsizei.
6417 if (first < 0) {
6418 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6419 return error::kNoError;
6422 if (count == 0 || (instanced && primcount == 0)) {
6423 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6424 return error::kNoError;
6427 GLuint max_vertex_accessed = first + count - 1;
6428 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6429 if (!ClearUnclearedTextures()) {
6430 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6431 return error::kNoError;
6433 bool simulated_attrib_0 = false;
6434 if (!SimulateAttrib0(
6435 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6436 return error::kNoError;
6438 bool simulated_fixed_attribs = false;
6439 if (SimulateFixedAttribs(
6440 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6441 primcount)) {
6442 bool textures_set = !PrepareTexturesForRender();
6443 ApplyDirtyState();
6444 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6445 if (!instanced) {
6446 glDrawArrays(mode, first, count);
6447 } else {
6448 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6450 if (textures_set) {
6451 RestoreStateForTextures();
6453 if (simulated_fixed_attribs) {
6454 RestoreStateForSimulatedFixedAttribs();
6457 if (simulated_attrib_0) {
6458 // We don't have to restore attrib 0 generic data at the end of this
6459 // function even if it is simulated. This is because we will simulate
6460 // it in each draw call, and attrib 0 generic data queries use cached
6461 // values instead of passing down to the underlying driver.
6462 RestoreStateForAttrib(0, false);
6465 return error::kNoError;
6468 error::Error GLES2DecoderImpl::HandleDrawArrays(
6469 uint32 immediate_data_size, const cmds::DrawArrays& c) {
6470 return DoDrawArrays("glDrawArrays",
6471 false,
6472 static_cast<GLenum>(c.mode),
6473 static_cast<GLint>(c.first),
6474 static_cast<GLsizei>(c.count),
6478 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6479 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
6480 if (!features().angle_instanced_arrays) {
6481 LOCAL_SET_GL_ERROR(
6482 GL_INVALID_OPERATION,
6483 "glDrawArraysInstancedANGLE", "function not available");
6484 return error::kNoError;
6486 return DoDrawArrays("glDrawArraysIntancedANGLE",
6487 true,
6488 static_cast<GLenum>(c.mode),
6489 static_cast<GLint>(c.first),
6490 static_cast<GLsizei>(c.count),
6491 static_cast<GLsizei>(c.primcount));
6494 error::Error GLES2DecoderImpl::DoDrawElements(
6495 const char* function_name,
6496 bool instanced,
6497 GLenum mode,
6498 GLsizei count,
6499 GLenum type,
6500 int32 offset,
6501 GLsizei primcount) {
6502 error::Error error = WillAccessBoundFramebufferForDraw();
6503 if (error != error::kNoError)
6504 return error;
6505 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6506 LOCAL_SET_GL_ERROR(
6507 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6508 return error::kNoError;
6511 if (count < 0) {
6512 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6513 return error::kNoError;
6515 if (offset < 0) {
6516 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6517 return error::kNoError;
6519 if (!validators_->draw_mode.IsValid(mode)) {
6520 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6521 return error::kNoError;
6523 if (!validators_->index_type.IsValid(type)) {
6524 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6525 return error::kNoError;
6527 if (primcount < 0) {
6528 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6529 return error::kNoError;
6532 if (!CheckBoundFramebuffersValid(function_name)) {
6533 return error::kNoError;
6536 if (count == 0 || (instanced && primcount == 0)) {
6537 return error::kNoError;
6540 GLuint max_vertex_accessed;
6541 Buffer* element_array_buffer =
6542 state_.vertex_attrib_manager->element_array_buffer();
6544 if (!element_array_buffer->GetMaxValueForRange(
6545 offset, count, type, &max_vertex_accessed)) {
6546 LOCAL_SET_GL_ERROR(
6547 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6548 return error::kNoError;
6551 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6552 if (!ClearUnclearedTextures()) {
6553 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6554 return error::kNoError;
6556 bool simulated_attrib_0 = false;
6557 if (!SimulateAttrib0(
6558 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6559 return error::kNoError;
6561 bool simulated_fixed_attribs = false;
6562 if (SimulateFixedAttribs(
6563 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6564 primcount)) {
6565 bool textures_set = !PrepareTexturesForRender();
6566 ApplyDirtyState();
6567 // TODO(gman): Refactor to hide these details in BufferManager or
6568 // VertexAttribManager.
6569 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6570 bool used_client_side_array = false;
6571 if (element_array_buffer->IsClientSideArray()) {
6572 used_client_side_array = true;
6573 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6574 indices = element_array_buffer->GetRange(offset, 0);
6577 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6578 if (!instanced) {
6579 glDrawElements(mode, count, type, indices);
6580 } else {
6581 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6584 if (used_client_side_array) {
6585 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6586 element_array_buffer->service_id());
6589 if (textures_set) {
6590 RestoreStateForTextures();
6592 if (simulated_fixed_attribs) {
6593 RestoreStateForSimulatedFixedAttribs();
6596 if (simulated_attrib_0) {
6597 // We don't have to restore attrib 0 generic data at the end of this
6598 // function even if it is simulated. This is because we will simulate
6599 // it in each draw call, and attrib 0 generic data queries use cached
6600 // values instead of passing down to the underlying driver.
6601 RestoreStateForAttrib(0, false);
6604 return error::kNoError;
6607 error::Error GLES2DecoderImpl::HandleDrawElements(
6608 uint32 immediate_data_size, const cmds::DrawElements& c) {
6609 return DoDrawElements("glDrawElements",
6610 false,
6611 static_cast<GLenum>(c.mode),
6612 static_cast<GLsizei>(c.count),
6613 static_cast<GLenum>(c.type),
6614 static_cast<int32>(c.index_offset),
6618 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6619 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
6620 if (!features().angle_instanced_arrays) {
6621 LOCAL_SET_GL_ERROR(
6622 GL_INVALID_OPERATION,
6623 "glDrawElementsInstancedANGLE", "function not available");
6624 return error::kNoError;
6626 return DoDrawElements("glDrawElementsInstancedANGLE",
6627 true,
6628 static_cast<GLenum>(c.mode),
6629 static_cast<GLsizei>(c.count),
6630 static_cast<GLenum>(c.type),
6631 static_cast<int32>(c.index_offset),
6632 static_cast<GLsizei>(c.primcount));
6635 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6636 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6637 GLuint max_vertex_accessed = 0;
6638 Buffer* buffer = GetBuffer(buffer_id);
6639 if (!buffer) {
6640 // TODO(gman): Should this be a GL error or a command buffer error?
6641 LOCAL_SET_GL_ERROR(
6642 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6643 } else {
6644 if (!buffer->GetMaxValueForRange(
6645 offset, count, type, &max_vertex_accessed)) {
6646 // TODO(gman): Should this be a GL error or a command buffer error?
6647 LOCAL_SET_GL_ERROR(
6648 GL_INVALID_OPERATION,
6649 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6652 return max_vertex_accessed;
6655 // Calls glShaderSource for the various versions of the ShaderSource command.
6656 // Assumes that data / data_size points to a piece of memory that is in range
6657 // of whatever context it came from (shared memory, immediate memory, bucket
6658 // memory.)
6659 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6660 GLuint client_id, const char* data, uint32 data_size) {
6661 std::string str(data, data + data_size);
6662 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6663 if (!shader) {
6664 return error::kNoError;
6666 // Note: We don't actually call glShaderSource here. We wait until
6667 // the call to glCompileShader.
6668 shader->UpdateSource(str.c_str());
6669 return error::kNoError;
6672 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6673 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
6674 Bucket* bucket = GetBucket(c.data_bucket_id);
6675 if (!bucket || bucket->size() == 0) {
6676 return error::kInvalidArguments;
6678 return ShaderSourceHelper(
6679 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6680 bucket->size() - 1);
6683 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6684 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6685 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6686 if (!shader) {
6687 return;
6689 ShaderTranslator* translator = NULL;
6690 if (use_shader_translator_) {
6691 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6692 vertex_translator_.get() : fragment_translator_.get();
6695 program_manager()->DoCompileShader(
6696 shader,
6697 translator,
6698 feature_info_->feature_flags().angle_translated_shader_source ?
6699 ProgramManager::kANGLE : ProgramManager::kGL);
6702 void GLES2DecoderImpl::DoGetShaderiv(
6703 GLuint shader_id, GLenum pname, GLint* params) {
6704 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6705 if (!shader) {
6706 return;
6708 switch (pname) {
6709 case GL_SHADER_SOURCE_LENGTH:
6710 *params = shader->source() ? shader->source()->size() + 1 : 0;
6711 return;
6712 case GL_COMPILE_STATUS:
6713 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
6714 return;
6715 case GL_INFO_LOG_LENGTH:
6716 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
6717 return;
6718 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6719 *params = shader->translated_source() ?
6720 shader->translated_source()->size() + 1 : 0;
6721 return;
6722 default:
6723 break;
6725 glGetShaderiv(shader->service_id(), pname, params);
6728 error::Error GLES2DecoderImpl::HandleGetShaderSource(
6729 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
6730 GLuint shader_id = c.shader;
6731 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6732 Bucket* bucket = CreateBucket(bucket_id);
6733 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6734 if (!shader || !shader->source()) {
6735 bucket->SetSize(0);
6736 return error::kNoError;
6738 bucket->SetFromString(shader->source()->c_str());
6739 return error::kNoError;
6742 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6743 uint32 immediate_data_size,
6744 const cmds::GetTranslatedShaderSourceANGLE& c) {
6745 GLuint shader_id = c.shader;
6746 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6747 Bucket* bucket = CreateBucket(bucket_id);
6748 Shader* shader = GetShaderInfoNotProgram(
6749 shader_id, "glGetTranslatedShaderSourceANGLE");
6750 if (!shader) {
6751 bucket->SetSize(0);
6752 return error::kNoError;
6755 bucket->SetFromString(shader->translated_source() ?
6756 shader->translated_source()->c_str() : NULL);
6757 return error::kNoError;
6760 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6761 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
6762 GLuint program_id = c.program;
6763 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6764 Bucket* bucket = CreateBucket(bucket_id);
6765 Program* program = GetProgramInfoNotShader(
6766 program_id, "glGetProgramInfoLog");
6767 if (!program || !program->log_info()) {
6768 bucket->SetFromString("");
6769 return error::kNoError;
6771 bucket->SetFromString(program->log_info()->c_str());
6772 return error::kNoError;
6775 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
6776 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
6777 GLuint shader_id = c.shader;
6778 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6779 Bucket* bucket = CreateBucket(bucket_id);
6780 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6781 if (!shader || !shader->log_info()) {
6782 bucket->SetFromString("");
6783 return error::kNoError;
6785 bucket->SetFromString(shader->log_info()->c_str());
6786 return error::kNoError;
6789 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6790 return state_.GetEnabled(cap);
6793 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
6794 const Buffer* buffer = GetBuffer(client_id);
6795 return buffer && buffer->IsValid() && !buffer->IsDeleted();
6798 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
6799 const Framebuffer* framebuffer =
6800 GetFramebuffer(client_id);
6801 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
6804 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
6805 // IsProgram is true for programs as soon as they are created, until they are
6806 // deleted and no longer in use.
6807 const Program* program = GetProgram(client_id);
6808 return program != NULL && !program->IsDeleted();
6811 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
6812 const Renderbuffer* renderbuffer =
6813 GetRenderbuffer(client_id);
6814 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
6817 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
6818 // IsShader is true for shaders as soon as they are created, until they
6819 // are deleted and not attached to any programs.
6820 const Shader* shader = GetShader(client_id);
6821 return shader != NULL && !shader->IsDeleted();
6824 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
6825 const TextureRef* texture_ref = GetTexture(client_id);
6826 return texture_ref && texture_ref->texture()->IsValid();
6829 void GLES2DecoderImpl::DoAttachShader(
6830 GLuint program_client_id, GLint shader_client_id) {
6831 Program* program = GetProgramInfoNotShader(
6832 program_client_id, "glAttachShader");
6833 if (!program) {
6834 return;
6836 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6837 if (!shader) {
6838 return;
6840 if (!program->AttachShader(shader_manager(), shader)) {
6841 LOCAL_SET_GL_ERROR(
6842 GL_INVALID_OPERATION,
6843 "glAttachShader",
6844 "can not attach more than one shader of the same type.");
6845 return;
6847 glAttachShader(program->service_id(), shader->service_id());
6850 void GLES2DecoderImpl::DoDetachShader(
6851 GLuint program_client_id, GLint shader_client_id) {
6852 Program* program = GetProgramInfoNotShader(
6853 program_client_id, "glDetachShader");
6854 if (!program) {
6855 return;
6857 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6858 if (!shader) {
6859 return;
6861 if (!program->DetachShader(shader_manager(), shader)) {
6862 LOCAL_SET_GL_ERROR(
6863 GL_INVALID_OPERATION,
6864 "glDetachShader", "shader not attached to program");
6865 return;
6867 glDetachShader(program->service_id(), shader->service_id());
6870 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
6871 Program* program = GetProgramInfoNotShader(
6872 program_client_id, "glValidateProgram");
6873 if (!program) {
6874 return;
6876 program->Validate();
6879 void GLES2DecoderImpl::GetVertexAttribHelper(
6880 const VertexAttrib* attrib, GLenum pname, GLint* params) {
6881 switch (pname) {
6882 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6883 Buffer* buffer = attrib->buffer();
6884 if (buffer && !buffer->IsDeleted()) {
6885 GLuint client_id;
6886 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6887 *params = client_id;
6889 break;
6891 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6892 *params = attrib->enabled();
6893 break;
6894 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6895 *params = attrib->size();
6896 break;
6897 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6898 *params = attrib->gl_stride();
6899 break;
6900 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6901 *params = attrib->type();
6902 break;
6903 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6904 *params = attrib->normalized();
6905 break;
6906 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6907 *params = attrib->divisor();
6908 break;
6909 default:
6910 NOTREACHED();
6911 break;
6915 void GLES2DecoderImpl::DoGetTexParameterfv(
6916 GLenum target, GLenum pname, GLfloat* params) {
6917 InitTextureMaxAnisotropyIfNeeded(target, pname);
6918 glGetTexParameterfv(target, pname, params);
6921 void GLES2DecoderImpl::DoGetTexParameteriv(
6922 GLenum target, GLenum pname, GLint* params) {
6923 InitTextureMaxAnisotropyIfNeeded(target, pname);
6924 glGetTexParameteriv(target, pname, params);
6927 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
6928 GLenum target, GLenum pname) {
6929 if (!workarounds().init_texture_max_anisotropy)
6930 return;
6931 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
6932 !validators_->texture_parameter.IsValid(pname)) {
6933 return;
6936 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
6937 &state_, target);
6938 if (!texture_ref) {
6939 LOCAL_SET_GL_ERROR(
6940 GL_INVALID_OPERATION,
6941 "glGetTexParamter{fi}v", "unknown texture for target");
6942 return;
6944 Texture* texture = texture_ref->texture();
6945 texture->InitTextureMaxAnisotropyIfNeeded(target);
6948 void GLES2DecoderImpl::DoGetVertexAttribfv(
6949 GLuint index, GLenum pname, GLfloat* params) {
6950 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6951 if (!attrib) {
6952 LOCAL_SET_GL_ERROR(
6953 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
6954 return;
6956 switch (pname) {
6957 case GL_CURRENT_VERTEX_ATTRIB: {
6958 const Vec4& value = state_.attrib_values[index];
6959 params[0] = value.v[0];
6960 params[1] = value.v[1];
6961 params[2] = value.v[2];
6962 params[3] = value.v[3];
6963 break;
6965 default: {
6966 GLint value = 0;
6967 GetVertexAttribHelper(attrib, pname, &value);
6968 *params = static_cast<GLfloat>(value);
6969 break;
6974 void GLES2DecoderImpl::DoGetVertexAttribiv(
6975 GLuint index, GLenum pname, GLint* params) {
6976 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6977 if (!attrib) {
6978 LOCAL_SET_GL_ERROR(
6979 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
6980 return;
6982 switch (pname) {
6983 case GL_CURRENT_VERTEX_ATTRIB: {
6984 const Vec4& value = state_.attrib_values[index];
6985 params[0] = static_cast<GLint>(value.v[0]);
6986 params[1] = static_cast<GLint>(value.v[1]);
6987 params[2] = static_cast<GLint>(value.v[2]);
6988 params[3] = static_cast<GLint>(value.v[3]);
6989 break;
6991 default:
6992 GetVertexAttribHelper(attrib, pname, params);
6993 break;
6997 bool GLES2DecoderImpl::SetVertexAttribValue(
6998 const char* function_name, GLuint index, const GLfloat* value) {
6999 if (index >= state_.attrib_values.size()) {
7000 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7001 return false;
7003 Vec4& v = state_.attrib_values[index];
7004 v.v[0] = value[0];
7005 v.v[1] = value[1];
7006 v.v[2] = value[2];
7007 v.v[3] = value[3];
7008 return true;
7011 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7012 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7013 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7014 glVertexAttrib1f(index, v0);
7018 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7019 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7020 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7021 glVertexAttrib2f(index, v0, v1);
7025 void GLES2DecoderImpl::DoVertexAttrib3f(
7026 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7027 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7028 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7029 glVertexAttrib3f(index, v0, v1, v2);
7033 void GLES2DecoderImpl::DoVertexAttrib4f(
7034 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7035 GLfloat v[4] = { v0, v1, v2, v3, };
7036 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7037 glVertexAttrib4f(index, v0, v1, v2, v3);
7041 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7042 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7043 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7044 glVertexAttrib1fv(index, v);
7048 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7049 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7050 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7051 glVertexAttrib2fv(index, v);
7055 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7056 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7057 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7058 glVertexAttrib3fv(index, v);
7062 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7063 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7064 glVertexAttrib4fv(index, v);
7068 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7069 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
7071 if (!state_.bound_array_buffer.get() ||
7072 state_.bound_array_buffer->IsDeleted()) {
7073 if (state_.vertex_attrib_manager.get() ==
7074 state_.default_vertex_attrib_manager.get()) {
7075 LOCAL_SET_GL_ERROR(
7076 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7077 return error::kNoError;
7078 } else if (c.offset != 0) {
7079 LOCAL_SET_GL_ERROR(
7080 GL_INVALID_VALUE,
7081 "glVertexAttribPointer", "client side arrays are not allowed");
7082 return error::kNoError;
7086 GLuint indx = c.indx;
7087 GLint size = c.size;
7088 GLenum type = c.type;
7089 GLboolean normalized = c.normalized;
7090 GLsizei stride = c.stride;
7091 GLsizei offset = c.offset;
7092 const void* ptr = reinterpret_cast<const void*>(offset);
7093 if (!validators_->vertex_attrib_type.IsValid(type)) {
7094 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7095 return error::kNoError;
7097 if (!validators_->vertex_attrib_size.IsValid(size)) {
7098 LOCAL_SET_GL_ERROR(
7099 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7100 return error::kNoError;
7102 if (indx >= group_->max_vertex_attribs()) {
7103 LOCAL_SET_GL_ERROR(
7104 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7105 return error::kNoError;
7107 if (stride < 0) {
7108 LOCAL_SET_GL_ERROR(
7109 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7110 return error::kNoError;
7112 if (stride > 255) {
7113 LOCAL_SET_GL_ERROR(
7114 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7115 return error::kNoError;
7117 if (offset < 0) {
7118 LOCAL_SET_GL_ERROR(
7119 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7120 return error::kNoError;
7122 GLsizei component_size =
7123 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7124 if (offset % component_size > 0) {
7125 LOCAL_SET_GL_ERROR(
7126 GL_INVALID_OPERATION,
7127 "glVertexAttribPointer", "offset not valid for type");
7128 return error::kNoError;
7130 if (stride % component_size > 0) {
7131 LOCAL_SET_GL_ERROR(
7132 GL_INVALID_OPERATION,
7133 "glVertexAttribPointer", "stride not valid for type");
7134 return error::kNoError;
7136 state_.vertex_attrib_manager
7137 ->SetAttribInfo(indx,
7138 state_.bound_array_buffer.get(),
7139 size,
7140 type,
7141 normalized,
7142 stride,
7143 stride != 0 ? stride : component_size * size,
7144 offset);
7145 if (type != GL_FIXED) {
7146 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7148 return error::kNoError;
7151 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7152 GLsizei height) {
7153 state_.viewport_x = x;
7154 state_.viewport_y = y;
7155 state_.viewport_width = std::min(width, viewport_max_width_);
7156 state_.viewport_height = std::min(height, viewport_max_height_);
7157 glViewport(x, y, width, height);
7160 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7161 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
7162 if (!features().angle_instanced_arrays) {
7163 LOCAL_SET_GL_ERROR(
7164 GL_INVALID_OPERATION,
7165 "glVertexAttribDivisorANGLE", "function not available");
7166 return error::kNoError;
7168 GLuint index = c.index;
7169 GLuint divisor = c.divisor;
7170 if (index >= group_->max_vertex_attribs()) {
7171 LOCAL_SET_GL_ERROR(
7172 GL_INVALID_VALUE,
7173 "glVertexAttribDivisorANGLE", "index out of range");
7174 return error::kNoError;
7177 state_.vertex_attrib_manager->SetDivisor(
7178 index,
7179 divisor);
7180 glVertexAttribDivisorANGLE(index, divisor);
7181 return error::kNoError;
7184 template <typename pixel_data_type>
7185 static void WriteAlphaData(
7186 void *pixels, uint32 row_count, uint32 channel_count,
7187 uint32 alpha_channel_index, uint32 unpadded_row_size,
7188 uint32 padded_row_size, pixel_data_type alpha_value) {
7189 DCHECK_GT(channel_count, 0U);
7190 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7191 uint32 unpadded_row_size_in_elements =
7192 unpadded_row_size / sizeof(pixel_data_type);
7193 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7194 uint32 padded_row_size_in_elements =
7195 padded_row_size / sizeof(pixel_data_type);
7196 pixel_data_type* dst =
7197 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7198 for (uint32 yy = 0; yy < row_count; ++yy) {
7199 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7200 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7201 *d = alpha_value;
7203 dst += padded_row_size_in_elements;
7207 void GLES2DecoderImpl::FinishReadPixels(
7208 const cmds::ReadPixels& c,
7209 GLuint buffer) {
7210 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7211 GLsizei width = c.width;
7212 GLsizei height = c.height;
7213 GLenum format = c.format;
7214 GLenum type = c.type;
7215 typedef cmds::ReadPixels::Result Result;
7216 uint32 pixels_size;
7217 Result* result = NULL;
7218 if (c.result_shm_id != 0) {
7219 result = GetSharedMemoryAs<Result*>(
7220 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7221 if (!result) {
7222 if (buffer != 0) {
7223 glDeleteBuffersARB(1, &buffer);
7225 return;
7228 GLES2Util::ComputeImageDataSizes(
7229 width, height, format, type, state_.pack_alignment, &pixels_size,
7230 NULL, NULL);
7231 void* pixels = GetSharedMemoryAs<void*>(
7232 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7233 if (!pixels) {
7234 if (buffer != 0) {
7235 glDeleteBuffersARB(1, &buffer);
7237 return;
7240 if (buffer != 0) {
7241 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7242 void* data;
7243 if (features().map_buffer_range) {
7244 data = glMapBufferRange(
7245 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7246 } else {
7247 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7249 memcpy(pixels, data, pixels_size);
7250 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7251 // have to restore the state.
7252 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7253 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7254 glDeleteBuffersARB(1, &buffer);
7257 if (result != NULL) {
7258 *result = true;
7261 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7262 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7263 if ((channels_exist & 0x0008) == 0 &&
7264 workarounds().clear_alpha_in_readpixels) {
7265 // Set the alpha to 255 because some drivers are buggy in this regard.
7266 uint32 temp_size;
7268 uint32 unpadded_row_size;
7269 uint32 padded_row_size;
7270 if (!GLES2Util::ComputeImageDataSizes(
7271 width, 2, format, type, state_.pack_alignment, &temp_size,
7272 &unpadded_row_size, &padded_row_size)) {
7273 return;
7276 uint32 channel_count = 0;
7277 uint32 alpha_channel = 0;
7278 switch (format) {
7279 case GL_RGBA:
7280 case GL_BGRA_EXT:
7281 channel_count = 4;
7282 alpha_channel = 3;
7283 break;
7284 case GL_ALPHA:
7285 channel_count = 1;
7286 alpha_channel = 0;
7287 break;
7290 if (channel_count > 0) {
7291 switch (type) {
7292 case GL_UNSIGNED_BYTE:
7293 WriteAlphaData<uint8>(
7294 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7295 padded_row_size, 0xFF);
7296 break;
7297 case GL_FLOAT:
7298 WriteAlphaData<float>(
7299 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7300 padded_row_size, 1.0f);
7301 break;
7302 case GL_HALF_FLOAT:
7303 WriteAlphaData<uint16>(
7304 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7305 padded_row_size, 0x3C00);
7306 break;
7313 error::Error GLES2DecoderImpl::HandleReadPixels(
7314 uint32 immediate_data_size, const cmds::ReadPixels& c) {
7315 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7316 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7317 if (fbo_error != error::kNoError)
7318 return fbo_error;
7319 GLint x = c.x;
7320 GLint y = c.y;
7321 GLsizei width = c.width;
7322 GLsizei height = c.height;
7323 GLenum format = c.format;
7324 GLenum type = c.type;
7325 GLboolean async = c.async;
7326 if (width < 0 || height < 0) {
7327 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7328 return error::kNoError;
7330 typedef cmds::ReadPixels::Result Result;
7331 uint32 pixels_size;
7332 if (!GLES2Util::ComputeImageDataSizes(
7333 width, height, format, type, state_.pack_alignment, &pixels_size,
7334 NULL, NULL)) {
7335 return error::kOutOfBounds;
7337 void* pixels = GetSharedMemoryAs<void*>(
7338 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7339 if (!pixels) {
7340 return error::kOutOfBounds;
7342 Result* result = NULL;
7343 if (c.result_shm_id != 0) {
7344 result = GetSharedMemoryAs<Result*>(
7345 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7346 if (!result) {
7347 return error::kOutOfBounds;
7351 if (!validators_->read_pixel_format.IsValid(format)) {
7352 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7353 return error::kNoError;
7355 if (!validators_->read_pixel_type.IsValid(type)) {
7356 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7357 return error::kNoError;
7359 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7360 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7361 // format and type are acceptable enums but not guaranteed to be supported
7362 // for this framebuffer. Have to ask gl if they are valid.
7363 GLint preferred_format = 0;
7364 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7365 GLint preferred_type = 0;
7366 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7367 if (format != static_cast<GLenum>(preferred_format) ||
7368 type != static_cast<GLenum>(preferred_type)) {
7369 LOCAL_SET_GL_ERROR(
7370 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7371 "with the current read framebuffer");
7372 return error::kNoError;
7375 if (width == 0 || height == 0) {
7376 return error::kNoError;
7379 // Get the size of the current fbo or backbuffer.
7380 gfx::Size max_size = GetBoundReadFrameBufferSize();
7382 int32 max_x;
7383 int32 max_y;
7384 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7385 LOCAL_SET_GL_ERROR(
7386 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7387 return error::kNoError;
7390 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7391 return error::kNoError;
7394 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7396 ScopedResolvedFrameBufferBinder binder(this, false, true);
7398 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7399 // The user requested an out of range area. Get the results 1 line
7400 // at a time.
7401 uint32 temp_size;
7402 uint32 unpadded_row_size;
7403 uint32 padded_row_size;
7404 if (!GLES2Util::ComputeImageDataSizes(
7405 width, 2, format, type, state_.pack_alignment, &temp_size,
7406 &unpadded_row_size, &padded_row_size)) {
7407 LOCAL_SET_GL_ERROR(
7408 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7409 return error::kNoError;
7412 GLint dest_x_offset = std::max(-x, 0);
7413 uint32 dest_row_offset;
7414 if (!GLES2Util::ComputeImageDataSizes(
7415 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7416 NULL, NULL)) {
7417 LOCAL_SET_GL_ERROR(
7418 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7419 return error::kNoError;
7422 // Copy each row into the larger dest rect.
7423 int8* dst = static_cast<int8*>(pixels);
7424 GLint read_x = std::max(0, x);
7425 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7426 GLint read_width = read_end_x - read_x;
7427 for (GLint yy = 0; yy < height; ++yy) {
7428 GLint ry = y + yy;
7430 // Clear the row.
7431 memset(dst, 0, unpadded_row_size);
7433 // If the row is in range, copy it.
7434 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7435 glReadPixels(
7436 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7438 dst += padded_row_size;
7440 } else {
7441 if (async && features().use_async_readpixels) {
7442 GLuint buffer;
7443 glGenBuffersARB(1, &buffer);
7444 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7445 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7446 GLenum error = glGetError();
7447 if (error == GL_NO_ERROR) {
7448 glReadPixels(x, y, width, height, format, type, 0);
7449 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7450 new FenceCallback()));
7451 WaitForReadPixels(base::Bind(
7452 &GLES2DecoderImpl::FinishReadPixels,
7453 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7454 <GLES2DecoderImpl>(this),
7455 c, buffer));
7456 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7457 return error::kNoError;
7458 } else {
7459 // On error, unbind pack buffer and fall through to sync readpixels
7460 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7463 glReadPixels(x, y, width, height, format, type, pixels);
7465 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7466 if (error == GL_NO_ERROR) {
7467 if (result != NULL) {
7468 *result = true;
7470 FinishReadPixels(c, 0);
7473 return error::kNoError;
7476 error::Error GLES2DecoderImpl::HandlePixelStorei(
7477 uint32 immediate_data_size, const cmds::PixelStorei& c) {
7478 GLenum pname = c.pname;
7479 GLenum param = c.param;
7480 if (!validators_->pixel_store.IsValid(pname)) {
7481 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7482 return error::kNoError;
7484 switch (pname) {
7485 case GL_PACK_ALIGNMENT:
7486 case GL_UNPACK_ALIGNMENT:
7487 if (!validators_->pixel_store_alignment.IsValid(param)) {
7488 LOCAL_SET_GL_ERROR(
7489 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7490 return error::kNoError;
7492 break;
7493 case GL_UNPACK_FLIP_Y_CHROMIUM:
7494 unpack_flip_y_ = (param != 0);
7495 return error::kNoError;
7496 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7497 unpack_premultiply_alpha_ = (param != 0);
7498 return error::kNoError;
7499 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7500 unpack_unpremultiply_alpha_ = (param != 0);
7501 return error::kNoError;
7502 default:
7503 break;
7505 glPixelStorei(pname, param);
7506 switch (pname) {
7507 case GL_PACK_ALIGNMENT:
7508 state_.pack_alignment = param;
7509 break;
7510 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7511 state_.pack_reverse_row_order = (param != 0);
7512 break;
7513 case GL_UNPACK_ALIGNMENT:
7514 state_.unpack_alignment = param;
7515 break;
7516 default:
7517 // Validation should have prevented us from getting here.
7518 NOTREACHED();
7519 break;
7521 return error::kNoError;
7524 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7525 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
7526 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7528 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7530 if (!supports_post_sub_buffer_) {
7531 LOCAL_SET_GL_ERROR(
7532 GL_INVALID_OPERATION,
7533 "glPostSubBufferCHROMIUM", "command not supported by surface");
7534 return error::kNoError;
7536 bool is_tracing;
7537 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7538 &is_tracing);
7539 if (is_tracing) {
7540 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7541 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7542 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7543 is_offscreen ? offscreen_size_ : surface_->GetSize());
7545 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7546 return error::kNoError;
7547 } else {
7548 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7549 return error::kLostContext;
7553 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7554 uint32 immediate_data_size,
7555 const cmds::ScheduleOverlayPlaneCHROMIUM& c) {
7556 NOTIMPLEMENTED() << "Overlay supported isn't finished.";
7557 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
7558 "glScheduleOverlayPlaneCHROMIUM",
7559 "function not implemented");
7560 return error::kNoError;
7563 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7564 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7565 const std::string& name_str) {
7566 if (!StringIsValidForGLES(name_str.c_str())) {
7567 LOCAL_SET_GL_ERROR(
7568 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7569 return error::kNoError;
7571 Program* program = GetProgramInfoNotShader(
7572 client_id, "glGetAttribLocation");
7573 if (!program) {
7574 return error::kNoError;
7576 if (!program->IsValid()) {
7577 LOCAL_SET_GL_ERROR(
7578 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7579 return error::kNoError;
7581 GLint* location = GetSharedMemoryAs<GLint*>(
7582 location_shm_id, location_shm_offset, sizeof(GLint));
7583 if (!location) {
7584 return error::kOutOfBounds;
7586 // Require the client to init this incase the context is lost and we are no
7587 // longer executing commands.
7588 if (*location != -1) {
7589 return error::kGenericError;
7591 *location = program->GetAttribLocation(name_str);
7592 return error::kNoError;
7595 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7596 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
7597 Bucket* bucket = GetBucket(c.name_bucket_id);
7598 if (!bucket) {
7599 return error::kInvalidArguments;
7601 std::string name_str;
7602 if (!bucket->GetAsString(&name_str)) {
7603 return error::kInvalidArguments;
7605 return GetAttribLocationHelper(
7606 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7609 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7610 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7611 const std::string& name_str) {
7612 if (!StringIsValidForGLES(name_str.c_str())) {
7613 LOCAL_SET_GL_ERROR(
7614 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7615 return error::kNoError;
7617 Program* program = GetProgramInfoNotShader(
7618 client_id, "glGetUniformLocation");
7619 if (!program) {
7620 return error::kNoError;
7622 if (!program->IsValid()) {
7623 LOCAL_SET_GL_ERROR(
7624 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7625 return error::kNoError;
7627 GLint* location = GetSharedMemoryAs<GLint*>(
7628 location_shm_id, location_shm_offset, sizeof(GLint));
7629 if (!location) {
7630 return error::kOutOfBounds;
7632 // Require the client to init this incase the context is lost an we are no
7633 // longer executing commands.
7634 if (*location != -1) {
7635 return error::kGenericError;
7637 *location = program->GetUniformFakeLocation(name_str);
7638 return error::kNoError;
7641 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7642 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
7643 Bucket* bucket = GetBucket(c.name_bucket_id);
7644 if (!bucket) {
7645 return error::kInvalidArguments;
7647 std::string name_str;
7648 if (!bucket->GetAsString(&name_str)) {
7649 return error::kInvalidArguments;
7651 return GetUniformLocationHelper(
7652 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7655 error::Error GLES2DecoderImpl::HandleGetString(
7656 uint32 immediate_data_size, const cmds::GetString& c) {
7657 GLenum name = static_cast<GLenum>(c.name);
7658 if (!validators_->string_type.IsValid(name)) {
7659 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7660 return error::kNoError;
7662 const char* str = reinterpret_cast<const char*>(glGetString(name));
7663 std::string extensions;
7664 switch (name) {
7665 case GL_VERSION:
7666 str = "OpenGL ES 2.0 Chromium";
7667 break;
7668 case GL_SHADING_LANGUAGE_VERSION:
7669 str = "OpenGL ES GLSL ES 1.0 Chromium";
7670 break;
7671 case GL_RENDERER:
7672 case GL_VENDOR:
7673 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7674 // They are used by WEBGL_debug_renderer_info.
7675 if (!force_webgl_glsl_validation_)
7676 str = "Chromium";
7677 break;
7678 case GL_EXTENSIONS:
7680 // For WebGL contexts, strip out the OES derivatives and
7681 // EXT frag depth extensions if they have not been enabled.
7682 if (force_webgl_glsl_validation_) {
7683 extensions = feature_info_->extensions();
7684 if (!derivatives_explicitly_enabled_) {
7685 size_t offset = extensions.find(kOESDerivativeExtension);
7686 if (std::string::npos != offset) {
7687 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7688 std::string());
7691 if (!frag_depth_explicitly_enabled_) {
7692 size_t offset = extensions.find(kEXTFragDepthExtension);
7693 if (std::string::npos != offset) {
7694 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7695 std::string());
7698 if (!draw_buffers_explicitly_enabled_) {
7699 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7700 if (std::string::npos != offset) {
7701 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7702 std::string());
7705 if (!shader_texture_lod_explicitly_enabled_) {
7706 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
7707 if (std::string::npos != offset) {
7708 extensions.replace(offset,
7709 arraysize(kEXTShaderTextureLodExtension),
7710 std::string());
7713 } else {
7714 extensions = feature_info_->extensions().c_str();
7716 if (supports_post_sub_buffer_)
7717 extensions += " GL_CHROMIUM_post_sub_buffer";
7718 str = extensions.c_str();
7720 break;
7721 default:
7722 break;
7724 Bucket* bucket = CreateBucket(c.bucket_id);
7725 bucket->SetFromString(str);
7726 return error::kNoError;
7729 error::Error GLES2DecoderImpl::HandleBufferData(
7730 uint32 immediate_data_size, const cmds::BufferData& c) {
7731 GLenum target = static_cast<GLenum>(c.target);
7732 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7733 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7734 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7735 GLenum usage = static_cast<GLenum>(c.usage);
7736 const void* data = NULL;
7737 if (data_shm_id != 0 || data_shm_offset != 0) {
7738 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7739 if (!data) {
7740 return error::kOutOfBounds;
7743 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
7744 return error::kNoError;
7747 void GLES2DecoderImpl::DoBufferSubData(
7748 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
7749 // Just delegate it. Some validation is actually done before this.
7750 buffer_manager()->ValidateAndDoBufferSubData(
7751 &state_, target, offset, size, data);
7754 bool GLES2DecoderImpl::ClearLevel(
7755 unsigned service_id,
7756 unsigned bind_target,
7757 unsigned target,
7758 int level,
7759 unsigned internal_format,
7760 unsigned format,
7761 unsigned type,
7762 int width,
7763 int height,
7764 bool is_texture_immutable) {
7765 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7766 if (feature_info_->feature_flags().angle_depth_texture &&
7767 (channels & GLES2Util::kDepth) != 0) {
7768 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7769 // on depth formats.
7770 GLuint fb = 0;
7771 glGenFramebuffersEXT(1, &fb);
7772 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7774 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7775 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7776 GL_DEPTH_ATTACHMENT;
7778 glFramebufferTexture2DEXT(
7779 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7780 // ANGLE promises a depth only attachment ok.
7781 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7782 GL_FRAMEBUFFER_COMPLETE) {
7783 return false;
7785 glClearStencil(0);
7786 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
7787 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
7788 glClearDepth(1.0f);
7789 state_.SetDeviceDepthMask(GL_TRUE);
7790 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
7791 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7793 RestoreClearState();
7795 glDeleteFramebuffersEXT(1, &fb);
7796 Framebuffer* framebuffer =
7797 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7798 GLuint fb_service_id =
7799 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7800 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7801 return true;
7804 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7806 uint32 size;
7807 uint32 padded_row_size;
7808 if (!GLES2Util::ComputeImageDataSizes(
7809 width, height, format, type, state_.unpack_alignment, &size,
7810 NULL, &padded_row_size)) {
7811 return false;
7814 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7816 int tile_height;
7818 if (size > kMaxZeroSize) {
7819 if (kMaxZeroSize < padded_row_size) {
7820 // That'd be an awfully large texture.
7821 return false;
7823 // We should never have a large total size with a zero row size.
7824 DCHECK_GT(padded_row_size, 0U);
7825 tile_height = kMaxZeroSize / padded_row_size;
7826 if (!GLES2Util::ComputeImageDataSizes(
7827 width, tile_height, format, type, state_.unpack_alignment, &size,
7828 NULL, NULL)) {
7829 return false;
7831 } else {
7832 tile_height = height;
7835 // Assumes the size has already been checked.
7836 scoped_ptr<char[]> zero(new char[size]);
7837 memset(zero.get(), 0, size);
7838 glBindTexture(bind_target, service_id);
7840 GLint y = 0;
7841 while (y < height) {
7842 GLint h = y + tile_height > height ? height - y : tile_height;
7843 if (is_texture_immutable || h != height) {
7844 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7845 } else {
7846 glTexImage2D(
7847 target, level, internal_format, width, h, 0, format, type,
7848 zero.get());
7850 y += tile_height;
7852 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7853 &state_, bind_target);
7854 glBindTexture(bind_target, texture ? texture->service_id() : 0);
7855 return true;
7858 namespace {
7860 const int kS3TCBlockWidth = 4;
7861 const int kS3TCBlockHeight = 4;
7862 const int kS3TCDXT1BlockSize = 8;
7863 const int kS3TCDXT3AndDXT5BlockSize = 16;
7865 bool IsValidDXTSize(GLint level, GLsizei size) {
7866 return (size == 1) ||
7867 (size == 2) || !(size % kS3TCBlockWidth);
7870 bool IsValidPVRTCSize(GLint level, GLsizei size) {
7871 // Ensure that the size is a power of two
7872 return (size & (size - 1)) == 0;
7875 } // anonymous namespace.
7877 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7878 const char* function_name,
7879 GLsizei width, GLsizei height, GLenum format, size_t size) {
7880 unsigned int bytes_required = 0;
7882 switch (format) {
7883 case GL_ATC_RGB_AMD:
7884 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7885 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7886 case GL_ETC1_RGB8_OES: {
7887 int num_blocks_across =
7888 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7889 int num_blocks_down =
7890 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7891 int num_blocks = num_blocks_across * num_blocks_down;
7892 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7893 break;
7895 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
7896 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
7897 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7898 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7899 int num_blocks_across =
7900 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7901 int num_blocks_down =
7902 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7903 int num_blocks = num_blocks_across * num_blocks_down;
7904 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7905 break;
7907 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
7908 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
7909 bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
7910 break;
7912 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
7913 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
7914 bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
7915 break;
7917 default:
7918 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7919 return false;
7922 if (size != bytes_required) {
7923 LOCAL_SET_GL_ERROR(
7924 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7925 return false;
7928 return true;
7931 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7932 const char* function_name,
7933 GLint level, GLsizei width, GLsizei height, GLenum format) {
7934 switch (format) {
7935 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7936 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7937 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7938 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7939 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
7940 LOCAL_SET_GL_ERROR(
7941 GL_INVALID_OPERATION, function_name,
7942 "width or height invalid for level");
7943 return false;
7945 return true;
7947 case GL_ATC_RGB_AMD:
7948 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
7949 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
7950 case GL_ETC1_RGB8_OES: {
7951 if (width <= 0 || height <= 0) {
7952 LOCAL_SET_GL_ERROR(
7953 GL_INVALID_OPERATION, function_name,
7954 "width or height invalid for level");
7955 return false;
7957 return true;
7959 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
7960 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
7961 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
7962 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
7963 if (!IsValidPVRTCSize(level, width) ||
7964 !IsValidPVRTCSize(level, height)) {
7965 LOCAL_SET_GL_ERROR(
7966 GL_INVALID_OPERATION, function_name,
7967 "width or height invalid for level");
7968 return false;
7970 return true;
7972 default:
7973 return false;
7977 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7978 const char* function_name,
7979 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7980 GLsizei width, GLsizei height, GLenum format,
7981 Texture* texture) {
7982 if (xoffset < 0 || yoffset < 0) {
7983 LOCAL_SET_GL_ERROR(
7984 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7985 return false;
7988 switch (format) {
7989 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7990 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7991 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7992 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7993 const int kBlockWidth = 4;
7994 const int kBlockHeight = 4;
7995 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
7996 LOCAL_SET_GL_ERROR(
7997 GL_INVALID_OPERATION, function_name,
7998 "xoffset or yoffset not multiple of 4");
7999 return false;
8001 GLsizei tex_width = 0;
8002 GLsizei tex_height = 0;
8003 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8004 width - xoffset > tex_width ||
8005 height - yoffset > tex_height) {
8006 LOCAL_SET_GL_ERROR(
8007 GL_INVALID_OPERATION, function_name, "dimensions out of range");
8008 return false;
8010 return ValidateCompressedTexDimensions(
8011 function_name, level, width, height, format);
8013 case GL_ATC_RGB_AMD:
8014 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8015 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
8016 LOCAL_SET_GL_ERROR(
8017 GL_INVALID_OPERATION, function_name,
8018 "not supported for ATC textures");
8019 return false;
8021 case GL_ETC1_RGB8_OES: {
8022 LOCAL_SET_GL_ERROR(
8023 GL_INVALID_OPERATION, function_name,
8024 "not supported for ECT1_RGB8_OES textures");
8025 return false;
8027 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8028 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8029 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8030 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8031 if ((xoffset != 0) || (yoffset != 0)) {
8032 LOCAL_SET_GL_ERROR(
8033 GL_INVALID_OPERATION, function_name,
8034 "xoffset and yoffset must be zero");
8035 return false;
8037 GLsizei tex_width = 0;
8038 GLsizei tex_height = 0;
8039 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8040 width != tex_width ||
8041 height != tex_height) {
8042 LOCAL_SET_GL_ERROR(
8043 GL_INVALID_OPERATION, function_name,
8044 "dimensions must match existing texture level dimensions");
8045 return false;
8047 return ValidateCompressedTexDimensions(
8048 function_name, level, width, height, format);
8050 default:
8051 return false;
8055 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
8056 GLenum target,
8057 GLint level,
8058 GLenum internal_format,
8059 GLsizei width,
8060 GLsizei height,
8061 GLint border,
8062 GLsizei image_size,
8063 const void* data) {
8064 // TODO(gman): Validate image_size is correct for width, height and format.
8065 if (!validators_->texture_target.IsValid(target)) {
8066 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8067 "glCompressedTexImage2D", target, "target");
8068 return error::kNoError;
8070 if (!validators_->compressed_texture_format.IsValid(
8071 internal_format)) {
8072 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8073 "glCompressedTexImage2D", internal_format, "internal_format");
8074 return error::kNoError;
8076 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8077 border != 0) {
8078 LOCAL_SET_GL_ERROR(
8079 GL_INVALID_VALUE,
8080 "glCompressedTexImage2D", "dimensions out of range");
8081 return error::kNoError;
8083 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8084 &state_, target);
8085 if (!texture_ref) {
8086 LOCAL_SET_GL_ERROR(
8087 GL_INVALID_VALUE,
8088 "glCompressedTexImage2D", "unknown texture target");
8089 return error::kNoError;
8091 Texture* texture = texture_ref->texture();
8092 if (texture->IsImmutable()) {
8093 LOCAL_SET_GL_ERROR(
8094 GL_INVALID_OPERATION,
8095 "glCompressedTexImage2D", "texture is immutable");
8096 return error::kNoError;
8099 if (!ValidateCompressedTexDimensions(
8100 "glCompressedTexImage2D", level, width, height, internal_format) ||
8101 !ValidateCompressedTexFuncData(
8102 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8103 return error::kNoError;
8106 if (!EnsureGPUMemoryAvailable(image_size)) {
8107 LOCAL_SET_GL_ERROR(
8108 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8109 return error::kNoError;
8112 if (texture->IsAttachedToFramebuffer()) {
8113 framebuffer_state_.clear_state_dirty = true;
8116 scoped_ptr<int8[]> zero;
8117 if (!data) {
8118 zero.reset(new int8[image_size]);
8119 memset(zero.get(), 0, image_size);
8120 data = zero.get();
8122 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8123 glCompressedTexImage2D(
8124 target, level, internal_format, width, height, border, image_size, data);
8125 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8126 if (error == GL_NO_ERROR) {
8127 texture_manager()->SetLevelInfo(
8128 texture_ref, target, level, internal_format,
8129 width, height, 1, border, 0, 0, true);
8131 return error::kNoError;
8134 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8135 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
8136 GLenum target = static_cast<GLenum>(c.target);
8137 GLint level = static_cast<GLint>(c.level);
8138 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8139 GLsizei width = static_cast<GLsizei>(c.width);
8140 GLsizei height = static_cast<GLsizei>(c.height);
8141 GLint border = static_cast<GLint>(c.border);
8142 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8143 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8144 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8145 const void* data = NULL;
8146 if (data_shm_id != 0 || data_shm_offset != 0) {
8147 data = GetSharedMemoryAs<const void*>(
8148 data_shm_id, data_shm_offset, image_size);
8149 if (!data) {
8150 return error::kOutOfBounds;
8153 return DoCompressedTexImage2D(
8154 target, level, internal_format, width, height, border, image_size, data);
8157 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8158 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
8159 GLenum target = static_cast<GLenum>(c.target);
8160 GLint level = static_cast<GLint>(c.level);
8161 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8162 GLsizei width = static_cast<GLsizei>(c.width);
8163 GLsizei height = static_cast<GLsizei>(c.height);
8164 GLint border = static_cast<GLint>(c.border);
8165 Bucket* bucket = GetBucket(c.bucket_id);
8166 if (!bucket) {
8167 return error::kInvalidArguments;
8169 uint32 data_size = bucket->size();
8170 GLsizei imageSize = data_size;
8171 const void* data = bucket->GetData(0, data_size);
8172 if (!data) {
8173 return error::kInvalidArguments;
8175 return DoCompressedTexImage2D(
8176 target, level, internal_format, width, height, border,
8177 imageSize, data);
8180 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8181 uint32 immediate_data_size,
8182 const cmds::CompressedTexSubImage2DBucket& c) {
8183 GLenum target = static_cast<GLenum>(c.target);
8184 GLint level = static_cast<GLint>(c.level);
8185 GLint xoffset = static_cast<GLint>(c.xoffset);
8186 GLint yoffset = static_cast<GLint>(c.yoffset);
8187 GLsizei width = static_cast<GLsizei>(c.width);
8188 GLsizei height = static_cast<GLsizei>(c.height);
8189 GLenum format = static_cast<GLenum>(c.format);
8190 Bucket* bucket = GetBucket(c.bucket_id);
8191 if (!bucket) {
8192 return error::kInvalidArguments;
8194 uint32 data_size = bucket->size();
8195 GLsizei imageSize = data_size;
8196 const void* data = bucket->GetData(0, data_size);
8197 if (!data) {
8198 return error::kInvalidArguments;
8200 if (!validators_->texture_target.IsValid(target)) {
8201 LOCAL_SET_GL_ERROR(
8202 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8203 return error::kNoError;
8205 if (!validators_->compressed_texture_format.IsValid(format)) {
8206 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8207 "glCompressedTexSubImage2D", format, "format");
8208 return error::kNoError;
8210 if (width < 0) {
8211 LOCAL_SET_GL_ERROR(
8212 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8213 return error::kNoError;
8215 if (height < 0) {
8216 LOCAL_SET_GL_ERROR(
8217 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8218 return error::kNoError;
8220 if (imageSize < 0) {
8221 LOCAL_SET_GL_ERROR(
8222 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8223 return error::kNoError;
8225 DoCompressedTexSubImage2D(
8226 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8227 return error::kNoError;
8230 error::Error GLES2DecoderImpl::HandleTexImage2D(
8231 uint32 immediate_data_size, const cmds::TexImage2D& c) {
8232 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8233 "width", c.width, "height", c.height);
8234 // Set as failed for now, but if it successed, this will be set to not failed.
8235 texture_state_.tex_image_2d_failed = true;
8236 GLenum target = static_cast<GLenum>(c.target);
8237 GLint level = static_cast<GLint>(c.level);
8238 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8239 // for internalformat.
8240 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8241 GLsizei width = static_cast<GLsizei>(c.width);
8242 GLsizei height = static_cast<GLsizei>(c.height);
8243 GLint border = static_cast<GLint>(c.border);
8244 GLenum format = static_cast<GLenum>(c.format);
8245 GLenum type = static_cast<GLenum>(c.type);
8246 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8247 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8248 uint32 pixels_size;
8249 if (!GLES2Util::ComputeImageDataSizes(
8250 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8251 NULL)) {
8252 return error::kOutOfBounds;
8254 const void* pixels = NULL;
8255 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8256 pixels = GetSharedMemoryAs<const void*>(
8257 pixels_shm_id, pixels_shm_offset, pixels_size);
8258 if (!pixels) {
8259 return error::kOutOfBounds;
8263 TextureManager::DoTextImage2DArguments args = {
8264 target, level, internal_format, width, height, border, format, type,
8265 pixels, pixels_size};
8266 texture_manager()->ValidateAndDoTexImage2D(
8267 &texture_state_, &state_, &framebuffer_state_, args);
8268 return error::kNoError;
8271 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8272 GLenum target,
8273 GLint level,
8274 GLint xoffset,
8275 GLint yoffset,
8276 GLsizei width,
8277 GLsizei height,
8278 GLenum format,
8279 GLsizei image_size,
8280 const void * data) {
8281 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8282 &state_, target);
8283 if (!texture_ref) {
8284 LOCAL_SET_GL_ERROR(
8285 GL_INVALID_OPERATION,
8286 "glCompressedTexSubImage2D", "unknown texture for target");
8287 return;
8289 Texture* texture = texture_ref->texture();
8290 GLenum type = 0;
8291 GLenum internal_format = 0;
8292 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8293 LOCAL_SET_GL_ERROR(
8294 GL_INVALID_OPERATION,
8295 "glCompressedTexSubImage2D", "level does not exist.");
8296 return;
8298 if (internal_format != format) {
8299 LOCAL_SET_GL_ERROR(
8300 GL_INVALID_OPERATION,
8301 "glCompressedTexSubImage2D", "format does not match internal format.");
8302 return;
8304 if (!texture->ValidForTexture(
8305 target, level, xoffset, yoffset, width, height, type)) {
8306 LOCAL_SET_GL_ERROR(
8307 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8308 return;
8311 if (!ValidateCompressedTexFuncData(
8312 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8313 !ValidateCompressedTexSubDimensions(
8314 "glCompressedTexSubImage2D",
8315 target, level, xoffset, yoffset, width, height, format, texture)) {
8316 return;
8320 // Note: There is no need to deal with texture cleared tracking here
8321 // because the validation above means you can only get here if the level
8322 // is already a matching compressed format and in that case
8323 // CompressedTexImage2D already cleared the texture.
8324 glCompressedTexSubImage2D(
8325 target, level, xoffset, yoffset, width, height, format, image_size, data);
8328 static void Clip(
8329 GLint start, GLint range, GLint sourceRange,
8330 GLint* out_start, GLint* out_range) {
8331 DCHECK(out_start);
8332 DCHECK(out_range);
8333 if (start < 0) {
8334 range += start;
8335 start = 0;
8337 GLint end = start + range;
8338 if (end > sourceRange) {
8339 range -= end - sourceRange;
8341 *out_start = start;
8342 *out_range = range;
8345 void GLES2DecoderImpl::DoCopyTexImage2D(
8346 GLenum target,
8347 GLint level,
8348 GLenum internal_format,
8349 GLint x,
8350 GLint y,
8351 GLsizei width,
8352 GLsizei height,
8353 GLint border) {
8354 DCHECK(!ShouldDeferReads());
8355 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8356 &state_, target);
8357 if (!texture_ref) {
8358 LOCAL_SET_GL_ERROR(
8359 GL_INVALID_OPERATION,
8360 "glCopyTexImage2D", "unknown texture for target");
8361 return;
8363 Texture* texture = texture_ref->texture();
8364 if (texture->IsImmutable()) {
8365 LOCAL_SET_GL_ERROR(
8366 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8367 return;
8369 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8370 border != 0) {
8371 LOCAL_SET_GL_ERROR(
8372 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8373 return;
8375 if (!texture_manager()->ValidateFormatAndTypeCombination(
8376 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8377 GL_UNSIGNED_BYTE)) {
8378 return;
8381 // Check we have compatible formats.
8382 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8383 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8384 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8386 if ((channels_needed & channels_exist) != channels_needed) {
8387 LOCAL_SET_GL_ERROR(
8388 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8389 return;
8392 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8393 LOCAL_SET_GL_ERROR(
8394 GL_INVALID_OPERATION,
8395 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8396 return;
8399 uint32 estimated_size = 0;
8400 if (!GLES2Util::ComputeImageDataSizes(
8401 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8402 &estimated_size, NULL, NULL)) {
8403 LOCAL_SET_GL_ERROR(
8404 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8405 return;
8408 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8409 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8410 return;
8413 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8414 return;
8417 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8418 ScopedResolvedFrameBufferBinder binder(this, false, true);
8419 gfx::Size size = GetBoundReadFrameBufferSize();
8421 if (texture->IsAttachedToFramebuffer()) {
8422 framebuffer_state_.clear_state_dirty = true;
8425 // Clip to size to source dimensions
8426 GLint copyX = 0;
8427 GLint copyY = 0;
8428 GLint copyWidth = 0;
8429 GLint copyHeight = 0;
8430 Clip(x, width, size.width(), &copyX, &copyWidth);
8431 Clip(y, height, size.height(), &copyY, &copyHeight);
8433 if (copyX != x ||
8434 copyY != y ||
8435 copyWidth != width ||
8436 copyHeight != height) {
8437 // some part was clipped so clear the texture.
8438 if (!ClearLevel(
8439 texture->service_id(), texture->target(),
8440 target, level, internal_format, internal_format, GL_UNSIGNED_BYTE,
8441 width, height, texture->IsImmutable())) {
8442 LOCAL_SET_GL_ERROR(
8443 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8444 return;
8446 if (copyHeight > 0 && copyWidth > 0) {
8447 GLint dx = copyX - x;
8448 GLint dy = copyY - y;
8449 GLint destX = dx;
8450 GLint destY = dy;
8451 ScopedModifyPixels modify(texture_ref);
8452 glCopyTexSubImage2D(target, level,
8453 destX, destY, copyX, copyY,
8454 copyWidth, copyHeight);
8456 } else {
8457 ScopedModifyPixels modify(texture_ref);
8458 glCopyTexImage2D(target, level, internal_format,
8459 copyX, copyY, copyWidth, copyHeight, border);
8461 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8462 if (error == GL_NO_ERROR) {
8463 texture_manager()->SetLevelInfo(
8464 texture_ref, target, level, internal_format, width, height, 1,
8465 border, internal_format, GL_UNSIGNED_BYTE, true);
8469 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8470 GLenum target,
8471 GLint level,
8472 GLint xoffset,
8473 GLint yoffset,
8474 GLint x,
8475 GLint y,
8476 GLsizei width,
8477 GLsizei height) {
8478 DCHECK(!ShouldDeferReads());
8479 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8480 &state_, target);
8481 if (!texture_ref) {
8482 LOCAL_SET_GL_ERROR(
8483 GL_INVALID_OPERATION,
8484 "glCopyTexSubImage2D", "unknown texture for target");
8485 return;
8487 Texture* texture = texture_ref->texture();
8488 GLenum type = 0;
8489 GLenum format = 0;
8490 if (!texture->GetLevelType(target, level, &type, &format) ||
8491 !texture->ValidForTexture(
8492 target, level, xoffset, yoffset, width, height, type)) {
8493 LOCAL_SET_GL_ERROR(
8494 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8495 return;
8497 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8498 LOCAL_SET_GL_ERROR(
8499 GL_INVALID_OPERATION,
8500 "glCopyTexSubImage2D", "async upload pending for texture");
8501 return;
8504 // Check we have compatible formats.
8505 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8506 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8507 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8509 if (!channels_needed ||
8510 (channels_needed & channels_exist) != channels_needed) {
8511 LOCAL_SET_GL_ERROR(
8512 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8513 return;
8516 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8517 LOCAL_SET_GL_ERROR(
8518 GL_INVALID_OPERATION,
8519 "glCopySubImage2D", "can not be used with depth or stencil textures");
8520 return;
8523 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8524 return;
8527 ScopedResolvedFrameBufferBinder binder(this, false, true);
8528 gfx::Size size = GetBoundReadFrameBufferSize();
8529 GLint copyX = 0;
8530 GLint copyY = 0;
8531 GLint copyWidth = 0;
8532 GLint copyHeight = 0;
8533 Clip(x, width, size.width(), &copyX, &copyWidth);
8534 Clip(y, height, size.height(), &copyY, &copyHeight);
8536 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8537 LOCAL_SET_GL_ERROR(
8538 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8539 return;
8542 if (copyX != x ||
8543 copyY != y ||
8544 copyWidth != width ||
8545 copyHeight != height) {
8546 // some part was clipped so clear the sub rect.
8547 uint32 pixels_size = 0;
8548 if (!GLES2Util::ComputeImageDataSizes(
8549 width, height, format, type, state_.unpack_alignment, &pixels_size,
8550 NULL, NULL)) {
8551 LOCAL_SET_GL_ERROR(
8552 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8553 return;
8555 scoped_ptr<char[]> zero(new char[pixels_size]);
8556 memset(zero.get(), 0, pixels_size);
8557 ScopedModifyPixels modify(texture_ref);
8558 glTexSubImage2D(
8559 target, level, xoffset, yoffset, width, height,
8560 format, type, zero.get());
8563 if (copyHeight > 0 && copyWidth > 0) {
8564 GLint dx = copyX - x;
8565 GLint dy = copyY - y;
8566 GLint destX = xoffset + dx;
8567 GLint destY = yoffset + dy;
8568 ScopedModifyPixels modify(texture_ref);
8569 glCopyTexSubImage2D(target, level,
8570 destX, destY, copyX, copyY,
8571 copyWidth, copyHeight);
8575 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8576 error::Error* error,
8577 const char* function_name,
8578 GLenum target,
8579 GLint level,
8580 GLint xoffset,
8581 GLint yoffset,
8582 GLsizei width,
8583 GLsizei height,
8584 GLenum format,
8585 GLenum type,
8586 const void * data) {
8587 (*error) = error::kNoError;
8588 if (!validators_->texture_target.IsValid(target)) {
8589 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8590 return false;
8592 if (width < 0) {
8593 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8594 return false;
8596 if (height < 0) {
8597 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8598 return false;
8600 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8601 &state_, target);
8602 if (!texture_ref) {
8603 LOCAL_SET_GL_ERROR(
8604 GL_INVALID_OPERATION,
8605 function_name, "unknown texture for target");
8606 return false;
8608 Texture* texture = texture_ref->texture();
8609 GLenum current_type = 0;
8610 GLenum internal_format = 0;
8611 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
8612 LOCAL_SET_GL_ERROR(
8613 GL_INVALID_OPERATION, function_name, "level does not exist.");
8614 return false;
8616 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
8617 function_name, format, type, internal_format, level)) {
8618 return false;
8620 if (type != current_type) {
8621 LOCAL_SET_GL_ERROR(
8622 GL_INVALID_OPERATION,
8623 function_name, "type does not match type of texture.");
8624 return false;
8626 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8627 LOCAL_SET_GL_ERROR(
8628 GL_INVALID_OPERATION,
8629 function_name, "async upload pending for texture");
8630 return false;
8632 if (!texture->ValidForTexture(
8633 target, level, xoffset, yoffset, width, height, type)) {
8634 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8635 return false;
8637 if ((GLES2Util::GetChannelsForFormat(format) &
8638 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8639 LOCAL_SET_GL_ERROR(
8640 GL_INVALID_OPERATION,
8641 function_name, "can not supply data for depth or stencil textures");
8642 return false;
8644 if (data == NULL) {
8645 (*error) = error::kOutOfBounds;
8646 return false;
8648 return true;
8651 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8652 GLenum target,
8653 GLint level,
8654 GLint xoffset,
8655 GLint yoffset,
8656 GLsizei width,
8657 GLsizei height,
8658 GLenum format,
8659 GLenum type,
8660 const void * data) {
8661 error::Error error = error::kNoError;
8662 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8663 xoffset, yoffset, width, height, format, type, data)) {
8664 return error;
8666 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8667 &state_, target);
8668 Texture* texture = texture_ref->texture();
8669 GLsizei tex_width = 0;
8670 GLsizei tex_height = 0;
8671 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8672 DCHECK(ok);
8673 if (xoffset != 0 || yoffset != 0 ||
8674 width != tex_width || height != tex_height) {
8675 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8676 target, level)) {
8677 LOCAL_SET_GL_ERROR(
8678 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8679 return error::kNoError;
8681 ScopedTextureUploadTimer timer(&texture_state_);
8682 glTexSubImage2D(
8683 target, level, xoffset, yoffset, width, height, format, type, data);
8684 return error::kNoError;
8687 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
8688 !texture->IsImmutable()) {
8689 ScopedTextureUploadTimer timer(&texture_state_);
8690 GLenum internal_format;
8691 GLenum tex_type;
8692 texture->GetLevelType(target, level, &tex_type, &internal_format);
8693 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
8694 // to look it up.
8695 glTexImage2D(
8696 target, level, internal_format, width, height, 0, format, type, data);
8697 } else {
8698 ScopedTextureUploadTimer timer(&texture_state_);
8699 glTexSubImage2D(
8700 target, level, xoffset, yoffset, width, height, format, type, data);
8702 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
8703 return error::kNoError;
8706 error::Error GLES2DecoderImpl::HandleTexSubImage2D(
8707 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
8708 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
8709 "width", c.width, "height", c.height);
8710 GLboolean internal = static_cast<GLboolean>(c.internal);
8711 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
8712 return error::kNoError;
8714 GLenum target = static_cast<GLenum>(c.target);
8715 GLint level = static_cast<GLint>(c.level);
8716 GLint xoffset = static_cast<GLint>(c.xoffset);
8717 GLint yoffset = static_cast<GLint>(c.yoffset);
8718 GLsizei width = static_cast<GLsizei>(c.width);
8719 GLsizei height = static_cast<GLsizei>(c.height);
8720 GLenum format = static_cast<GLenum>(c.format);
8721 GLenum type = static_cast<GLenum>(c.type);
8722 uint32 data_size;
8723 if (!GLES2Util::ComputeImageDataSizes(
8724 width, height, format, type, state_.unpack_alignment, &data_size,
8725 NULL, NULL)) {
8726 return error::kOutOfBounds;
8728 const void* pixels = GetSharedMemoryAs<const void*>(
8729 c.pixels_shm_id, c.pixels_shm_offset, data_size);
8730 return DoTexSubImage2D(
8731 target, level, xoffset, yoffset, width, height, format, type, pixels);
8734 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8735 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
8736 GLuint index = static_cast<GLuint>(c.index);
8737 GLenum pname = static_cast<GLenum>(c.pname);
8738 typedef cmds::GetVertexAttribPointerv::Result Result;
8739 Result* result = GetSharedMemoryAs<Result*>(
8740 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8741 if (!result) {
8742 return error::kOutOfBounds;
8744 // Check that the client initialized the result.
8745 if (result->size != 0) {
8746 return error::kInvalidArguments;
8748 if (!validators_->vertex_pointer.IsValid(pname)) {
8749 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8750 "glGetVertexAttribPointerv", pname, "pname");
8751 return error::kNoError;
8753 if (index >= group_->max_vertex_attribs()) {
8754 LOCAL_SET_GL_ERROR(
8755 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
8756 return error::kNoError;
8758 result->SetNumResults(1);
8759 *result->GetData() =
8760 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
8761 return error::kNoError;
8764 bool GLES2DecoderImpl::GetUniformSetup(
8765 GLuint program_id, GLint fake_location,
8766 uint32 shm_id, uint32 shm_offset,
8767 error::Error* error, GLint* real_location,
8768 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8769 DCHECK(error);
8770 DCHECK(service_id);
8771 DCHECK(result_pointer);
8772 DCHECK(result_type);
8773 DCHECK(real_location);
8774 *error = error::kNoError;
8775 // Make sure we have enough room for the result on failure.
8776 SizedResult<GLint>* result;
8777 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8778 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8779 if (!result) {
8780 *error = error::kOutOfBounds;
8781 return false;
8783 *result_pointer = result;
8784 // Set the result size to 0 so the client does not have to check for success.
8785 result->SetNumResults(0);
8786 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8787 if (!program) {
8788 return false;
8790 if (!program->IsValid()) {
8791 // Program was not linked successfully. (ie, glLinkProgram)
8792 LOCAL_SET_GL_ERROR(
8793 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
8794 return false;
8796 *service_id = program->service_id();
8797 GLint array_index = -1;
8798 const Program::UniformInfo* uniform_info =
8799 program->GetUniformInfoByFakeLocation(
8800 fake_location, real_location, &array_index);
8801 if (!uniform_info) {
8802 // No such location.
8803 LOCAL_SET_GL_ERROR(
8804 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
8805 return false;
8807 GLenum type = uniform_info->type;
8808 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8809 if (size == 0) {
8810 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
8811 return false;
8813 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8814 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8815 if (!result) {
8816 *error = error::kOutOfBounds;
8817 return false;
8819 result->size = size;
8820 *result_type = type;
8821 return true;
8824 error::Error GLES2DecoderImpl::HandleGetUniformiv(
8825 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
8826 GLuint program = c.program;
8827 GLint fake_location = c.location;
8828 GLuint service_id;
8829 GLenum result_type;
8830 GLint real_location = -1;
8831 Error error;
8832 void* result;
8833 if (GetUniformSetup(
8834 program, fake_location, c.params_shm_id, c.params_shm_offset,
8835 &error, &real_location, &service_id, &result, &result_type)) {
8836 glGetUniformiv(
8837 service_id, real_location,
8838 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
8840 return error;
8843 error::Error GLES2DecoderImpl::HandleGetUniformfv(
8844 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
8845 GLuint program = c.program;
8846 GLint fake_location = c.location;
8847 GLuint service_id;
8848 GLint real_location = -1;
8849 Error error;
8850 typedef cmds::GetUniformfv::Result Result;
8851 Result* result;
8852 GLenum result_type;
8853 if (GetUniformSetup(
8854 program, fake_location, c.params_shm_id, c.params_shm_offset,
8855 &error, &real_location, &service_id,
8856 reinterpret_cast<void**>(&result), &result_type)) {
8857 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8858 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8859 GLsizei num_values = result->GetNumResults();
8860 scoped_ptr<GLint[]> temp(new GLint[num_values]);
8861 glGetUniformiv(service_id, real_location, temp.get());
8862 GLfloat* dst = result->GetData();
8863 for (GLsizei ii = 0; ii < num_values; ++ii) {
8864 dst[ii] = (temp[ii] != 0);
8866 } else {
8867 glGetUniformfv(service_id, real_location, result->GetData());
8870 return error;
8873 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8874 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
8875 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8876 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
8877 typedef cmds::GetShaderPrecisionFormat::Result Result;
8878 Result* result = GetSharedMemoryAs<Result*>(
8879 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8880 if (!result) {
8881 return error::kOutOfBounds;
8883 // Check that the client initialized the result.
8884 if (result->success != 0) {
8885 return error::kInvalidArguments;
8887 if (!validators_->shader_type.IsValid(shader_type)) {
8888 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8889 "glGetShaderPrecisionFormat", shader_type, "shader_type");
8890 return error::kNoError;
8892 if (!validators_->shader_precision.IsValid(precision_type)) {
8893 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8894 "glGetShaderPrecisionFormat", precision_type, "precision_type");
8895 return error::kNoError;
8898 result->success = 1; // true
8900 GLint range[2] = { 0, 0 };
8901 GLint precision = 0;
8902 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
8904 result->min_range = range[0];
8905 result->max_range = range[1];
8906 result->precision = precision;
8908 return error::kNoError;
8911 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
8912 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
8913 uint32 result_size = c.result_size;
8914 GLuint program_id = static_cast<GLuint>(c.program);
8915 Program* program = GetProgramInfoNotShader(
8916 program_id, "glGetAttachedShaders");
8917 if (!program) {
8918 return error::kNoError;
8920 typedef cmds::GetAttachedShaders::Result Result;
8921 uint32 max_count = Result::ComputeMaxResults(result_size);
8922 Result* result = GetSharedMemoryAs<Result*>(
8923 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8924 if (!result) {
8925 return error::kOutOfBounds;
8927 // Check that the client initialized the result.
8928 if (result->size != 0) {
8929 return error::kInvalidArguments;
8931 GLsizei count = 0;
8932 glGetAttachedShaders(
8933 program->service_id(), max_count, &count, result->GetData());
8934 for (GLsizei ii = 0; ii < count; ++ii) {
8935 if (!shader_manager()->GetClientId(result->GetData()[ii],
8936 &result->GetData()[ii])) {
8937 NOTREACHED();
8938 return error::kGenericError;
8941 result->SetNumResults(count);
8942 return error::kNoError;
8945 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
8946 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
8947 GLuint program_id = c.program;
8948 GLuint index = c.index;
8949 uint32 name_bucket_id = c.name_bucket_id;
8950 typedef cmds::GetActiveUniform::Result Result;
8951 Result* result = GetSharedMemoryAs<Result*>(
8952 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8953 if (!result) {
8954 return error::kOutOfBounds;
8956 // Check that the client initialized the result.
8957 if (result->success != 0) {
8958 return error::kInvalidArguments;
8960 Program* program = GetProgramInfoNotShader(
8961 program_id, "glGetActiveUniform");
8962 if (!program) {
8963 return error::kNoError;
8965 const Program::UniformInfo* uniform_info =
8966 program->GetUniformInfo(index);
8967 if (!uniform_info) {
8968 LOCAL_SET_GL_ERROR(
8969 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
8970 return error::kNoError;
8972 result->success = 1; // true.
8973 result->size = uniform_info->size;
8974 result->type = uniform_info->type;
8975 Bucket* bucket = CreateBucket(name_bucket_id);
8976 bucket->SetFromString(uniform_info->name.c_str());
8977 return error::kNoError;
8980 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
8981 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
8982 GLuint program_id = c.program;
8983 GLuint index = c.index;
8984 uint32 name_bucket_id = c.name_bucket_id;
8985 typedef cmds::GetActiveAttrib::Result Result;
8986 Result* result = GetSharedMemoryAs<Result*>(
8987 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8988 if (!result) {
8989 return error::kOutOfBounds;
8991 // Check that the client initialized the result.
8992 if (result->success != 0) {
8993 return error::kInvalidArguments;
8995 Program* program = GetProgramInfoNotShader(
8996 program_id, "glGetActiveAttrib");
8997 if (!program) {
8998 return error::kNoError;
9000 const Program::VertexAttrib* attrib_info =
9001 program->GetAttribInfo(index);
9002 if (!attrib_info) {
9003 LOCAL_SET_GL_ERROR(
9004 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
9005 return error::kNoError;
9007 result->success = 1; // true.
9008 result->size = attrib_info->size;
9009 result->type = attrib_info->type;
9010 Bucket* bucket = CreateBucket(name_bucket_id);
9011 bucket->SetFromString(attrib_info->name.c_str());
9012 return error::kNoError;
9015 error::Error GLES2DecoderImpl::HandleShaderBinary(
9016 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
9017 #if 1 // No binary shader support.
9018 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
9019 return error::kNoError;
9020 #else
9021 GLsizei n = static_cast<GLsizei>(c.n);
9022 if (n < 0) {
9023 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
9024 return error::kNoError;
9026 GLsizei length = static_cast<GLsizei>(c.length);
9027 if (length < 0) {
9028 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
9029 return error::kNoError;
9031 uint32 data_size;
9032 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
9033 return error::kOutOfBounds;
9035 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
9036 c.shaders_shm_id, c.shaders_shm_offset, data_size);
9037 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
9038 const void* binary = GetSharedMemoryAs<const void*>(
9039 c.binary_shm_id, c.binary_shm_offset, length);
9040 if (shaders == NULL || binary == NULL) {
9041 return error::kOutOfBounds;
9043 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9044 for (GLsizei ii = 0; ii < n; ++ii) {
9045 Shader* shader = GetShader(shaders[ii]);
9046 if (!shader) {
9047 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
9048 return error::kNoError;
9050 service_ids[ii] = shader->service_id();
9052 // TODO(gman): call glShaderBinary
9053 return error::kNoError;
9054 #endif
9057 void GLES2DecoderImpl::DoSwapBuffers() {
9058 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
9060 int this_frame_number = frame_number_++;
9061 // TRACE_EVENT for gpu tests:
9062 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9063 TRACE_EVENT_SCOPE_THREAD,
9064 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9065 "width", (is_offscreen ? offscreen_size_.width() :
9066 surface_->GetSize().width()));
9067 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9068 "offscreen", is_offscreen,
9069 "frame", this_frame_number);
9071 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9074 bool is_tracing;
9075 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9076 &is_tracing);
9077 if (is_tracing) {
9078 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
9079 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
9080 is_offscreen ? offscreen_size_ : surface_->GetSize());
9083 // If offscreen then don't actually SwapBuffers to the display. Just copy
9084 // the rendered frame to another frame buffer.
9085 if (is_offscreen) {
9086 TRACE_EVENT2("gpu", "Offscreen",
9087 "width", offscreen_size_.width(), "height", offscreen_size_.height());
9088 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
9089 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9090 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9091 // fix this.
9092 if (workarounds().needs_offscreen_buffer_workaround) {
9093 offscreen_saved_frame_buffer_->Create();
9094 glFinish();
9097 // Allocate the offscreen saved color texture.
9098 DCHECK(offscreen_saved_color_format_);
9099 offscreen_saved_color_texture_->AllocateStorage(
9100 offscreen_size_, offscreen_saved_color_format_, false);
9102 offscreen_saved_frame_buffer_->AttachRenderTexture(
9103 offscreen_saved_color_texture_.get());
9104 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
9105 if (offscreen_saved_frame_buffer_->CheckStatus() !=
9106 GL_FRAMEBUFFER_COMPLETE) {
9107 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9108 << "because offscreen saved FBO was incomplete.";
9109 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9110 return;
9113 // Clear the offscreen color texture.
9114 // TODO(piman): Is this still necessary?
9116 ScopedFrameBufferBinder binder(this,
9117 offscreen_saved_frame_buffer_->id());
9118 glClearColor(0, 0, 0, 0);
9119 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9120 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
9121 glClear(GL_COLOR_BUFFER_BIT);
9122 RestoreClearState();
9126 UpdateParentTextureInfo();
9129 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
9130 return;
9131 ScopedGLErrorSuppressor suppressor(
9132 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9134 if (IsOffscreenBufferMultisampled()) {
9135 // For multisampled buffers, resolve the frame buffer.
9136 ScopedResolvedFrameBufferBinder binder(this, true, false);
9137 } else {
9138 ScopedFrameBufferBinder binder(this,
9139 offscreen_target_frame_buffer_->id());
9141 if (offscreen_target_buffer_preserved_) {
9142 // Copy the target frame buffer to the saved offscreen texture.
9143 offscreen_saved_color_texture_->Copy(
9144 offscreen_saved_color_texture_->size(),
9145 offscreen_saved_color_format_);
9146 } else {
9147 // Flip the textures in the parent context via the texture manager.
9148 if (!!offscreen_saved_color_texture_info_.get())
9149 offscreen_saved_color_texture_info_->texture()->
9150 SetServiceId(offscreen_target_color_texture_->id());
9152 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9153 offscreen_target_frame_buffer_->AttachRenderTexture(
9154 offscreen_target_color_texture_.get());
9157 // Ensure the side effects of the copy are visible to the parent
9158 // context. There is no need to do this for ANGLE because it uses a
9159 // single D3D device for all contexts.
9160 if (!feature_info_->feature_flags().is_angle)
9161 glFlush();
9163 } else {
9164 if (!surface_->SwapBuffers()) {
9165 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9166 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9171 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9172 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
9173 Bucket* bucket = GetBucket(c.bucket_id);
9174 if (!bucket || bucket->size() == 0) {
9175 return error::kInvalidArguments;
9177 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9178 Result* result = GetSharedMemoryAs<Result*>(
9179 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9180 if (!result) {
9181 return error::kOutOfBounds;
9183 // Check that the client initialized the result.
9184 if (*result != 0) {
9185 return error::kInvalidArguments;
9187 std::string feature_str;
9188 if (!bucket->GetAsString(&feature_str)) {
9189 return error::kInvalidArguments;
9192 // TODO(gman): make this some kind of table to function pointer thingy.
9193 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9194 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9195 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9196 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9197 // TODO(gman): decide how to remove the need for this const_cast.
9198 // I could make validators_ non const but that seems bad as this is the only
9199 // place it is needed. I could make some special friend class of validators
9200 // just to allow this to set them. That seems silly. I could refactor this
9201 // code to use the extension mechanism or the initialization attributes to
9202 // turn this feature on. Given that the only real point of this is to make
9203 // the conformance tests pass and given that there is lots of real work that
9204 // needs to be done it seems like refactoring for one to one of those
9205 // methods is a very low priority.
9206 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9207 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9208 force_webgl_glsl_validation_ = true;
9209 InitializeShaderTranslator();
9210 } else {
9211 return error::kNoError;
9214 *result = 1; // true.
9215 return error::kNoError;
9218 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9219 uint32 immediate_data_size,
9220 const cmds::GetRequestableExtensionsCHROMIUM& c) {
9221 Bucket* bucket = CreateBucket(c.bucket_id);
9222 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9223 info->Initialize(disallowed_features_);
9224 bucket->SetFromString(info->extensions().c_str());
9225 return error::kNoError;
9228 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9229 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
9230 Bucket* bucket = GetBucket(c.bucket_id);
9231 if (!bucket || bucket->size() == 0) {
9232 return error::kInvalidArguments;
9234 std::string feature_str;
9235 if (!bucket->GetAsString(&feature_str)) {
9236 return error::kInvalidArguments;
9239 bool desire_webgl_glsl_validation =
9240 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9241 bool desire_standard_derivatives = false;
9242 bool desire_frag_depth = false;
9243 bool desire_draw_buffers = false;
9244 bool desire_shader_texture_lod = false;
9245 if (force_webgl_glsl_validation_) {
9246 desire_standard_derivatives =
9247 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9248 desire_frag_depth =
9249 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9250 desire_draw_buffers =
9251 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9252 desire_shader_texture_lod =
9253 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
9256 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9257 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9258 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9259 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9260 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9261 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9262 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9263 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9264 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
9265 InitializeShaderTranslator();
9268 UpdateCapabilities();
9270 return error::kNoError;
9273 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9274 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
9275 GLuint count = c.count;
9276 uint32 pnames_size;
9277 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9278 return error::kOutOfBounds;
9280 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9281 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9282 if (pnames == NULL) {
9283 return error::kOutOfBounds;
9286 // We have to copy them since we use them twice so the client
9287 // can't change them between the time we validate them and the time we use
9288 // them.
9289 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9290 memcpy(enums.get(), pnames, pnames_size);
9292 // Count up the space needed for the result.
9293 uint32 num_results = 0;
9294 for (GLuint ii = 0; ii < count; ++ii) {
9295 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9296 if (num == 0) {
9297 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9298 "glGetMultipleCHROMIUM", enums[ii], "pname");
9299 return error::kNoError;
9301 // Num will never be more than 4.
9302 DCHECK_LE(num, 4u);
9303 if (!SafeAddUint32(num_results, num, &num_results)) {
9304 return error::kOutOfBounds;
9308 uint32 result_size = 0;
9309 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9310 return error::kOutOfBounds;
9313 if (result_size != static_cast<uint32>(c.size)) {
9314 LOCAL_SET_GL_ERROR(
9315 GL_INVALID_VALUE,
9316 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9317 return error::kNoError;
9320 GLint* results = GetSharedMemoryAs<GLint*>(
9321 c.results_shm_id, c.results_shm_offset, result_size);
9322 if (results == NULL) {
9323 return error::kOutOfBounds;
9326 // Check the results have been cleared in case the context was lost.
9327 for (uint32 ii = 0; ii < num_results; ++ii) {
9328 if (results[ii]) {
9329 return error::kInvalidArguments;
9333 // Get each result.
9334 GLint* start = results;
9335 for (GLuint ii = 0; ii < count; ++ii) {
9336 GLsizei num_written = 0;
9337 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9338 !GetHelper(enums[ii], results, &num_written)) {
9339 DoGetIntegerv(enums[ii], results);
9341 results += num_written;
9344 // Just to verify. Should this be a DCHECK?
9345 if (static_cast<uint32>(results - start) != num_results) {
9346 return error::kOutOfBounds;
9349 return error::kNoError;
9352 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9353 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
9354 GLuint program_id = static_cast<GLuint>(c.program);
9355 uint32 bucket_id = c.bucket_id;
9356 Bucket* bucket = CreateBucket(bucket_id);
9357 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9358 Program* program = NULL;
9359 program = GetProgram(program_id);
9360 if (!program || !program->IsValid()) {
9361 return error::kNoError;
9363 program->GetProgramInfo(program_manager(), bucket);
9364 return error::kNoError;
9367 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9368 switch (reset_status_) {
9369 case GL_NO_ERROR:
9370 // TODO(kbr): improve the precision of the error code in this case.
9371 // Consider delegating to context for error code if MakeCurrent fails.
9372 return error::kUnknown;
9373 case GL_GUILTY_CONTEXT_RESET_ARB:
9374 return error::kGuilty;
9375 case GL_INNOCENT_CONTEXT_RESET_ARB:
9376 return error::kInnocent;
9377 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9378 return error::kUnknown;
9381 NOTREACHED();
9382 return error::kUnknown;
9385 bool GLES2DecoderImpl::WasContextLost() {
9386 if (reset_status_ != GL_NO_ERROR) {
9387 return true;
9389 if (context_->WasAllocatedUsingRobustnessExtension()) {
9390 GLenum status = GL_NO_ERROR;
9391 if (has_robustness_extension_)
9392 status = glGetGraphicsResetStatusARB();
9393 if (status != GL_NO_ERROR) {
9394 // The graphics card was reset. Signal a lost context to the application.
9395 reset_status_ = status;
9396 reset_by_robustness_extension_ = true;
9397 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9398 << " context lost via ARB/EXT_robustness. Reset status = "
9399 << GLES2Util::GetStringEnum(status);
9400 return true;
9403 return false;
9406 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9407 return WasContextLost() && reset_by_robustness_extension_;
9410 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9411 // Only loses the context once.
9412 if (reset_status_ != GL_NO_ERROR) {
9413 return;
9416 // Marks this context as lost.
9417 reset_status_ = reset_status;
9418 current_decoder_error_ = error::kLostContext;
9421 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9422 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9423 return error::kUnknownCommand;
9426 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9427 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9428 group_->mailbox_manager()->PullTextureUpdates();
9429 if (wait_sync_point_callback_.is_null())
9430 return error::kNoError;
9432 return wait_sync_point_callback_.Run(c.sync_point) ?
9433 error::kNoError : error::kDeferCommandUntilLater;
9436 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9437 uint32 immediate_data_size, const cmds::DiscardBackbufferCHROMIUM& c) {
9438 if (surface_->DeferDraws())
9439 return error::kDeferCommandUntilLater;
9440 if (!surface_->SetBackbufferAllocation(false))
9441 return error::kLostContext;
9442 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9443 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9444 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9445 return error::kNoError;
9448 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9449 GLsizei n, const GLuint* client_ids) {
9450 for (GLsizei ii = 0; ii < n; ++ii) {
9451 if (query_manager_->GetQuery(client_ids[ii])) {
9452 return false;
9455 query_manager_->GenQueries(n, client_ids);
9456 return true;
9459 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9460 GLsizei n, const GLuint* client_ids) {
9461 for (GLsizei ii = 0; ii < n; ++ii) {
9462 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9463 if (query && !query->IsDeleted()) {
9464 ContextState::QueryMap::iterator it =
9465 state_.current_queries.find(query->target());
9466 if (it != state_.current_queries.end())
9467 state_.current_queries.erase(it);
9469 query->Destroy(true);
9471 query_manager_->RemoveQuery(client_ids[ii]);
9475 bool GLES2DecoderImpl::ProcessPendingQueries() {
9476 if (query_manager_.get() == NULL) {
9477 return false;
9479 if (!query_manager_->ProcessPendingQueries()) {
9480 current_decoder_error_ = error::kOutOfBounds;
9482 return query_manager_->HavePendingQueries();
9485 // Note that if there are no pending readpixels right now,
9486 // this function will call the callback immediately.
9487 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9488 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9489 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9490 } else {
9491 callback.Run();
9495 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9496 while (!pending_readpixel_fences_.empty() &&
9497 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9498 std::vector<base::Closure> callbacks =
9499 pending_readpixel_fences_.front()->callbacks;
9500 pending_readpixel_fences_.pop();
9501 for (size_t i = 0; i < callbacks.size(); i++) {
9502 callbacks[i].Run();
9507 bool GLES2DecoderImpl::HasMoreIdleWork() {
9508 return !pending_readpixel_fences_.empty() ||
9509 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9512 void GLES2DecoderImpl::PerformIdleWork() {
9513 ProcessPendingReadPixels();
9514 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9515 return;
9516 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9517 ProcessFinishedAsyncTransfers();
9520 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
9521 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
9522 GLenum target = static_cast<GLenum>(c.target);
9523 GLuint client_id = static_cast<GLuint>(c.id);
9524 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9525 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9527 switch (target) {
9528 case GL_COMMANDS_ISSUED_CHROMIUM:
9529 case GL_LATENCY_QUERY_CHROMIUM:
9530 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9531 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9532 case GL_GET_ERROR_QUERY_CHROMIUM:
9533 break;
9534 case GL_COMMANDS_COMPLETED_CHROMIUM:
9535 if (!features().chromium_sync_query) {
9536 LOCAL_SET_GL_ERROR(
9537 GL_INVALID_OPERATION, "glBeginQueryEXT",
9538 "not enabled for commands completed queries");
9539 return error::kNoError;
9541 break;
9542 default:
9543 if (!features().occlusion_query_boolean) {
9544 LOCAL_SET_GL_ERROR(
9545 GL_INVALID_OPERATION, "glBeginQueryEXT",
9546 "not enabled for occlusion queries");
9547 return error::kNoError;
9549 break;
9552 if (state_.current_queries.find(target) != state_.current_queries.end()) {
9553 LOCAL_SET_GL_ERROR(
9554 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9555 return error::kNoError;
9558 if (client_id == 0) {
9559 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9560 return error::kNoError;
9563 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9564 if (!query) {
9565 if (!query_manager_->IsValidQuery(client_id)) {
9566 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9567 "glBeginQueryEXT",
9568 "id not made by glGenQueriesEXT");
9569 return error::kNoError;
9571 query = query_manager_->CreateQuery(
9572 target, client_id, sync_shm_id, sync_shm_offset);
9575 if (query->target() != target) {
9576 LOCAL_SET_GL_ERROR(
9577 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9578 return error::kNoError;
9579 } else if (query->shm_id() != sync_shm_id ||
9580 query->shm_offset() != sync_shm_offset) {
9581 DLOG(ERROR) << "Shared memory used by query not the same as before";
9582 return error::kInvalidArguments;
9585 if (!query_manager_->BeginQuery(query)) {
9586 return error::kOutOfBounds;
9589 state_.current_queries[target] = query;
9590 return error::kNoError;
9593 error::Error GLES2DecoderImpl::HandleEndQueryEXT(
9594 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
9595 GLenum target = static_cast<GLenum>(c.target);
9596 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9597 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
9599 if (it == state_.current_queries.end()) {
9600 LOCAL_SET_GL_ERROR(
9601 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9602 return error::kNoError;
9605 QueryManager::Query* query = it->second.get();
9606 if (!query_manager_->EndQuery(query, submit_count)) {
9607 return error::kOutOfBounds;
9610 query_manager_->ProcessPendingTransferQueries();
9612 state_.current_queries.erase(it);
9613 return error::kNoError;
9616 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9617 GLsizei n, const GLuint* client_ids) {
9618 for (GLsizei ii = 0; ii < n; ++ii) {
9619 if (GetVertexAttribManager(client_ids[ii])) {
9620 return false;
9624 if (!features().native_vertex_array_object) {
9625 // Emulated VAO
9626 for (GLsizei ii = 0; ii < n; ++ii) {
9627 CreateVertexAttribManager(client_ids[ii], 0, true);
9629 } else {
9630 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9632 glGenVertexArraysOES(n, service_ids.get());
9633 for (GLsizei ii = 0; ii < n; ++ii) {
9634 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
9638 return true;
9641 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9642 GLsizei n, const GLuint* client_ids) {
9643 for (GLsizei ii = 0; ii < n; ++ii) {
9644 VertexAttribManager* vao =
9645 GetVertexAttribManager(client_ids[ii]);
9646 if (vao && !vao->IsDeleted()) {
9647 if (state_.vertex_attrib_manager.get() == vao) {
9648 DoBindVertexArrayOES(0);
9650 RemoveVertexAttribManager(client_ids[ii]);
9655 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9656 VertexAttribManager* vao = NULL;
9657 if (client_id != 0) {
9658 vao = GetVertexAttribManager(client_id);
9659 if (!vao) {
9660 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9661 // only allows names that have been previously generated. As such, we do
9662 // not generate new names here.
9663 LOCAL_SET_GL_ERROR(
9664 GL_INVALID_OPERATION,
9665 "glBindVertexArrayOES", "bad vertex array id.");
9666 current_decoder_error_ = error::kNoError;
9667 return;
9669 } else {
9670 vao = state_.default_vertex_attrib_manager.get();
9673 // Only set the VAO state if it's changed
9674 if (state_.vertex_attrib_manager.get() != vao) {
9675 state_.vertex_attrib_manager = vao;
9676 if (!features().native_vertex_array_object) {
9677 EmulateVertexArrayState();
9678 } else {
9679 GLuint service_id = vao->service_id();
9680 glBindVertexArrayOES(service_id);
9685 // Used when OES_vertex_array_object isn't natively supported
9686 void GLES2DecoderImpl::EmulateVertexArrayState() {
9687 // Setup the Vertex attribute state
9688 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9689 RestoreStateForAttrib(vv, true);
9692 // Setup the element buffer
9693 Buffer* element_array_buffer =
9694 state_.vertex_attrib_manager->element_array_buffer();
9695 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9696 element_array_buffer ? element_array_buffer->service_id() : 0);
9699 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9700 const VertexAttribManager* vao =
9701 GetVertexAttribManager(client_id);
9702 return vao && vao->IsValid() && !vao->IsDeleted();
9705 #if defined(OS_MACOSX)
9706 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9707 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9708 texture_id);
9709 if (it != texture_to_io_surface_map_.end()) {
9710 // Found a previous IOSurface bound to this texture; release it.
9711 IOSurfaceRef surface = it->second;
9712 CFRelease(surface);
9713 texture_to_io_surface_map_.erase(it);
9716 #endif
9718 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9719 GLenum target, GLsizei width, GLsizei height,
9720 GLuint io_surface_id, GLuint plane) {
9721 #if defined(OS_MACOSX)
9722 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
9723 LOCAL_SET_GL_ERROR(
9724 GL_INVALID_OPERATION,
9725 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9726 return;
9729 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9730 // This might be supported in the future, and if we could require
9731 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9732 // could delete a lot of code. For now, perform strict validation so we
9733 // know what's going on.
9734 LOCAL_SET_GL_ERROR(
9735 GL_INVALID_OPERATION,
9736 "glTexImageIOSurface2DCHROMIUM",
9737 "requires TEXTURE_RECTANGLE_ARB target");
9738 return;
9741 // Default target might be conceptually valid, but disallow it to avoid
9742 // accidents.
9743 TextureRef* texture_ref =
9744 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9745 if (!texture_ref) {
9746 LOCAL_SET_GL_ERROR(
9747 GL_INVALID_OPERATION,
9748 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9749 return;
9752 // Look up the new IOSurface. Note that because of asynchrony
9753 // between processes this might fail; during live resizing the
9754 // plugin process might allocate and release an IOSurface before
9755 // this process gets a chance to look it up. Hold on to any old
9756 // IOSurface in this case.
9757 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
9758 if (!surface) {
9759 LOCAL_SET_GL_ERROR(
9760 GL_INVALID_OPERATION,
9761 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9762 return;
9765 // Release any IOSurface previously bound to this texture.
9766 ReleaseIOSurfaceForTexture(texture_ref->service_id());
9768 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9769 texture_to_io_surface_map_.insert(
9770 std::make_pair(texture_ref->service_id(), surface));
9772 CGLContextObj context =
9773 static_cast<CGLContextObj>(context_->GetHandle());
9775 CGLError err = CGLTexImageIOSurface2D(
9776 context,
9777 target,
9778 GL_RGBA,
9779 width,
9780 height,
9781 GL_BGRA,
9782 GL_UNSIGNED_INT_8_8_8_8_REV,
9783 surface,
9784 plane);
9786 if (err != kCGLNoError) {
9787 LOCAL_SET_GL_ERROR(
9788 GL_INVALID_OPERATION,
9789 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9790 return;
9793 texture_manager()->SetLevelInfo(
9794 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
9795 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9797 #else
9798 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9799 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9800 #endif
9803 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9804 switch (internalformat) {
9805 case GL_RGB565:
9806 return GL_RGB;
9807 case GL_RGBA4:
9808 return GL_RGBA;
9809 case GL_RGB5_A1:
9810 return GL_RGBA;
9811 case GL_RGB8_OES:
9812 return GL_RGB;
9813 case GL_RGBA8_OES:
9814 return GL_RGBA;
9815 case GL_LUMINANCE8_ALPHA8_EXT:
9816 return GL_LUMINANCE_ALPHA;
9817 case GL_LUMINANCE8_EXT:
9818 return GL_LUMINANCE;
9819 case GL_ALPHA8_EXT:
9820 return GL_ALPHA;
9821 case GL_RGBA32F_EXT:
9822 return GL_RGBA;
9823 case GL_RGB32F_EXT:
9824 return GL_RGB;
9825 case GL_ALPHA32F_EXT:
9826 return GL_ALPHA;
9827 case GL_LUMINANCE32F_EXT:
9828 return GL_LUMINANCE;
9829 case GL_LUMINANCE_ALPHA32F_EXT:
9830 return GL_LUMINANCE_ALPHA;
9831 case GL_RGBA16F_EXT:
9832 return GL_RGBA;
9833 case GL_RGB16F_EXT:
9834 return GL_RGB;
9835 case GL_ALPHA16F_EXT:
9836 return GL_ALPHA;
9837 case GL_LUMINANCE16F_EXT:
9838 return GL_LUMINANCE;
9839 case GL_LUMINANCE_ALPHA16F_EXT:
9840 return GL_LUMINANCE_ALPHA;
9841 case GL_BGRA8_EXT:
9842 return GL_BGRA_EXT;
9843 default:
9844 return GL_NONE;
9848 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9849 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
9850 GLenum internal_format, GLenum dest_type) {
9851 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
9853 TextureRef* dest_texture_ref = GetTexture(dest_id);
9854 TextureRef* source_texture_ref = GetTexture(source_id);
9856 if (!source_texture_ref || !dest_texture_ref) {
9857 LOCAL_SET_GL_ERROR(
9858 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
9859 return;
9862 if (GL_TEXTURE_2D != target) {
9863 LOCAL_SET_GL_ERROR(
9864 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
9865 return;
9868 Texture* source_texture = source_texture_ref->texture();
9869 Texture* dest_texture = dest_texture_ref->texture();
9870 if (dest_texture->target() != GL_TEXTURE_2D ||
9871 (source_texture->target() != GL_TEXTURE_2D &&
9872 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
9873 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
9874 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9875 "glCopyTextureCHROMIUM",
9876 "invalid texture target binding");
9877 return;
9880 int source_width, source_height, dest_width, dest_height;
9882 gfx::GLImage* image =
9883 source_texture->GetLevelImage(source_texture->target(), 0);
9884 if (image) {
9885 gfx::Size size = image->GetSize();
9886 source_width = size.width();
9887 source_height = size.height();
9888 if (source_width <= 0 || source_height <= 0) {
9889 LOCAL_SET_GL_ERROR(
9890 GL_INVALID_VALUE,
9891 "glCopyTextureChromium", "invalid image size");
9892 return;
9894 } else {
9895 if (!source_texture->GetLevelSize(
9896 source_texture->target(), 0, &source_width, &source_height)) {
9897 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9898 "glCopyTextureChromium",
9899 "source texture has no level 0");
9900 return;
9903 // Check that this type of texture is allowed.
9904 if (!texture_manager()->ValidForTarget(
9905 source_texture->target(), level, source_width, source_height, 1)) {
9906 LOCAL_SET_GL_ERROR(
9907 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
9908 return;
9912 // Clear the source texture if necessary.
9913 if (!texture_manager()->ClearTextureLevel(
9914 this, source_texture_ref, source_texture->target(), 0)) {
9915 LOCAL_SET_GL_ERROR(
9916 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
9917 return;
9920 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9921 // needed because it takes 10s of milliseconds to initialize.
9922 if (!copy_texture_CHROMIUM_.get()) {
9923 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9924 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
9925 copy_texture_CHROMIUM_->Initialize(this);
9926 RestoreCurrentFramebufferBindings();
9927 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
9928 return;
9931 GLenum dest_type_previous;
9932 GLenum dest_internal_format;
9933 bool dest_level_defined = dest_texture->GetLevelSize(
9934 GL_TEXTURE_2D, level, &dest_width, &dest_height);
9936 if (dest_level_defined) {
9937 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
9938 &dest_internal_format);
9941 // Resize the destination texture to the dimensions of the source texture.
9942 if (!dest_level_defined || dest_width != source_width ||
9943 dest_height != source_height ||
9944 dest_internal_format != internal_format ||
9945 dest_type_previous != dest_type) {
9946 // Ensure that the glTexImage2D succeeds.
9947 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9948 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
9949 glTexImage2D(
9950 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
9951 0, internal_format, dest_type, NULL);
9952 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9953 if (error != GL_NO_ERROR) {
9954 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
9955 return;
9958 texture_manager()->SetLevelInfo(
9959 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
9960 source_height, 1, 0, internal_format, dest_type, true);
9961 } else {
9962 texture_manager()->SetLevelCleared(
9963 dest_texture_ref, GL_TEXTURE_2D, level, true);
9966 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
9967 ScopedModifyPixels modify(dest_texture_ref);
9969 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9970 // before presenting.
9971 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9972 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9973 // instead of using default matrix crbug.com/226218.
9974 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9975 0.0f, 1.0f, 0.0f, 0.0f,
9976 0.0f, 0.0f, 1.0f, 0.0f,
9977 0.0f, 0.0f, 0.0f, 1.0f};
9978 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9979 this,
9980 source_texture->target(),
9981 dest_texture->target(),
9982 source_texture->service_id(),
9983 dest_texture->service_id(), level,
9984 source_width, source_height,
9985 unpack_flip_y_,
9986 unpack_premultiply_alpha_,
9987 unpack_unpremultiply_alpha_,
9988 default_matrix);
9989 } else {
9990 copy_texture_CHROMIUM_->DoCopyTexture(
9991 this,
9992 source_texture->target(),
9993 dest_texture->target(),
9994 source_texture->service_id(),
9995 dest_texture->service_id(), level,
9996 source_width, source_height,
9997 unpack_flip_y_,
9998 unpack_premultiply_alpha_,
9999 unpack_unpremultiply_alpha_);
10002 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
10005 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
10006 switch (internalformat) {
10007 case GL_RGB565:
10008 return GL_UNSIGNED_SHORT_5_6_5;
10009 case GL_RGBA4:
10010 return GL_UNSIGNED_SHORT_4_4_4_4;
10011 case GL_RGB5_A1:
10012 return GL_UNSIGNED_SHORT_5_5_5_1;
10013 case GL_RGB8_OES:
10014 return GL_UNSIGNED_BYTE;
10015 case GL_RGBA8_OES:
10016 return GL_UNSIGNED_BYTE;
10017 case GL_LUMINANCE8_ALPHA8_EXT:
10018 return GL_UNSIGNED_BYTE;
10019 case GL_LUMINANCE8_EXT:
10020 return GL_UNSIGNED_BYTE;
10021 case GL_ALPHA8_EXT:
10022 return GL_UNSIGNED_BYTE;
10023 case GL_RGBA32F_EXT:
10024 return GL_FLOAT;
10025 case GL_RGB32F_EXT:
10026 return GL_FLOAT;
10027 case GL_ALPHA32F_EXT:
10028 return GL_FLOAT;
10029 case GL_LUMINANCE32F_EXT:
10030 return GL_FLOAT;
10031 case GL_LUMINANCE_ALPHA32F_EXT:
10032 return GL_FLOAT;
10033 case GL_RGBA16F_EXT:
10034 return GL_HALF_FLOAT_OES;
10035 case GL_RGB16F_EXT:
10036 return GL_HALF_FLOAT_OES;
10037 case GL_ALPHA16F_EXT:
10038 return GL_HALF_FLOAT_OES;
10039 case GL_LUMINANCE16F_EXT:
10040 return GL_HALF_FLOAT_OES;
10041 case GL_LUMINANCE_ALPHA16F_EXT:
10042 return GL_HALF_FLOAT_OES;
10043 case GL_BGRA8_EXT:
10044 return GL_UNSIGNED_BYTE;
10045 default:
10046 return GL_NONE;
10050 void GLES2DecoderImpl::DoTexStorage2DEXT(
10051 GLenum target,
10052 GLint levels,
10053 GLenum internal_format,
10054 GLsizei width,
10055 GLsizei height) {
10056 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10057 "width", width, "height", height);
10058 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
10059 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
10060 LOCAL_SET_GL_ERROR(
10061 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
10062 return;
10064 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10065 &state_, target);
10066 if (!texture_ref) {
10067 LOCAL_SET_GL_ERROR(
10068 GL_INVALID_OPERATION,
10069 "glTexStorage2DEXT", "unknown texture for target");
10070 return;
10072 Texture* texture = texture_ref->texture();
10073 if (texture->IsAttachedToFramebuffer()) {
10074 framebuffer_state_.clear_state_dirty = true;
10076 if (texture->IsImmutable()) {
10077 LOCAL_SET_GL_ERROR(
10078 GL_INVALID_OPERATION,
10079 "glTexStorage2DEXT", "texture is immutable");
10080 return;
10083 GLenum format = ExtractFormatFromStorageFormat(internal_format);
10084 GLenum type = ExtractTypeFromStorageFormat(internal_format);
10087 GLsizei level_width = width;
10088 GLsizei level_height = height;
10089 uint32 estimated_size = 0;
10090 for (int ii = 0; ii < levels; ++ii) {
10091 uint32 level_size = 0;
10092 if (!GLES2Util::ComputeImageDataSizes(
10093 level_width, level_height, format, type, state_.unpack_alignment,
10094 &estimated_size, NULL, NULL) ||
10095 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
10096 LOCAL_SET_GL_ERROR(
10097 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
10098 return;
10100 level_width = std::max(1, level_width >> 1);
10101 level_height = std::max(1, level_height >> 1);
10103 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10104 LOCAL_SET_GL_ERROR(
10105 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
10106 return;
10110 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10111 glTexStorage2DEXT(target, levels, internal_format, width, height);
10112 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10113 if (error == GL_NO_ERROR) {
10114 GLsizei level_width = width;
10115 GLsizei level_height = height;
10116 for (int ii = 0; ii < levels; ++ii) {
10117 texture_manager()->SetLevelInfo(
10118 texture_ref, target, ii, format,
10119 level_width, level_height, 1, 0, format, type, false);
10120 level_width = std::max(1, level_width >> 1);
10121 level_height = std::max(1, level_height >> 1);
10123 texture->SetImmutable(true);
10127 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10128 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
10129 return error::kUnknownCommand;
10132 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10133 const GLbyte* data) {
10134 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10135 "context", logger_.GetLogPrefix(),
10136 "mailbox[0]", static_cast<unsigned char>(data[0]));
10138 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10139 &state_, target);
10140 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
10143 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
10144 GLenum target, const GLbyte* data) {
10145 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10146 "context", logger_.GetLogPrefix(),
10147 "mailbox[0]", static_cast<unsigned char>(data[0]));
10149 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
10150 target, data);
10153 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
10154 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
10155 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10156 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
10157 "mailbox that was not generated by "
10158 "GenMailboxCHROMIUM.";
10160 if (!texture_ref) {
10161 LOCAL_SET_GL_ERROR(
10162 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
10163 return;
10166 Texture* produced = texture_manager()->Produce(texture_ref);
10167 if (!produced) {
10168 LOCAL_SET_GL_ERROR(
10169 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
10170 return;
10173 if (produced->target() != target) {
10174 LOCAL_SET_GL_ERROR(
10175 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
10176 return;
10179 group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
10182 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10183 const GLbyte* data) {
10184 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10185 "context", logger_.GetLogPrefix(),
10186 "mailbox[0]", static_cast<unsigned char>(data[0]));
10187 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10188 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10189 "mailbox that was not generated by "
10190 "GenMailboxCHROMIUM.";
10192 scoped_refptr<TextureRef> texture_ref =
10193 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10194 if (!texture_ref.get()) {
10195 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10196 "glConsumeTextureCHROMIUM",
10197 "unknown texture for target");
10198 return;
10200 GLuint client_id = texture_ref->client_id();
10201 if (!client_id) {
10202 LOCAL_SET_GL_ERROR(
10203 GL_INVALID_OPERATION,
10204 "glConsumeTextureCHROMIUM", "unknown texture for target");
10205 return;
10207 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10208 if (!texture) {
10209 LOCAL_SET_GL_ERROR(
10210 GL_INVALID_OPERATION,
10211 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10212 return;
10214 if (texture->target() != target) {
10215 LOCAL_SET_GL_ERROR(
10216 GL_INVALID_OPERATION,
10217 "glConsumeTextureCHROMIUM", "invalid target");
10218 return;
10221 DeleteTexturesHelper(1, &client_id);
10222 texture_ref = texture_manager()->Consume(client_id, texture);
10223 glBindTexture(target, texture_ref->service_id());
10225 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10226 unit.bind_target = target;
10227 switch (target) {
10228 case GL_TEXTURE_2D:
10229 unit.bound_texture_2d = texture_ref;
10230 break;
10231 case GL_TEXTURE_CUBE_MAP:
10232 unit.bound_texture_cube_map = texture_ref;
10233 break;
10234 case GL_TEXTURE_EXTERNAL_OES:
10235 unit.bound_texture_external_oes = texture_ref;
10236 break;
10237 case GL_TEXTURE_RECTANGLE_ARB:
10238 unit.bound_texture_rectangle_arb = texture_ref;
10239 break;
10240 default:
10241 NOTREACHED(); // Validation should prevent us getting here.
10242 break;
10246 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10247 uint32_t immediate_data_size,
10248 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c) {
10249 GLenum target = static_cast<GLenum>(c.target);
10250 uint32_t data_size;
10251 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
10252 return error::kOutOfBounds;
10254 if (data_size > immediate_data_size) {
10255 return error::kOutOfBounds;
10257 const GLbyte* mailbox =
10258 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
10259 if (!validators_->texture_bind_target.IsValid(target)) {
10260 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10261 "glCreateAndConsumeTextureCHROMIUM", target, "target");
10262 return error::kNoError;
10264 if (mailbox == NULL) {
10265 return error::kOutOfBounds;
10267 uint32_t client_id = c.client_id;
10268 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
10269 return error::kNoError;
10272 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
10273 const GLbyte* data, GLuint client_id) {
10274 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
10275 "context", logger_.GetLogPrefix(),
10276 "mailbox[0]", static_cast<unsigned char>(data[0]));
10277 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10278 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
10279 "passed a mailbox that was not "
10280 "generated by GenMailboxCHROMIUM.";
10282 TextureRef* texture_ref = GetTexture(client_id);
10283 if (texture_ref) {
10284 LOCAL_SET_GL_ERROR(
10285 GL_INVALID_OPERATION,
10286 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
10287 return;
10289 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10290 if (!texture) {
10291 LOCAL_SET_GL_ERROR(
10292 GL_INVALID_OPERATION,
10293 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
10294 return;
10296 if (texture->target() != target) {
10297 LOCAL_SET_GL_ERROR(
10298 GL_INVALID_OPERATION,
10299 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
10300 return;
10303 IdAllocatorInterface* id_allocator =
10304 group_->GetIdAllocator(id_namespaces::kTextures);
10305 id_allocator->MarkAsUsed(client_id);
10307 texture_ref = texture_manager()->Consume(client_id, texture);
10310 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10311 GLsizei length, const GLchar* marker) {
10312 if (!marker) {
10313 marker = "";
10315 debug_marker_manager_.SetMarker(
10316 length ? std::string(marker, length) : std::string(marker));
10319 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10320 GLsizei length, const GLchar* marker) {
10321 if (!marker) {
10322 marker = "";
10324 std::string name = length ? std::string(marker, length) : std::string(marker);
10325 debug_marker_manager_.PushGroup(name);
10326 gpu_tracer_->Begin(name, kTraceGroupMarker);
10329 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10330 debug_marker_manager_.PopGroup();
10331 gpu_tracer_->End(kTraceGroupMarker);
10334 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10335 GLenum target, GLint image_id) {
10336 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10338 if (target == GL_TEXTURE_CUBE_MAP) {
10339 LOCAL_SET_GL_ERROR(
10340 GL_INVALID_ENUM,
10341 "glBindTexImage2DCHROMIUM", "invalid target");
10342 return;
10345 // Default target might be conceptually valid, but disallow it to avoid
10346 // accidents.
10347 TextureRef* texture_ref =
10348 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10349 if (!texture_ref) {
10350 LOCAL_SET_GL_ERROR(
10351 GL_INVALID_OPERATION,
10352 "glBindTexImage2DCHROMIUM", "no texture bound");
10353 return;
10356 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10357 if (!gl_image) {
10358 LOCAL_SET_GL_ERROR(
10359 GL_INVALID_OPERATION,
10360 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10361 return;
10365 ScopedGLErrorSuppressor suppressor(
10366 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10367 if (!gl_image->BindTexImage(target)) {
10368 LOCAL_SET_GL_ERROR(
10369 GL_INVALID_OPERATION,
10370 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10371 return;
10375 gfx::Size size = gl_image->GetSize();
10376 texture_manager()->SetLevelInfo(
10377 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10378 GL_RGBA, GL_UNSIGNED_BYTE, true);
10379 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10382 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10383 GLenum target, GLint image_id) {
10384 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10386 // Default target might be conceptually valid, but disallow it to avoid
10387 // accidents.
10388 TextureRef* texture_ref =
10389 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10390 if (!texture_ref) {
10391 LOCAL_SET_GL_ERROR(
10392 GL_INVALID_OPERATION,
10393 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10394 return;
10397 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10398 if (!gl_image) {
10399 LOCAL_SET_GL_ERROR(
10400 GL_INVALID_OPERATION,
10401 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10402 return;
10405 // Do nothing when image is not currently bound.
10406 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10407 return;
10410 ScopedGLErrorSuppressor suppressor(
10411 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10412 gl_image->ReleaseTexImage(target);
10415 texture_manager()->SetLevelInfo(
10416 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10417 GL_RGBA, GL_UNSIGNED_BYTE, false);
10420 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10421 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10422 Bucket* bucket = GetBucket(c.bucket_id);
10423 if (!bucket || bucket->size() == 0) {
10424 return error::kInvalidArguments;
10426 std::string command_name;
10427 if (!bucket->GetAsString(&command_name)) {
10428 return error::kInvalidArguments;
10430 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10431 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
10432 LOCAL_SET_GL_ERROR(
10433 GL_INVALID_OPERATION,
10434 "glTraceBeginCHROMIUM", "unable to create begin trace");
10435 return error::kNoError;
10437 return error::kNoError;
10440 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10441 if (gpu_tracer_->CurrentName().empty()) {
10442 LOCAL_SET_GL_ERROR(
10443 GL_INVALID_OPERATION,
10444 "glTraceEndCHROMIUM", "no trace begin found");
10445 return;
10447 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10448 gpu_tracer_->End(kTraceCHROMIUM);
10451 void GLES2DecoderImpl::DoDrawBuffersEXT(
10452 GLsizei count, const GLenum* bufs) {
10453 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10454 LOCAL_SET_GL_ERROR(
10455 GL_INVALID_VALUE,
10456 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10457 return;
10460 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10461 if (framebuffer) {
10462 for (GLsizei i = 0; i < count; ++i) {
10463 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10464 bufs[i] != GL_NONE) {
10465 LOCAL_SET_GL_ERROR(
10466 GL_INVALID_OPERATION,
10467 "glDrawBuffersEXT",
10468 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10469 return;
10472 glDrawBuffersARB(count, bufs);
10473 framebuffer->SetDrawBuffers(count, bufs);
10474 } else { // backbuffer
10475 if (count > 1 ||
10476 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10477 LOCAL_SET_GL_ERROR(
10478 GL_INVALID_OPERATION,
10479 "glDrawBuffersEXT",
10480 "more than one buffer or bufs not GL_NONE or GL_BACK");
10481 return;
10483 GLenum mapped_buf = bufs[0];
10484 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10485 bufs[0] == GL_BACK) {
10486 mapped_buf = GL_COLOR_ATTACHMENT0;
10488 glDrawBuffersARB(count, &mapped_buf);
10489 group_->set_draw_buffer(bufs[0]);
10493 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
10494 group_->LoseContexts(other);
10495 reset_status_ = current;
10496 current_decoder_error_ = error::kLostContext;
10499 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10500 const char* function_name,
10501 TextureRef* texture_ref,
10502 GLenum target,
10503 GLint level,
10504 const void * data) {
10505 // We only support async uploads to 2D textures for now.
10506 if (GL_TEXTURE_2D != target) {
10507 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10508 return false;
10510 // We only support uploads to level zero for now.
10511 if (level != 0) {
10512 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10513 return false;
10515 // A transfer buffer must be bound, even for asyncTexImage2D.
10516 if (data == NULL) {
10517 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10518 return false;
10520 // We only support one async transfer in progress.
10521 if (!texture_ref ||
10522 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10523 LOCAL_SET_GL_ERROR(
10524 GL_INVALID_OPERATION,
10525 function_name, "transfer already in progress");
10526 return false;
10528 return true;
10531 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
10532 uint32 async_upload_token,
10533 uint32 sync_data_shm_id,
10534 uint32 sync_data_shm_offset) {
10535 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
10536 if (!buffer || !buffer->GetDataAddress(sync_data_shm_offset,
10537 sizeof(AsyncUploadSync)))
10538 return base::Closure();
10540 AsyncMemoryParams mem_params(buffer,
10541 sync_data_shm_offset,
10542 sizeof(AsyncUploadSync));
10544 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
10545 new AsyncUploadTokenCompletionObserver(async_upload_token));
10547 return base::Bind(
10548 &AsyncPixelTransferManager::AsyncNotifyCompletion,
10549 base::Unretained(GetAsyncPixelTransferManager()),
10550 mem_params,
10551 observer);
10554 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10555 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10556 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10557 GLenum target = static_cast<GLenum>(c.target);
10558 GLint level = static_cast<GLint>(c.level);
10559 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10560 GLsizei width = static_cast<GLsizei>(c.width);
10561 GLsizei height = static_cast<GLsizei>(c.height);
10562 GLint border = static_cast<GLint>(c.border);
10563 GLenum format = static_cast<GLenum>(c.format);
10564 GLenum type = static_cast<GLenum>(c.type);
10565 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10566 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10567 uint32 pixels_size;
10568 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
10569 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
10570 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10572 base::ScopedClosureRunner scoped_completion_callback;
10573 if (async_upload_token) {
10574 base::Closure completion_closure =
10575 AsyncUploadTokenCompletionClosure(async_upload_token,
10576 sync_data_shm_id,
10577 sync_data_shm_offset);
10578 if (completion_closure.is_null())
10579 return error::kInvalidArguments;
10581 scoped_completion_callback.Reset(completion_closure);
10584 // TODO(epenner): Move this and copies of this memory validation
10585 // into ValidateTexImage2D step.
10586 if (!GLES2Util::ComputeImageDataSizes(
10587 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10588 NULL)) {
10589 return error::kOutOfBounds;
10591 const void* pixels = NULL;
10592 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10593 pixels = GetSharedMemoryAs<const void*>(
10594 pixels_shm_id, pixels_shm_offset, pixels_size);
10595 if (!pixels) {
10596 return error::kOutOfBounds;
10600 TextureManager::DoTextImage2DArguments args = {
10601 target, level, internal_format, width, height, border, format, type,
10602 pixels, pixels_size};
10603 TextureRef* texture_ref;
10604 // All the normal glTexSubImage2D validation.
10605 if (!texture_manager()->ValidateTexImage2D(
10606 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
10607 return error::kNoError;
10610 // Extra async validation.
10611 Texture* texture = texture_ref->texture();
10612 if (!ValidateAsyncTransfer(
10613 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
10614 return error::kNoError;
10616 // Don't allow async redefinition of a textures.
10617 if (texture->IsDefined()) {
10618 LOCAL_SET_GL_ERROR(
10619 GL_INVALID_OPERATION,
10620 "glAsyncTexImage2DCHROMIUM", "already defined");
10621 return error::kNoError;
10624 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10625 LOCAL_SET_GL_ERROR(
10626 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10627 return error::kNoError;
10630 // Setup the parameters.
10631 AsyncTexImage2DParams tex_params = {
10632 target, level, static_cast<GLenum>(internal_format),
10633 width, height, border, format, type};
10634 AsyncMemoryParams mem_params(
10635 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
10637 // Set up the async state if needed, and make the texture
10638 // immutable so the async state stays valid. The level info
10639 // is set up lazily when the transfer completes.
10640 AsyncPixelTransferDelegate* delegate =
10641 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10642 tex_params);
10643 texture->SetImmutable(true);
10645 delegate->AsyncTexImage2D(
10646 tex_params,
10647 mem_params,
10648 base::Bind(&TextureManager::SetLevelInfoFromParams,
10649 // The callback is only invoked if the transfer delegate still
10650 // exists, which implies through manager->texture_ref->state
10651 // ownership that both of these pointers are valid.
10652 base::Unretained(texture_manager()),
10653 base::Unretained(texture_ref),
10654 tex_params));
10655 return error::kNoError;
10658 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10659 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10660 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10661 GLenum target = static_cast<GLenum>(c.target);
10662 GLint level = static_cast<GLint>(c.level);
10663 GLint xoffset = static_cast<GLint>(c.xoffset);
10664 GLint yoffset = static_cast<GLint>(c.yoffset);
10665 GLsizei width = static_cast<GLsizei>(c.width);
10666 GLsizei height = static_cast<GLsizei>(c.height);
10667 GLenum format = static_cast<GLenum>(c.format);
10668 GLenum type = static_cast<GLenum>(c.type);
10669 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
10670 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
10671 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10673 base::ScopedClosureRunner scoped_completion_callback;
10674 if (async_upload_token) {
10675 base::Closure completion_closure =
10676 AsyncUploadTokenCompletionClosure(async_upload_token,
10677 sync_data_shm_id,
10678 sync_data_shm_offset);
10679 if (completion_closure.is_null())
10680 return error::kInvalidArguments;
10682 scoped_completion_callback.Reset(completion_closure);
10685 // TODO(epenner): Move this and copies of this memory validation
10686 // into ValidateTexSubImage2D step.
10687 uint32 data_size;
10688 if (!GLES2Util::ComputeImageDataSizes(
10689 width, height, format, type, state_.unpack_alignment, &data_size,
10690 NULL, NULL)) {
10691 return error::kOutOfBounds;
10693 const void* pixels = GetSharedMemoryAs<const void*>(
10694 c.data_shm_id, c.data_shm_offset, data_size);
10696 // All the normal glTexSubImage2D validation.
10697 error::Error error = error::kNoError;
10698 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10699 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10700 return error;
10703 // Extra async validation.
10704 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10705 &state_, target);
10706 Texture* texture = texture_ref->texture();
10707 if (!ValidateAsyncTransfer(
10708 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
10709 return error::kNoError;
10711 // Guarantee async textures are always 'cleared' as follows:
10712 // - AsyncTexImage2D can not redefine an existing texture
10713 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10714 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10715 // - Textures become immutable after an async call.
10716 // This way we know in all cases that an async texture is always clear.
10717 if (!texture->SafeToRenderFrom()) {
10718 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10719 target, level)) {
10720 LOCAL_SET_GL_ERROR(
10721 GL_OUT_OF_MEMORY,
10722 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10723 return error::kNoError;
10727 // Setup the parameters.
10728 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
10729 width, height, format, type};
10730 AsyncMemoryParams mem_params(
10731 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
10732 AsyncPixelTransferDelegate* delegate =
10733 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10734 if (!delegate) {
10735 // TODO(epenner): We may want to enforce exclusive use
10736 // of async APIs in which case this should become an error,
10737 // (the texture should have been async defined).
10738 AsyncTexImage2DParams define_params = {target, level,
10739 0, 0, 0, 0, 0, 0};
10740 texture->GetLevelSize(target, level, &define_params.width,
10741 &define_params.height);
10742 texture->GetLevelType(target, level, &define_params.type,
10743 &define_params.internal_format);
10744 // Set up the async state if needed, and make the texture
10745 // immutable so the async state stays valid.
10746 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
10747 texture_ref, define_params);
10748 texture->SetImmutable(true);
10751 delegate->AsyncTexSubImage2D(tex_params, mem_params);
10752 return error::kNoError;
10755 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10756 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10757 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10758 GLenum target = static_cast<GLenum>(c.target);
10760 if (GL_TEXTURE_2D != target) {
10761 LOCAL_SET_GL_ERROR(
10762 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10763 return error::kNoError;
10765 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10766 &state_, target);
10767 if (!texture_ref) {
10768 LOCAL_SET_GL_ERROR(
10769 GL_INVALID_OPERATION,
10770 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10771 return error::kNoError;
10773 AsyncPixelTransferDelegate* delegate =
10774 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10775 if (!delegate) {
10776 LOCAL_SET_GL_ERROR(
10777 GL_INVALID_OPERATION,
10778 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10779 return error::kNoError;
10781 delegate->WaitForTransferCompletion();
10782 ProcessFinishedAsyncTransfers();
10783 return error::kNoError;
10786 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
10787 uint32 immediate_data_size, const cmds::WaitAllAsyncTexImage2DCHROMIUM& c) {
10788 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10790 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
10791 ProcessFinishedAsyncTransfers();
10792 return error::kNoError;
10795 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10796 TextureRef* texture_ref) {
10797 Texture* texture = texture_ref->texture();
10798 DoDidUseTexImageIfNeeded(texture, texture->target());
10801 void GLES2DecoderImpl::OnOutOfMemoryError() {
10802 if (lose_context_when_out_of_memory_) {
10803 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
10804 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB);
10808 // Include the auto-generated part of this file. We split this because it means
10809 // we can easily edit the non-auto generated parts right here in this file
10810 // instead of having to edit some template or the code generator.
10811 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10813 } // namespace gles2
10814 } // namespace gpu