Remove the now unused TextButton code.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob1c812c755fbbb7ddad34d7fb4951de0b9d50018f
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) 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 RestoreRenderbufferBindings() OVERRIDE;
620 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
622 virtual void ClearAllAttributes() const OVERRIDE;
623 virtual void RestoreAllAttributes() const OVERRIDE;
625 virtual QueryManager* GetQueryManager() OVERRIDE {
626 return query_manager_.get();
628 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
629 return vertex_array_manager_.get();
631 virtual bool ProcessPendingQueries() OVERRIDE;
632 virtual bool HasMoreIdleWork() OVERRIDE;
633 virtual void PerformIdleWork() OVERRIDE;
635 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
637 virtual void SetResizeCallback(
638 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
640 virtual Logger* GetLogger() OVERRIDE;
642 virtual void BeginDecoding() OVERRIDE;
643 virtual void EndDecoding() OVERRIDE;
645 virtual ErrorState* GetErrorState() OVERRIDE;
646 virtual const ContextState* GetContextState() OVERRIDE { return &state_; }
648 virtual void SetShaderCacheCallback(
649 const ShaderCacheCallback& callback) OVERRIDE;
650 virtual void SetWaitSyncPointCallback(
651 const WaitSyncPointCallback& callback) OVERRIDE;
653 virtual AsyncPixelTransferManager*
654 GetAsyncPixelTransferManager() OVERRIDE;
655 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
656 virtual void SetAsyncPixelTransferManagerForTest(
657 AsyncPixelTransferManager* manager) OVERRIDE;
658 virtual void SetIgnoreCachedStateForTest(bool ignore) OVERRIDE;
659 void ProcessFinishedAsyncTransfers();
661 virtual bool GetServiceTextureId(uint32 client_texture_id,
662 uint32* service_texture_id) OVERRIDE;
664 virtual uint32 GetTextureUploadCount() OVERRIDE;
665 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
666 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
667 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
669 // Restores the current state to the user's settings.
670 void RestoreCurrentFramebufferBindings();
672 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
673 void ApplyDirtyState();
675 // These check the state of the currently bound framebuffer or the
676 // backbuffer if no framebuffer is bound.
677 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
678 // check with all attached and enabled color attachments.
679 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
680 bool BoundFramebufferHasDepthAttachment();
681 bool BoundFramebufferHasStencilAttachment();
683 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
685 // Overridden from FramebufferManager::TextureDetachObserver:
686 virtual void OnTextureRefDetachedFromFramebuffer(
687 TextureRef* texture) OVERRIDE;
689 // Overriden from ErrorStateClient.
690 virtual void OnOutOfMemoryError() OVERRIDE;
692 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
693 void EnsureRenderbufferBound();
695 // Helpers to facilitate calling into compatible extensions.
696 static void RenderbufferStorageMultisampleHelper(
697 const FeatureInfo* feature_info,
698 GLenum target,
699 GLsizei samples,
700 GLenum internal_format,
701 GLsizei width,
702 GLsizei height);
704 void BlitFramebufferHelper(GLint srcX0,
705 GLint srcY0,
706 GLint srcX1,
707 GLint srcY1,
708 GLint dstX0,
709 GLint dstY0,
710 GLint dstX1,
711 GLint dstY1,
712 GLbitfield mask,
713 GLenum filter);
715 private:
716 friend class ScopedFrameBufferBinder;
717 friend class ScopedResolvedFrameBufferBinder;
718 friend class BackFramebuffer;
720 // Initialize or re-initialize the shader translator.
721 bool InitializeShaderTranslator();
723 void UpdateCapabilities();
725 // Helpers for the glGen and glDelete functions.
726 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
727 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
728 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
729 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
730 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
731 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
732 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
733 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
734 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
735 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
736 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
737 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
739 // Helper for async upload token completion notification callback.
740 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
741 uint32 sync_data_shm_id,
742 uint32 sync_data_shm_offset);
746 // Workarounds
747 void OnFboChanged() const;
748 void OnUseFramebuffer() const;
750 // TODO(gman): Cache these pointers?
751 BufferManager* buffer_manager() {
752 return group_->buffer_manager();
755 RenderbufferManager* renderbuffer_manager() {
756 return group_->renderbuffer_manager();
759 FramebufferManager* framebuffer_manager() {
760 return group_->framebuffer_manager();
763 ProgramManager* program_manager() {
764 return group_->program_manager();
767 ShaderManager* shader_manager() {
768 return group_->shader_manager();
771 ShaderTranslatorCache* shader_translator_cache() {
772 return group_->shader_translator_cache();
775 const TextureManager* texture_manager() const {
776 return group_->texture_manager();
779 TextureManager* texture_manager() {
780 return group_->texture_manager();
783 MailboxManager* mailbox_manager() {
784 return group_->mailbox_manager();
787 ImageManager* image_manager() {
788 return group_->image_manager();
791 VertexArrayManager* vertex_array_manager() {
792 return vertex_array_manager_.get();
795 MemoryTracker* memory_tracker() {
796 return group_->memory_tracker();
799 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
800 MemoryTracker* tracker = memory_tracker();
801 if (tracker) {
802 return tracker->EnsureGPUMemoryAvailable(estimated_size);
804 return true;
807 bool IsOffscreenBufferMultisampled() const {
808 return offscreen_target_samples_ > 1;
811 // Creates a Texture for the given texture.
812 TextureRef* CreateTexture(
813 GLuint client_id, GLuint service_id) {
814 return texture_manager()->CreateTexture(client_id, service_id);
817 // Gets the texture info for the given texture. Returns NULL if none exists.
818 TextureRef* GetTexture(GLuint client_id) const {
819 return texture_manager()->GetTexture(client_id);
822 // Deletes the texture info for the given texture.
823 void RemoveTexture(GLuint client_id) {
824 texture_manager()->RemoveTexture(client_id);
827 // Get the size (in pixels) of the currently bound frame buffer (either FBO
828 // or regular back buffer).
829 gfx::Size GetBoundReadFrameBufferSize();
831 // Get the format of the currently bound frame buffer (either FBO or regular
832 // back buffer)
833 GLenum GetBoundReadFrameBufferTextureType();
834 GLenum GetBoundReadFrameBufferInternalFormat();
835 GLenum GetBoundDrawFrameBufferInternalFormat();
837 // Wrapper for CompressedTexImage2D commands.
838 error::Error DoCompressedTexImage2D(
839 GLenum target,
840 GLint level,
841 GLenum internal_format,
842 GLsizei width,
843 GLsizei height,
844 GLint border,
845 GLsizei image_size,
846 const void* data);
848 // Wrapper for CompressedTexSubImage2D.
849 void DoCompressedTexSubImage2D(
850 GLenum target,
851 GLint level,
852 GLint xoffset,
853 GLint yoffset,
854 GLsizei width,
855 GLsizei height,
856 GLenum format,
857 GLsizei imageSize,
858 const void * data);
860 // Wrapper for CopyTexImage2D.
861 void DoCopyTexImage2D(
862 GLenum target,
863 GLint level,
864 GLenum internal_format,
865 GLint x,
866 GLint y,
867 GLsizei width,
868 GLsizei height,
869 GLint border);
871 // Wrapper for SwapBuffers.
872 void DoSwapBuffers();
874 // Wrapper for CopyTexSubImage2D.
875 void DoCopyTexSubImage2D(
876 GLenum target,
877 GLint level,
878 GLint xoffset,
879 GLint yoffset,
880 GLint x,
881 GLint y,
882 GLsizei width,
883 GLsizei height);
885 // Validation for TexSubImage2D.
886 bool ValidateTexSubImage2D(
887 error::Error* error,
888 const char* function_name,
889 GLenum target,
890 GLint level,
891 GLint xoffset,
892 GLint yoffset,
893 GLsizei width,
894 GLsizei height,
895 GLenum format,
896 GLenum type,
897 const void * data);
899 // Wrapper for TexSubImage2D.
900 error::Error DoTexSubImage2D(
901 GLenum target,
902 GLint level,
903 GLint xoffset,
904 GLint yoffset,
905 GLsizei width,
906 GLsizei height,
907 GLenum format,
908 GLenum type,
909 const void * data);
911 // Extra validation for async tex(Sub)Image2D.
912 bool ValidateAsyncTransfer(
913 const char* function_name,
914 TextureRef* texture_ref,
915 GLenum target,
916 GLint level,
917 const void * data);
919 // Wrapper for TexImageIOSurface2DCHROMIUM.
920 void DoTexImageIOSurface2DCHROMIUM(
921 GLenum target,
922 GLsizei width,
923 GLsizei height,
924 GLuint io_surface_id,
925 GLuint plane);
927 void DoCopyTextureCHROMIUM(
928 GLenum target,
929 GLuint source_id,
930 GLuint target_id,
931 GLint level,
932 GLenum internal_format,
933 GLenum dest_type);
935 // Wrapper for TexStorage2DEXT.
936 void DoTexStorage2DEXT(
937 GLenum target,
938 GLint levels,
939 GLenum internal_format,
940 GLsizei width,
941 GLsizei height);
943 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
944 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
945 const GLbyte* key);
946 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
947 GLenum target, const GLbyte* data);
949 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
950 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
951 GLuint client_id);
953 void DoBindTexImage2DCHROMIUM(
954 GLenum target,
955 GLint image_id);
956 void DoReleaseTexImage2DCHROMIUM(
957 GLenum target,
958 GLint image_id);
960 void DoTraceEndCHROMIUM(void);
962 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
964 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
966 // Creates a Program for the given program.
967 Program* CreateProgram(
968 GLuint client_id, GLuint service_id) {
969 return program_manager()->CreateProgram(client_id, service_id);
972 // Gets the program info for the given program. Returns NULL if none exists.
973 Program* GetProgram(GLuint client_id) {
974 return program_manager()->GetProgram(client_id);
977 #if defined(NDEBUG)
978 void LogClientServiceMapping(
979 const char* /* function_name */,
980 GLuint /* client_id */,
981 GLuint /* service_id */) {
983 template<typename T>
984 void LogClientServiceForInfo(
985 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
987 #else
988 void LogClientServiceMapping(
989 const char* function_name, GLuint client_id, GLuint service_id) {
990 if (service_logging_) {
991 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
992 << ": client_id = " << client_id
993 << ", service_id = " << service_id;
996 template<typename T>
997 void LogClientServiceForInfo(
998 T* info, GLuint client_id, const char* function_name) {
999 if (info) {
1000 LogClientServiceMapping(function_name, client_id, info->service_id());
1003 #endif
1005 // Gets the program info for the given program. If it's not a program
1006 // generates a GL error. Returns NULL if not program.
1007 Program* GetProgramInfoNotShader(
1008 GLuint client_id, const char* function_name) {
1009 Program* program = GetProgram(client_id);
1010 if (!program) {
1011 if (GetShader(client_id)) {
1012 LOCAL_SET_GL_ERROR(
1013 GL_INVALID_OPERATION, function_name, "shader passed for program");
1014 } else {
1015 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1018 LogClientServiceForInfo(program, client_id, function_name);
1019 return program;
1023 // Creates a Shader for the given shader.
1024 Shader* CreateShader(
1025 GLuint client_id,
1026 GLuint service_id,
1027 GLenum shader_type) {
1028 return shader_manager()->CreateShader(
1029 client_id, service_id, shader_type);
1032 // Gets the shader info for the given shader. Returns NULL if none exists.
1033 Shader* GetShader(GLuint client_id) {
1034 return shader_manager()->GetShader(client_id);
1037 // Gets the shader info for the given shader. If it's not a shader generates a
1038 // GL error. Returns NULL if not shader.
1039 Shader* GetShaderInfoNotProgram(
1040 GLuint client_id, const char* function_name) {
1041 Shader* shader = GetShader(client_id);
1042 if (!shader) {
1043 if (GetProgram(client_id)) {
1044 LOCAL_SET_GL_ERROR(
1045 GL_INVALID_OPERATION, function_name, "program passed for shader");
1046 } else {
1047 LOCAL_SET_GL_ERROR(
1048 GL_INVALID_VALUE, function_name, "unknown shader");
1051 LogClientServiceForInfo(shader, client_id, function_name);
1052 return shader;
1055 // Creates a buffer info for the given buffer.
1056 void CreateBuffer(GLuint client_id, GLuint service_id) {
1057 return buffer_manager()->CreateBuffer(client_id, service_id);
1060 // Gets the buffer info for the given buffer.
1061 Buffer* GetBuffer(GLuint client_id) {
1062 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1063 return buffer;
1066 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1067 // on glDeleteBuffers so we can make sure the user does not try to render
1068 // with deleted buffers.
1069 void RemoveBuffer(GLuint client_id);
1071 // Creates a framebuffer info for the given framebuffer.
1072 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1073 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1076 // Gets the framebuffer info for the given framebuffer.
1077 Framebuffer* GetFramebuffer(GLuint client_id) {
1078 return framebuffer_manager()->GetFramebuffer(client_id);
1081 // Removes the framebuffer info for the given framebuffer.
1082 void RemoveFramebuffer(GLuint client_id) {
1083 framebuffer_manager()->RemoveFramebuffer(client_id);
1086 // Creates a renderbuffer info for the given renderbuffer.
1087 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1088 return renderbuffer_manager()->CreateRenderbuffer(
1089 client_id, service_id);
1092 // Gets the renderbuffer info for the given renderbuffer.
1093 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1094 return renderbuffer_manager()->GetRenderbuffer(client_id);
1097 // Removes the renderbuffer info for the given renderbuffer.
1098 void RemoveRenderbuffer(GLuint client_id) {
1099 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1102 // Gets the vertex attrib manager for the given vertex array.
1103 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1104 VertexAttribManager* info =
1105 vertex_array_manager()->GetVertexAttribManager(client_id);
1106 return info;
1109 // Removes the vertex attrib manager for the given vertex array.
1110 void RemoveVertexAttribManager(GLuint client_id) {
1111 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1114 // Creates a vertex attrib manager for the given vertex array.
1115 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1116 GLuint client_id,
1117 GLuint service_id,
1118 bool client_visible) {
1119 return vertex_array_manager()->CreateVertexAttribManager(
1120 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1123 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1124 void DoBindUniformLocationCHROMIUM(
1125 GLuint client_id, GLint location, const char* name);
1127 error::Error GetAttribLocationHelper(
1128 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1129 const std::string& name_str);
1131 error::Error GetUniformLocationHelper(
1132 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1133 const std::string& name_str);
1135 // Helper for glShaderSource.
1136 error::Error ShaderSourceHelper(
1137 GLuint client_id, const char* data, uint32 data_size);
1139 // Clear any textures used by the current program.
1140 bool ClearUnclearedTextures();
1142 // Clears any uncleared attachments attached to the given frame buffer.
1143 // Returns false if there was a generated GL error.
1144 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1146 // overridden from GLES2Decoder
1147 virtual bool ClearLevel(unsigned service_id,
1148 unsigned bind_target,
1149 unsigned target,
1150 int level,
1151 unsigned internal_format,
1152 unsigned format,
1153 unsigned type,
1154 int width,
1155 int height,
1156 bool is_texture_immutable) OVERRIDE;
1158 // Restore all GL state that affects clearing.
1159 void RestoreClearState();
1161 // Remembers the state of some capabilities.
1162 // Returns: true if glEnable/glDisable should actually be called.
1163 bool SetCapabilityState(GLenum cap, bool enabled);
1165 // Check that the currently bound framebuffers are valid.
1166 // Generates GL error if not.
1167 bool CheckBoundFramebuffersValid(const char* func_name);
1169 // Check if a framebuffer meets our requirements.
1170 bool CheckFramebufferValid(
1171 Framebuffer* framebuffer,
1172 GLenum target,
1173 const char* func_name);
1175 // Checks if the current program exists and is valid. If not generates the
1176 // appropriate GL error. Returns true if the current program is in a usable
1177 // state.
1178 bool CheckCurrentProgram(const char* function_name);
1180 // Checks if the current program exists and is valid and that location is not
1181 // -1. If the current program is not valid generates the appropriate GL
1182 // error. Returns true if the current program is in a usable state and
1183 // location is not -1.
1184 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1186 // Gets the type of a uniform for a location in the current program. Sets GL
1187 // errors if the current program is not valid. Returns true if the current
1188 // program is valid and the location exists. Adjusts count so it
1189 // does not overflow the uniform.
1190 bool PrepForSetUniformByLocation(GLint fake_location,
1191 const char* function_name,
1192 Program::UniformApiType api_type,
1193 GLint* real_location,
1194 GLenum* type,
1195 GLsizei* count);
1197 // Gets the service id for any simulated backbuffer fbo.
1198 GLuint GetBackbufferServiceId() const;
1200 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1201 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1203 // Helper for glGetVertexAttrib
1204 void GetVertexAttribHelper(
1205 const VertexAttrib* attrib, GLenum pname, GLint* param);
1207 // Wrapper for glCreateProgram
1208 bool CreateProgramHelper(GLuint client_id);
1210 // Wrapper for glCreateShader
1211 bool CreateShaderHelper(GLenum type, GLuint client_id);
1213 // Wrapper for glActiveTexture
1214 void DoActiveTexture(GLenum texture_unit);
1216 // Wrapper for glAttachShader
1217 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1219 // Wrapper for glBindBuffer since we need to track the current targets.
1220 void DoBindBuffer(GLenum target, GLuint buffer);
1222 // Wrapper for glBindFramebuffer since we need to track the current targets.
1223 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1225 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1226 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1228 // Wrapper for glBindTexture since we need to track the current targets.
1229 void DoBindTexture(GLenum target, GLuint texture);
1231 // Wrapper for glBindVertexArrayOES
1232 void DoBindVertexArrayOES(GLuint array);
1233 void EmulateVertexArrayState();
1235 // Wrapper for glBlitFramebufferCHROMIUM.
1236 void DoBlitFramebufferCHROMIUM(
1237 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1238 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1239 GLbitfield mask, GLenum filter);
1241 // Wrapper for glBufferSubData.
1242 void DoBufferSubData(
1243 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1245 // Wrapper for glCheckFramebufferStatus
1246 GLenum DoCheckFramebufferStatus(GLenum target);
1248 // Wrapper for glClear
1249 error::Error DoClear(GLbitfield mask);
1251 // Wrappers for various state.
1252 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1253 void DoSampleCoverage(GLclampf value, GLboolean invert);
1255 // Wrapper for glCompileShader.
1256 void DoCompileShader(GLuint shader);
1258 // Helper for DeleteSharedIdsCHROMIUM commands.
1259 void DoDeleteSharedIdsCHROMIUM(
1260 GLuint namespace_id, GLsizei n, const GLuint* ids);
1262 // Wrapper for glDetachShader
1263 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1265 // Wrapper for glDisable
1266 void DoDisable(GLenum cap);
1268 // Wrapper for glDisableVertexAttribArray.
1269 void DoDisableVertexAttribArray(GLuint index);
1271 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1272 // attachments.
1273 void DoDiscardFramebufferEXT(GLenum target,
1274 GLsizei numAttachments,
1275 const GLenum* attachments);
1277 // Wrapper for glEnable
1278 void DoEnable(GLenum cap);
1280 // Wrapper for glEnableVertexAttribArray.
1281 void DoEnableVertexAttribArray(GLuint index);
1283 // Wrapper for glFinish.
1284 void DoFinish();
1286 // Wrapper for glFlush.
1287 void DoFlush();
1289 // Wrapper for glFramebufferRenderbufffer.
1290 void DoFramebufferRenderbuffer(
1291 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1292 GLuint renderbuffer);
1294 // Wrapper for glFramebufferTexture2D.
1295 void DoFramebufferTexture2D(
1296 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1297 GLint level);
1299 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1300 void DoFramebufferTexture2DMultisample(
1301 GLenum target, GLenum attachment, GLenum textarget,
1302 GLuint texture, GLint level, GLsizei samples);
1304 // Common implementation for both DoFramebufferTexture2D wrappers.
1305 void DoFramebufferTexture2DCommon(const char* name,
1306 GLenum target, GLenum attachment, GLenum textarget,
1307 GLuint texture, GLint level, GLsizei samples);
1309 // Wrapper for glGenerateMipmap
1310 void DoGenerateMipmap(GLenum target);
1312 // Helper for GenSharedIdsCHROMIUM commands.
1313 void DoGenSharedIdsCHROMIUM(
1314 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1316 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1317 // to account for different pname values defined in different extension
1318 // variants.
1319 GLenum AdjustGetPname(GLenum pname);
1321 // Wrapper for DoGetBooleanv.
1322 void DoGetBooleanv(GLenum pname, GLboolean* params);
1324 // Wrapper for DoGetFloatv.
1325 void DoGetFloatv(GLenum pname, GLfloat* params);
1327 // Wrapper for glGetFramebufferAttachmentParameteriv.
1328 void DoGetFramebufferAttachmentParameteriv(
1329 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1331 // Wrapper for glGetIntegerv.
1332 void DoGetIntegerv(GLenum pname, GLint* params);
1334 // Gets the max value in a range in a buffer.
1335 GLuint DoGetMaxValueInBufferCHROMIUM(
1336 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1338 // Wrapper for glGetBufferParameteriv.
1339 void DoGetBufferParameteriv(
1340 GLenum target, GLenum pname, GLint* params);
1342 // Wrapper for glGetProgramiv.
1343 void DoGetProgramiv(
1344 GLuint program_id, GLenum pname, GLint* params);
1346 // Wrapper for glRenderbufferParameteriv.
1347 void DoGetRenderbufferParameteriv(
1348 GLenum target, GLenum pname, GLint* params);
1350 // Wrapper for glGetShaderiv
1351 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1353 // Wrappers for glGetTexParameter.
1354 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1355 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1356 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1358 // Wrappers for glGetVertexAttrib.
1359 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1360 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1362 // Wrappers for glIsXXX functions.
1363 bool DoIsEnabled(GLenum cap);
1364 bool DoIsBuffer(GLuint client_id);
1365 bool DoIsFramebuffer(GLuint client_id);
1366 bool DoIsProgram(GLuint client_id);
1367 bool DoIsRenderbuffer(GLuint client_id);
1368 bool DoIsShader(GLuint client_id);
1369 bool DoIsTexture(GLuint client_id);
1370 bool DoIsVertexArrayOES(GLuint client_id);
1372 // Wrapper for glLinkProgram
1373 void DoLinkProgram(GLuint program);
1375 // Helper for RegisterSharedIdsCHROMIUM.
1376 void DoRegisterSharedIdsCHROMIUM(
1377 GLuint namespace_id, GLsizei n, const GLuint* ids);
1379 // Wrapper for glRenderbufferStorage.
1380 void DoRenderbufferStorage(
1381 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1383 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1384 void DoRenderbufferStorageMultisampleCHROMIUM(
1385 GLenum target, GLsizei samples, GLenum internalformat,
1386 GLsizei width, GLsizei height);
1388 // Handler for glRenderbufferStorageMultisampleEXT
1389 // (multisampled_render_to_texture).
1390 void DoRenderbufferStorageMultisampleEXT(
1391 GLenum target, GLsizei samples, GLenum internalformat,
1392 GLsizei width, GLsizei height);
1394 // Common validation for multisample extensions.
1395 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1396 GLenum internalformat,
1397 GLsizei width,
1398 GLsizei height);
1400 // Verifies that the currently bound multisample renderbuffer is valid
1401 // Very slow! Only done on platforms with driver bugs that return invalid
1402 // buffers under memory pressure
1403 bool VerifyMultisampleRenderbufferIntegrity(
1404 GLuint renderbuffer, GLenum format);
1406 // Wrapper for glReleaseShaderCompiler.
1407 void DoReleaseShaderCompiler() { }
1409 // Wrappers for glTexParameter functions.
1410 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1411 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1412 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1413 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1415 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1416 // spec only these 2 functions can be used to set sampler uniforms.
1417 void DoUniform1i(GLint fake_location, GLint v0);
1418 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1419 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1420 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1421 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1423 // Wrappers for glUniformfv because some drivers don't correctly accept
1424 // bool uniforms.
1425 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1426 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1427 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1428 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1430 void DoUniformMatrix2fv(
1431 GLint fake_location, GLsizei count, GLboolean transpose,
1432 const GLfloat* value);
1433 void DoUniformMatrix3fv(
1434 GLint fake_location, GLsizei count, GLboolean transpose,
1435 const GLfloat* value);
1436 void DoUniformMatrix4fv(
1437 GLint fake_location, GLsizei count, GLboolean transpose,
1438 const GLfloat* value);
1440 bool SetVertexAttribValue(
1441 const char* function_name, GLuint index, const GLfloat* value);
1443 // Wrappers for glVertexAttrib??
1444 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1445 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1446 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1447 void DoVertexAttrib4f(
1448 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1449 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1450 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1451 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1452 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1454 // Wrapper for glViewport
1455 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1457 // Wrapper for glUseProgram
1458 void DoUseProgram(GLuint program);
1460 // Wrapper for glValidateProgram.
1461 void DoValidateProgram(GLuint program_client_id);
1463 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1464 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1465 void DoPopGroupMarkerEXT(void);
1467 // Gets the number of values that will be returned by glGetXXX. Returns
1468 // false if pname is unknown.
1469 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1471 // Checks if the current program and vertex attributes are valid for drawing.
1472 bool IsDrawValid(
1473 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
1475 // Returns true if successful, simulated will be true if attrib0 was
1476 // simulated.
1477 bool SimulateAttrib0(
1478 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1479 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1481 // If an image is bound to texture, this will call Will/DidUseTexImage
1482 // if needed.
1483 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1484 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1486 // Returns false if textures were replaced.
1487 bool PrepareTexturesForRender();
1488 void RestoreStateForTextures();
1490 // Returns true if GL_FIXED attribs were simulated.
1491 bool SimulateFixedAttribs(
1492 const char* function_name,
1493 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1494 void RestoreStateForSimulatedFixedAttribs();
1496 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1497 // cases (primcount is 0 for non-instanced).
1498 error::Error DoDrawArrays(
1499 const char* function_name,
1500 bool instanced, GLenum mode, GLint first, GLsizei count,
1501 GLsizei primcount);
1502 error::Error DoDrawElements(
1503 const char* function_name,
1504 bool instanced, GLenum mode, GLsizei count, GLenum type,
1505 int32 offset, GLsizei primcount);
1507 GLenum GetBindTargetForSamplerType(GLenum type) {
1508 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1509 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1510 switch (type) {
1511 case GL_SAMPLER_2D:
1512 return GL_TEXTURE_2D;
1513 case GL_SAMPLER_CUBE:
1514 return GL_TEXTURE_CUBE_MAP;
1515 case GL_SAMPLER_EXTERNAL_OES:
1516 return GL_TEXTURE_EXTERNAL_OES;
1517 case GL_SAMPLER_2D_RECT_ARB:
1518 return GL_TEXTURE_RECTANGLE_ARB;
1521 NOTREACHED();
1522 return 0;
1525 // Gets the framebuffer info for a particular target.
1526 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1527 Framebuffer* framebuffer = NULL;
1528 switch (target) {
1529 case GL_FRAMEBUFFER:
1530 case GL_DRAW_FRAMEBUFFER_EXT:
1531 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1532 break;
1533 case GL_READ_FRAMEBUFFER_EXT:
1534 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1535 break;
1536 default:
1537 NOTREACHED();
1538 break;
1540 return framebuffer;
1543 Renderbuffer* GetRenderbufferInfoForTarget(
1544 GLenum target) {
1545 Renderbuffer* renderbuffer = NULL;
1546 switch (target) {
1547 case GL_RENDERBUFFER:
1548 renderbuffer = state_.bound_renderbuffer.get();
1549 break;
1550 default:
1551 NOTREACHED();
1552 break;
1554 return renderbuffer;
1557 // Validates the program and location for a glGetUniform call and returns
1558 // a SizeResult setup to receive the result. Returns true if glGetUniform
1559 // should be called.
1560 bool GetUniformSetup(
1561 GLuint program, GLint fake_location,
1562 uint32 shm_id, uint32 shm_offset,
1563 error::Error* error, GLint* real_location, GLuint* service_id,
1564 void** result, GLenum* result_type);
1566 virtual bool WasContextLost() OVERRIDE;
1567 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
1568 virtual void LoseContext(uint32 reset_status) OVERRIDE;
1570 #if defined(OS_MACOSX)
1571 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1572 #endif
1574 bool ValidateCompressedTexDimensions(
1575 const char* function_name,
1576 GLint level, GLsizei width, GLsizei height, GLenum format);
1577 bool ValidateCompressedTexFuncData(
1578 const char* function_name,
1579 GLsizei width, GLsizei height, GLenum format, size_t size);
1580 bool ValidateCompressedTexSubDimensions(
1581 const char* function_name,
1582 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1583 GLsizei width, GLsizei height, GLenum format,
1584 Texture* texture);
1586 void RenderWarning(const char* filename, int line, const std::string& msg);
1587 void PerformanceWarning(
1588 const char* filename, int line, const std::string& msg);
1590 const FeatureInfo::FeatureFlags& features() const {
1591 return feature_info_->feature_flags();
1594 const FeatureInfo::Workarounds& workarounds() const {
1595 return feature_info_->workarounds();
1598 bool ShouldDeferDraws() {
1599 return !offscreen_target_frame_buffer_.get() &&
1600 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1601 surface_->DeferDraws();
1604 bool ShouldDeferReads() {
1605 return !offscreen_target_frame_buffer_.get() &&
1606 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1607 surface_->DeferDraws();
1610 error::Error WillAccessBoundFramebufferForDraw() {
1611 if (ShouldDeferDraws())
1612 return error::kDeferCommandUntilLater;
1613 if (!offscreen_target_frame_buffer_.get() &&
1614 !framebuffer_state_.bound_draw_framebuffer.get() &&
1615 !surface_->SetBackbufferAllocation(true))
1616 return error::kLostContext;
1617 return error::kNoError;
1620 error::Error WillAccessBoundFramebufferForRead() {
1621 if (ShouldDeferReads())
1622 return error::kDeferCommandUntilLater;
1623 if (!offscreen_target_frame_buffer_.get() &&
1624 !framebuffer_state_.bound_read_framebuffer.get() &&
1625 !surface_->SetBackbufferAllocation(true))
1626 return error::kLostContext;
1627 return error::kNoError;
1630 void ProcessPendingReadPixels();
1631 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1633 // Generate a member function prototype for each command in an automated and
1634 // typesafe way.
1635 #define GLES2_CMD_OP(name) \
1636 Error Handle ## name( \
1637 uint32 immediate_data_size, \
1638 const cmds::name& args); \
1640 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1642 #undef GLES2_CMD_OP
1644 // The GL context this decoder renders to on behalf of the client.
1645 scoped_refptr<gfx::GLSurface> surface_;
1646 scoped_refptr<gfx::GLContext> context_;
1648 // The ContextGroup for this decoder uses to track resources.
1649 scoped_refptr<ContextGroup> group_;
1651 DebugMarkerManager debug_marker_manager_;
1652 Logger logger_;
1654 // All the state for this context.
1655 ContextState state_;
1657 // Current width and height of the offscreen frame buffer.
1658 gfx::Size offscreen_size_;
1660 // Util to help with GL.
1661 GLES2Util util_;
1663 // unpack flip y as last set by glPixelStorei
1664 bool unpack_flip_y_;
1666 // unpack (un)premultiply alpha as last set by glPixelStorei
1667 bool unpack_premultiply_alpha_;
1668 bool unpack_unpremultiply_alpha_;
1670 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1671 GLuint attrib_0_buffer_id_;
1673 // The value currently in attrib_0.
1674 Vec4 attrib_0_value_;
1676 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1677 bool attrib_0_buffer_matches_value_;
1679 // The size of attrib 0.
1680 GLsizei attrib_0_size_;
1682 // The buffer used to simulate GL_FIXED attribs.
1683 GLuint fixed_attrib_buffer_id_;
1685 // The size of fiixed attrib buffer.
1686 GLsizei fixed_attrib_buffer_size_;
1688 // The offscreen frame buffer that the client renders to. With EGL, the
1689 // depth and stencil buffers are separate. With regular GL there is a single
1690 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1691 // offscreen_target_stencil_render_buffer_ is unused.
1692 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1693 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1694 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1695 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1696 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1697 GLenum offscreen_target_color_format_;
1698 GLenum offscreen_target_depth_format_;
1699 GLenum offscreen_target_stencil_format_;
1700 GLsizei offscreen_target_samples_;
1701 GLboolean offscreen_target_buffer_preserved_;
1703 // The copy that is saved when SwapBuffers is called.
1704 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1705 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1706 scoped_refptr<TextureRef>
1707 offscreen_saved_color_texture_info_;
1709 // The copy that is used as the destination for multi-sample resolves.
1710 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1711 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1712 GLenum offscreen_saved_color_format_;
1714 scoped_ptr<QueryManager> query_manager_;
1716 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1718 base::Callback<void(gfx::Size, float)> resize_callback_;
1720 WaitSyncPointCallback wait_sync_point_callback_;
1722 ShaderCacheCallback shader_cache_callback_;
1724 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1726 // The format of the back buffer_
1727 GLenum back_buffer_color_format_;
1728 bool back_buffer_has_depth_;
1729 bool back_buffer_has_stencil_;
1731 // Backbuffer attachments that are currently undefined.
1732 uint32 backbuffer_needs_clear_bits_;
1734 // The current decoder error communicates the decoder error through command
1735 // processing functions that do not return the error value. Should be set only
1736 // if not returning an error.
1737 error::Error current_decoder_error_;
1739 bool use_shader_translator_;
1740 scoped_refptr<ShaderTranslator> vertex_translator_;
1741 scoped_refptr<ShaderTranslator> fragment_translator_;
1743 DisallowedFeatures disallowed_features_;
1745 // Cached from ContextGroup
1746 const Validators* validators_;
1747 scoped_refptr<FeatureInfo> feature_info_;
1749 int frame_number_;
1751 bool has_robustness_extension_;
1752 GLenum reset_status_;
1753 bool reset_by_robustness_extension_;
1754 bool supports_post_sub_buffer_;
1756 // These flags are used to override the state of the shared feature_info_
1757 // member. Because the same FeatureInfo instance may be shared among many
1758 // contexts, the assumptions on the availablity of extensions in WebGL
1759 // contexts may be broken. These flags override the shared state to preserve
1760 // WebGL semantics.
1761 bool force_webgl_glsl_validation_;
1762 bool derivatives_explicitly_enabled_;
1763 bool frag_depth_explicitly_enabled_;
1764 bool draw_buffers_explicitly_enabled_;
1765 bool shader_texture_lod_explicitly_enabled_;
1767 bool compile_shader_always_succeeds_;
1769 // An optional behaviour to lose the context and group when OOM.
1770 bool lose_context_when_out_of_memory_;
1772 // Log extra info.
1773 bool service_logging_;
1775 #if defined(OS_MACOSX)
1776 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1777 TextureToIOSurfaceMap texture_to_io_surface_map_;
1778 #endif
1780 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1782 // Cached values of the currently assigned viewport dimensions.
1783 GLsizei viewport_max_width_;
1784 GLsizei viewport_max_height_;
1786 // Command buffer stats.
1787 base::TimeDelta total_processing_commands_time_;
1789 // States related to each manager.
1790 DecoderTextureState texture_state_;
1791 DecoderFramebufferState framebuffer_state_;
1793 scoped_ptr<GPUTracer> gpu_tracer_;
1794 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1795 int gpu_trace_level_;
1796 bool gpu_trace_commands_;
1798 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1800 // Used to validate multisample renderbuffers if needed
1801 GLuint validation_texture_;
1802 GLuint validation_fbo_multisample_;
1803 GLuint validation_fbo_;
1805 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1808 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1809 const char* function_name, ErrorState* error_state)
1810 : function_name_(function_name),
1811 error_state_(error_state) {
1812 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1815 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1816 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1819 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1820 TextureUnit& info = state->texture_units[0];
1821 GLuint last_id;
1822 scoped_refptr<TextureRef> texture_ref;
1823 switch (target) {
1824 case GL_TEXTURE_2D:
1825 texture_ref = info.bound_texture_2d;
1826 break;
1827 case GL_TEXTURE_CUBE_MAP:
1828 texture_ref = info.bound_texture_cube_map;
1829 break;
1830 case GL_TEXTURE_EXTERNAL_OES:
1831 texture_ref = info.bound_texture_external_oes;
1832 break;
1833 case GL_TEXTURE_RECTANGLE_ARB:
1834 texture_ref = info.bound_texture_rectangle_arb;
1835 break;
1836 default:
1837 NOTREACHED();
1838 break;
1840 if (texture_ref.get()) {
1841 last_id = texture_ref->service_id();
1842 } else {
1843 last_id = 0;
1846 glBindTexture(target, last_id);
1847 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1850 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1851 GLuint id,
1852 GLenum target)
1853 : state_(state),
1854 target_(target) {
1855 ScopedGLErrorSuppressor suppressor(
1856 "ScopedTextureBinder::ctor", state_->GetErrorState());
1858 // TODO(apatrick): Check if there are any other states that need to be reset
1859 // before binding a new texture.
1860 glActiveTexture(GL_TEXTURE0);
1861 glBindTexture(target, id);
1864 ScopedTextureBinder::~ScopedTextureBinder() {
1865 ScopedGLErrorSuppressor suppressor(
1866 "ScopedTextureBinder::dtor", state_->GetErrorState());
1867 RestoreCurrentTextureBindings(state_, target_);
1870 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1871 GLuint id)
1872 : state_(state) {
1873 ScopedGLErrorSuppressor suppressor(
1874 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1875 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1878 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1879 ScopedGLErrorSuppressor suppressor(
1880 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1881 state_->RestoreRenderbufferBindings();
1884 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1885 GLuint id)
1886 : decoder_(decoder) {
1887 ScopedGLErrorSuppressor suppressor(
1888 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
1889 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1890 decoder->OnFboChanged();
1893 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1894 ScopedGLErrorSuppressor suppressor(
1895 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
1896 decoder_->RestoreCurrentFramebufferBindings();
1899 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1900 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1901 : decoder_(decoder) {
1902 resolve_and_bind_ = (
1903 decoder_->offscreen_target_frame_buffer_.get() &&
1904 decoder_->IsOffscreenBufferMultisampled() &&
1905 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1906 enforce_internal_framebuffer));
1907 if (!resolve_and_bind_)
1908 return;
1910 ScopedGLErrorSuppressor suppressor(
1911 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
1912 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1913 decoder_->offscreen_target_frame_buffer_->id());
1914 GLuint targetid;
1915 if (internal) {
1916 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1917 decoder_->offscreen_resolved_frame_buffer_.reset(
1918 new BackFramebuffer(decoder_));
1919 decoder_->offscreen_resolved_frame_buffer_->Create();
1920 decoder_->offscreen_resolved_color_texture_.reset(
1921 new BackTexture(decoder->memory_tracker(), &decoder->state_));
1922 decoder_->offscreen_resolved_color_texture_->Create();
1924 DCHECK(decoder_->offscreen_saved_color_format_);
1925 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1926 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1927 false);
1928 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1929 decoder_->offscreen_resolved_color_texture_.get());
1930 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1931 GL_FRAMEBUFFER_COMPLETE) {
1932 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1933 << "because offscreen resolved FBO was incomplete.";
1934 return;
1937 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1938 } else {
1939 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1941 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1942 const int width = decoder_->offscreen_size_.width();
1943 const int height = decoder_->offscreen_size_.height();
1944 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
1945 decoder->BlitFramebufferHelper(0,
1947 width,
1948 height,
1951 width,
1952 height,
1953 GL_COLOR_BUFFER_BIT,
1954 GL_NEAREST);
1955 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1958 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1959 if (!resolve_and_bind_)
1960 return;
1962 ScopedGLErrorSuppressor suppressor(
1963 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
1964 decoder_->RestoreCurrentFramebufferBindings();
1965 if (decoder_->state_.enable_flags.scissor_test) {
1966 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
1970 BackTexture::BackTexture(
1971 MemoryTracker* memory_tracker,
1972 ContextState* state)
1973 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1974 state_(state),
1975 bytes_allocated_(0),
1976 id_(0) {
1979 BackTexture::~BackTexture() {
1980 // This does not destroy the render texture because that would require that
1981 // the associated GL context was current. Just check that it was explicitly
1982 // destroyed.
1983 DCHECK_EQ(id_, 0u);
1986 void BackTexture::Create() {
1987 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
1988 state_->GetErrorState());
1989 Destroy();
1990 glGenTextures(1, &id_);
1991 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
1992 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1993 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1994 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1995 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1997 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1998 // never called on an offscreen context, no data will ever be uploaded to the
1999 // saved offscreen color texture (it is deferred until to when SwapBuffers
2000 // is called). My idea is that some nvidia drivers might have a bug where
2001 // deleting a texture that has never been populated might cause a
2002 // crash.
2003 glTexImage2D(
2004 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2006 bytes_allocated_ = 16u * 16u * 4u;
2007 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2010 bool BackTexture::AllocateStorage(
2011 const gfx::Size& size, GLenum format, bool zero) {
2012 DCHECK_NE(id_, 0u);
2013 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2014 state_->GetErrorState());
2015 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2016 uint32 image_size = 0;
2017 GLES2Util::ComputeImageDataSizes(
2018 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
2019 NULL, NULL);
2021 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2022 return false;
2025 scoped_ptr<char[]> zero_data;
2026 if (zero) {
2027 zero_data.reset(new char[image_size]);
2028 memset(zero_data.get(), 0, image_size);
2031 glTexImage2D(GL_TEXTURE_2D,
2032 0, // mip level
2033 format,
2034 size.width(),
2035 size.height(),
2036 0, // border
2037 format,
2038 GL_UNSIGNED_BYTE,
2039 zero_data.get());
2041 size_ = size;
2043 bool success = glGetError() == GL_NO_ERROR;
2044 if (success) {
2045 memory_tracker_.TrackMemFree(bytes_allocated_);
2046 bytes_allocated_ = image_size;
2047 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2049 return success;
2052 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2053 DCHECK_NE(id_, 0u);
2054 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2055 state_->GetErrorState());
2056 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2057 glCopyTexImage2D(GL_TEXTURE_2D,
2058 0, // level
2059 format,
2060 0, 0,
2061 size.width(),
2062 size.height(),
2063 0); // border
2066 void BackTexture::Destroy() {
2067 if (id_ != 0) {
2068 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2069 state_->GetErrorState());
2070 glDeleteTextures(1, &id_);
2071 id_ = 0;
2073 memory_tracker_.TrackMemFree(bytes_allocated_);
2074 bytes_allocated_ = 0;
2077 void BackTexture::Invalidate() {
2078 id_ = 0;
2081 BackRenderbuffer::BackRenderbuffer(
2082 RenderbufferManager* renderbuffer_manager,
2083 MemoryTracker* memory_tracker,
2084 ContextState* state)
2085 : renderbuffer_manager_(renderbuffer_manager),
2086 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2087 state_(state),
2088 bytes_allocated_(0),
2089 id_(0) {
2092 BackRenderbuffer::~BackRenderbuffer() {
2093 // This does not destroy the render buffer because that would require that
2094 // the associated GL context was current. Just check that it was explicitly
2095 // destroyed.
2096 DCHECK_EQ(id_, 0u);
2099 void BackRenderbuffer::Create() {
2100 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2101 state_->GetErrorState());
2102 Destroy();
2103 glGenRenderbuffersEXT(1, &id_);
2106 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2107 const gfx::Size& size,
2108 GLenum format,
2109 GLsizei samples) {
2110 ScopedGLErrorSuppressor suppressor(
2111 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2112 ScopedRenderBufferBinder binder(state_, id_);
2114 uint32 estimated_size = 0;
2115 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2116 size.width(), size.height(), samples, format, &estimated_size)) {
2117 return false;
2120 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2121 return false;
2124 if (samples <= 1) {
2125 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2126 format,
2127 size.width(),
2128 size.height());
2129 } else {
2130 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2131 GL_RENDERBUFFER,
2132 samples,
2133 format,
2134 size.width(),
2135 size.height());
2137 bool success = glGetError() == GL_NO_ERROR;
2138 if (success) {
2139 // Mark the previously allocated bytes as free.
2140 memory_tracker_.TrackMemFree(bytes_allocated_);
2141 bytes_allocated_ = estimated_size;
2142 // Track the newly allocated bytes.
2143 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2145 return success;
2148 void BackRenderbuffer::Destroy() {
2149 if (id_ != 0) {
2150 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2151 state_->GetErrorState());
2152 glDeleteRenderbuffersEXT(1, &id_);
2153 id_ = 0;
2155 memory_tracker_.TrackMemFree(bytes_allocated_);
2156 bytes_allocated_ = 0;
2159 void BackRenderbuffer::Invalidate() {
2160 id_ = 0;
2163 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2164 : decoder_(decoder),
2165 id_(0) {
2168 BackFramebuffer::~BackFramebuffer() {
2169 // This does not destroy the frame buffer because that would require that
2170 // the associated GL context was current. Just check that it was explicitly
2171 // destroyed.
2172 DCHECK_EQ(id_, 0u);
2175 void BackFramebuffer::Create() {
2176 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2177 decoder_->GetErrorState());
2178 Destroy();
2179 glGenFramebuffersEXT(1, &id_);
2182 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2183 DCHECK_NE(id_, 0u);
2184 ScopedGLErrorSuppressor suppressor(
2185 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2186 ScopedFrameBufferBinder binder(decoder_, id_);
2187 GLuint attach_id = texture ? texture->id() : 0;
2188 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2189 GL_COLOR_ATTACHMENT0,
2190 GL_TEXTURE_2D,
2191 attach_id,
2195 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2196 BackRenderbuffer* render_buffer) {
2197 DCHECK_NE(id_, 0u);
2198 ScopedGLErrorSuppressor suppressor(
2199 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2200 ScopedFrameBufferBinder binder(decoder_, id_);
2201 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2202 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2203 target,
2204 GL_RENDERBUFFER,
2205 attach_id);
2208 void BackFramebuffer::Destroy() {
2209 if (id_ != 0) {
2210 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2211 decoder_->GetErrorState());
2212 glDeleteFramebuffersEXT(1, &id_);
2213 id_ = 0;
2217 void BackFramebuffer::Invalidate() {
2218 id_ = 0;
2221 GLenum BackFramebuffer::CheckStatus() {
2222 DCHECK_NE(id_, 0u);
2223 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2224 decoder_->GetErrorState());
2225 ScopedFrameBufferBinder binder(decoder_, id_);
2226 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2229 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2230 return new GLES2DecoderImpl(group);
2233 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2234 : GLES2Decoder(),
2235 group_(group),
2236 logger_(&debug_marker_manager_),
2237 state_(group_->feature_info(), this, &logger_),
2238 unpack_flip_y_(false),
2239 unpack_premultiply_alpha_(false),
2240 unpack_unpremultiply_alpha_(false),
2241 attrib_0_buffer_id_(0),
2242 attrib_0_buffer_matches_value_(true),
2243 attrib_0_size_(0),
2244 fixed_attrib_buffer_id_(0),
2245 fixed_attrib_buffer_size_(0),
2246 offscreen_target_color_format_(0),
2247 offscreen_target_depth_format_(0),
2248 offscreen_target_stencil_format_(0),
2249 offscreen_target_samples_(0),
2250 offscreen_target_buffer_preserved_(true),
2251 offscreen_saved_color_format_(0),
2252 back_buffer_color_format_(0),
2253 back_buffer_has_depth_(false),
2254 back_buffer_has_stencil_(false),
2255 backbuffer_needs_clear_bits_(0),
2256 current_decoder_error_(error::kNoError),
2257 use_shader_translator_(true),
2258 validators_(group_->feature_info()->validators()),
2259 feature_info_(group_->feature_info()),
2260 frame_number_(0),
2261 has_robustness_extension_(false),
2262 reset_status_(GL_NO_ERROR),
2263 reset_by_robustness_extension_(false),
2264 supports_post_sub_buffer_(false),
2265 force_webgl_glsl_validation_(false),
2266 derivatives_explicitly_enabled_(false),
2267 frag_depth_explicitly_enabled_(false),
2268 draw_buffers_explicitly_enabled_(false),
2269 shader_texture_lod_explicitly_enabled_(false),
2270 compile_shader_always_succeeds_(false),
2271 lose_context_when_out_of_memory_(false),
2272 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2273 switches::kEnableGPUServiceLoggingGPU)),
2274 viewport_max_width_(0),
2275 viewport_max_height_(0),
2276 texture_state_(group_->feature_info()
2277 ->workarounds()
2278 .texsubimage2d_faster_than_teximage2d),
2279 validation_texture_(0),
2280 validation_fbo_multisample_(0),
2281 validation_fbo_(0) {
2282 DCHECK(group);
2284 attrib_0_value_.v[0] = 0.0f;
2285 attrib_0_value_.v[1] = 0.0f;
2286 attrib_0_value_.v[2] = 0.0f;
2287 attrib_0_value_.v[3] = 1.0f;
2289 // The shader translator is used for WebGL even when running on EGL
2290 // because additional restrictions are needed (like only enabling
2291 // GL_OES_standard_derivatives on demand). It is used for the unit
2292 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2293 // the empty string to CompileShader and this is not a valid shader.
2294 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2295 CommandLine::ForCurrentProcess()->HasSwitch(
2296 switches::kDisableGLSLTranslator)) {
2297 use_shader_translator_ = false;
2301 GLES2DecoderImpl::~GLES2DecoderImpl() {
2304 bool GLES2DecoderImpl::Initialize(
2305 const scoped_refptr<gfx::GLSurface>& surface,
2306 const scoped_refptr<gfx::GLContext>& context,
2307 bool offscreen,
2308 const gfx::Size& size,
2309 const DisallowedFeatures& disallowed_features,
2310 const std::vector<int32>& attribs) {
2311 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2312 DCHECK(context->IsCurrent(surface.get()));
2313 DCHECK(!context_.get());
2315 set_initialized();
2316 gpu_tracer_ = GPUTracer::Create(this);
2317 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2318 // TODO(vmiura): Enable changing gpu_trace_level_ at runtime
2319 gpu_trace_level_ = 2;
2320 gpu_trace_commands_ = false;
2322 if (CommandLine::ForCurrentProcess()->HasSwitch(
2323 switches::kEnableGPUDebugging)) {
2324 set_debug(true);
2327 if (CommandLine::ForCurrentProcess()->HasSwitch(
2328 switches::kEnableGPUCommandLogging)) {
2329 set_log_commands(true);
2332 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2333 switches::kCompileShaderAlwaysSucceeds);
2336 // Take ownership of the context and surface. The surface can be replaced with
2337 // SetSurface.
2338 context_ = context;
2339 surface_ = surface;
2341 ContextCreationAttribHelper attrib_parser;
2342 if (!attrib_parser.Parse(attribs))
2343 return false;
2345 // Save the loseContextWhenOutOfMemory context creation attribute.
2346 lose_context_when_out_of_memory_ =
2347 attrib_parser.lose_context_when_out_of_memory_;
2349 // If the failIfMajorPerformanceCaveat context creation attribute was true
2350 // and we are using a software renderer, fail.
2351 if (attrib_parser.fail_if_major_perf_caveat_ &&
2352 feature_info_->feature_flags().is_swiftshader) {
2353 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2354 Destroy(true);
2355 return false;
2358 if (!group_->Initialize(this, disallowed_features)) {
2359 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2360 << "failed to initialize.";
2361 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2362 Destroy(true);
2363 return false;
2365 CHECK_GL_ERROR();
2367 disallowed_features_ = disallowed_features;
2369 state_.attrib_values.resize(group_->max_vertex_attribs());
2370 vertex_array_manager_.reset(new VertexArrayManager());
2372 GLuint default_vertex_attrib_service_id = 0;
2373 if (features().native_vertex_array_object) {
2374 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2375 glBindVertexArrayOES(default_vertex_attrib_service_id);
2378 state_.default_vertex_attrib_manager =
2379 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2381 state_.default_vertex_attrib_manager->Initialize(
2382 group_->max_vertex_attribs(),
2383 feature_info_->workarounds().init_vertex_attributes);
2385 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2386 DoBindVertexArrayOES(0);
2388 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2390 util_.set_num_compressed_texture_formats(
2391 validators_->compressed_texture_format.GetValues().size());
2393 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2394 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2395 // OpenGL ES 2.0 does not have this issue.
2396 glEnableVertexAttribArray(0);
2398 glGenBuffersARB(1, &attrib_0_buffer_id_);
2399 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2400 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2401 glBindBuffer(GL_ARRAY_BUFFER, 0);
2402 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2404 state_.texture_units.resize(group_->max_texture_units());
2405 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2406 glActiveTexture(GL_TEXTURE0 + tt);
2407 // We want the last bind to be 2D.
2408 TextureRef* ref;
2409 if (features().oes_egl_image_external) {
2410 ref = texture_manager()->GetDefaultTextureInfo(
2411 GL_TEXTURE_EXTERNAL_OES);
2412 state_.texture_units[tt].bound_texture_external_oes = ref;
2413 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2415 if (features().arb_texture_rectangle) {
2416 ref = texture_manager()->GetDefaultTextureInfo(
2417 GL_TEXTURE_RECTANGLE_ARB);
2418 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2419 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2421 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2422 state_.texture_units[tt].bound_texture_cube_map = ref;
2423 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2424 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2425 state_.texture_units[tt].bound_texture_2d = ref;
2426 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2428 glActiveTexture(GL_TEXTURE0);
2429 CHECK_GL_ERROR();
2431 if (offscreen) {
2432 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
2433 features().chromium_framebuffer_multisample) {
2434 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2435 // max_sample_count must be initialized to a sane value. If
2436 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2437 GLint max_sample_count = 1;
2438 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2439 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2440 max_sample_count);
2441 } else {
2442 offscreen_target_samples_ = 1;
2444 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
2446 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2447 const bool rgb8_supported =
2448 context_->HasExtension("GL_OES_rgb8_rgba8");
2449 // The only available default render buffer formats in GLES2 have very
2450 // little precision. Don't enable multisampling unless 8-bit render
2451 // buffer formats are available--instead fall back to 8-bit textures.
2452 if (rgb8_supported && offscreen_target_samples_ > 1) {
2453 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2454 GL_RGBA8 : GL_RGB8;
2455 } else {
2456 offscreen_target_samples_ = 1;
2457 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2458 GL_RGBA : GL_RGB;
2461 // ANGLE only supports packed depth/stencil formats, so use it if it is
2462 // available.
2463 const bool depth24_stencil8_supported =
2464 feature_info_->feature_flags().packed_depth24_stencil8;
2465 VLOG(1) << "GL_OES_packed_depth_stencil "
2466 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2467 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2468 depth24_stencil8_supported) {
2469 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2470 offscreen_target_stencil_format_ = 0;
2471 } else {
2472 // It may be the case that this depth/stencil combination is not
2473 // supported, but this will be checked later by CheckFramebufferStatus.
2474 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2475 GL_DEPTH_COMPONENT16 : 0;
2476 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2477 GL_STENCIL_INDEX8 : 0;
2479 } else {
2480 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2481 GL_RGBA : GL_RGB;
2483 // If depth is requested at all, use the packed depth stencil format if
2484 // it's available, as some desktop GL drivers don't support any non-packed
2485 // formats for depth attachments.
2486 const bool depth24_stencil8_supported =
2487 feature_info_->feature_flags().packed_depth24_stencil8;
2488 VLOG(1) << "GL_EXT_packed_depth_stencil "
2489 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2491 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2492 depth24_stencil8_supported) {
2493 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2494 offscreen_target_stencil_format_ = 0;
2495 } else {
2496 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2497 GL_DEPTH_COMPONENT : 0;
2498 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2499 GL_STENCIL_INDEX : 0;
2503 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2504 GL_RGBA : GL_RGB;
2506 // Create the target frame buffer. This is the one that the client renders
2507 // directly to.
2508 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2509 offscreen_target_frame_buffer_->Create();
2510 // Due to GLES2 format limitations, either the color texture (for
2511 // non-multisampling) or the color render buffer (for multisampling) will be
2512 // attached to the offscreen frame buffer. The render buffer has more
2513 // limited formats available to it, but the texture can't do multisampling.
2514 if (IsOffscreenBufferMultisampled()) {
2515 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2516 renderbuffer_manager(), memory_tracker(), &state_));
2517 offscreen_target_color_render_buffer_->Create();
2518 } else {
2519 offscreen_target_color_texture_.reset(new BackTexture(
2520 memory_tracker(), &state_));
2521 offscreen_target_color_texture_->Create();
2523 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2524 renderbuffer_manager(), memory_tracker(), &state_));
2525 offscreen_target_depth_render_buffer_->Create();
2526 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2527 renderbuffer_manager(), memory_tracker(), &state_));
2528 offscreen_target_stencil_render_buffer_->Create();
2530 // Create the saved offscreen texture. The target frame buffer is copied
2531 // here when SwapBuffers is called.
2532 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2533 offscreen_saved_frame_buffer_->Create();
2535 offscreen_saved_color_texture_.reset(new BackTexture(
2536 memory_tracker(), &state_));
2537 offscreen_saved_color_texture_->Create();
2539 // Allocate the render buffers at their initial size and check the status
2540 // of the frame buffers is okay.
2541 if (!ResizeOffscreenFrameBuffer(size)) {
2542 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2543 Destroy(true);
2544 return false;
2547 // Allocate the offscreen saved color texture.
2548 DCHECK(offscreen_saved_color_format_);
2549 offscreen_saved_color_texture_->AllocateStorage(
2550 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2552 offscreen_saved_frame_buffer_->AttachRenderTexture(
2553 offscreen_saved_color_texture_.get());
2554 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2555 GL_FRAMEBUFFER_COMPLETE) {
2556 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2557 Destroy(true);
2558 return false;
2561 // Bind to the new default frame buffer (the offscreen target frame buffer).
2562 // This should now be associated with ID zero.
2563 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2564 } else {
2565 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2566 // These are NOT if the back buffer has these proprorties. They are
2567 // if we want the command buffer to enforce them regardless of what
2568 // the real backbuffer is assuming the real back buffer gives us more than
2569 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2570 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2571 // can't do anything about that.
2573 GLint v = 0;
2574 glGetIntegerv(GL_ALPHA_BITS, &v);
2575 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2576 // user requested RGB then RGB. If the user did not specify a preference
2577 // than use whatever we were given. Same for DEPTH and STENCIL.
2578 back_buffer_color_format_ =
2579 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2580 glGetIntegerv(GL_DEPTH_BITS, &v);
2581 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2582 glGetIntegerv(GL_STENCIL_BITS, &v);
2583 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2586 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2587 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2588 // isn't well documented; it was discovered in the Khronos OpenGL ES
2589 // mailing list archives. It also implicitly enables the desktop GL
2590 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2591 // variable in fragment shaders.
2592 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2593 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2594 glEnable(GL_POINT_SPRITE);
2597 has_robustness_extension_ =
2598 context->HasExtension("GL_ARB_robustness") ||
2599 context->HasExtension("GL_EXT_robustness");
2601 if (!InitializeShaderTranslator()) {
2602 return false;
2605 state_.viewport_width = size.width();
2606 state_.viewport_height = size.height();
2608 GLint viewport_params[4] = { 0 };
2609 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2610 viewport_max_width_ = viewport_params[0];
2611 viewport_max_height_ = viewport_params[1];
2613 state_.scissor_width = state_.viewport_width;
2614 state_.scissor_height = state_.viewport_height;
2616 // Set all the default state because some GL drivers get it wrong.
2617 state_.InitCapabilities(NULL);
2618 state_.InitState(NULL);
2619 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2621 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2622 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2623 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2624 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2626 bool call_gl_clear = true;
2627 #if defined(OS_ANDROID)
2628 // Temporary workaround for Android WebView because this clear ignores the
2629 // clip and corrupts that external UI of the App. Not calling glClear is ok
2630 // because the system already clears the buffer before each draw. Proper
2631 // fix might be setting the scissor clip properly before initialize. See
2632 // crbug.com/259023 for details.
2633 call_gl_clear = surface_->GetHandle();
2634 #endif
2635 if (call_gl_clear) {
2636 // Clear the backbuffer.
2637 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2640 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2641 if (feature_info_->workarounds()
2642 .disable_post_sub_buffers_for_onscreen_surfaces &&
2643 !surface->IsOffscreen())
2644 supports_post_sub_buffer_ = false;
2646 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2647 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2650 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2651 context_->SetUnbindFboOnMakeCurrent();
2654 if (feature_info_->workarounds().release_image_after_use) {
2655 image_manager()->SetReleaseAfterUse();
2658 // Only compositor contexts are known to use only the subset of GL
2659 // that can be safely migrated between the iGPU and the dGPU. Mark
2660 // those contexts as safe to forcibly transition between the GPUs.
2661 // http://crbug.com/180876, http://crbug.com/227228
2662 if (!offscreen)
2663 context_->SetSafeToForceGpuSwitch();
2665 async_pixel_transfer_manager_.reset(
2666 AsyncPixelTransferManager::Create(context.get()));
2667 async_pixel_transfer_manager_->Initialize(texture_manager());
2669 framebuffer_manager()->AddObserver(this);
2671 return true;
2674 Capabilities GLES2DecoderImpl::GetCapabilities() {
2675 DCHECK(initialized());
2677 Capabilities caps;
2679 caps.fast_npot_mo8_textures =
2680 feature_info_->workarounds().enable_chromium_fast_npot_mo8_textures;
2681 caps.egl_image_external =
2682 feature_info_->feature_flags().oes_egl_image_external;
2683 caps.texture_format_bgra8888 =
2684 feature_info_->feature_flags().ext_texture_format_bgra8888;
2685 caps.texture_format_etc1 =
2686 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2687 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2688 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2689 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2690 caps.discard_framebuffer =
2691 feature_info_->feature_flags().ext_discard_framebuffer;
2692 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
2694 #if defined(OS_MACOSX)
2695 // This is unconditionally true on mac, no need to test for it at runtime.
2696 caps.iosurface = true;
2697 #endif
2699 caps.post_sub_buffer = supports_post_sub_buffer_;
2700 caps.map_image = !!image_manager();
2702 return caps;
2705 void GLES2DecoderImpl::UpdateCapabilities() {
2706 util_.set_num_compressed_texture_formats(
2707 validators_->compressed_texture_format.GetValues().size());
2708 util_.set_num_shader_binary_formats(
2709 validators_->shader_binary_format.GetValues().size());
2712 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2713 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2715 if (!use_shader_translator_) {
2716 return true;
2718 ShBuiltInResources resources;
2719 ShInitBuiltInResources(&resources);
2720 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2721 resources.MaxVertexUniformVectors =
2722 group_->max_vertex_uniform_vectors();
2723 resources.MaxVaryingVectors = group_->max_varying_vectors();
2724 resources.MaxVertexTextureImageUnits =
2725 group_->max_vertex_texture_image_units();
2726 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2727 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2728 resources.MaxFragmentUniformVectors =
2729 group_->max_fragment_uniform_vectors();
2730 resources.MaxDrawBuffers = group_->max_draw_buffers();
2731 resources.MaxExpressionComplexity = 256;
2732 resources.MaxCallStackDepth = 256;
2734 #if (ANGLE_SH_VERSION >= 110)
2735 GLint range[2] = { 0, 0 };
2736 GLint precision = 0;
2737 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2738 range, &precision);
2739 resources.FragmentPrecisionHigh =
2740 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2741 #endif
2743 if (force_webgl_glsl_validation_) {
2744 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2745 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2746 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2747 if (!draw_buffers_explicitly_enabled_)
2748 resources.MaxDrawBuffers = 1;
2749 #if (ANGLE_SH_VERSION >= 123)
2750 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
2751 #endif
2752 } else {
2753 resources.OES_standard_derivatives =
2754 features().oes_standard_derivatives ? 1 : 0;
2755 resources.ARB_texture_rectangle =
2756 features().arb_texture_rectangle ? 1 : 0;
2757 resources.OES_EGL_image_external =
2758 features().oes_egl_image_external ? 1 : 0;
2759 resources.EXT_draw_buffers =
2760 features().ext_draw_buffers ? 1 : 0;
2761 resources.EXT_frag_depth =
2762 features().ext_frag_depth ? 1 : 0;
2763 #if (ANGLE_SH_VERSION >= 123)
2764 resources.EXT_shader_texture_lod =
2765 features().ext_shader_texture_lod ? 1 : 0;
2766 #endif
2769 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2770 : SH_GLES2_SPEC;
2771 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2772 #if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2773 resources.HashFunction = &CityHashForAngle;
2774 #else
2775 resources.HashFunction = &CityHash64;
2776 #endif
2777 else
2778 resources.HashFunction = NULL;
2779 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2780 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2781 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2782 int driver_bug_workarounds = 0;
2783 if (workarounds().needs_glsl_built_in_function_emulation)
2784 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2785 if (workarounds().init_gl_position_in_vertex_shader)
2786 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2787 if (workarounds().unfold_short_circuit_as_ternary_operation)
2788 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2789 if (workarounds().init_varyings_without_static_use)
2790 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2791 if (workarounds().unroll_for_loop_with_sampler_array_index)
2792 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2794 vertex_translator_ = shader_translator_cache()->GetTranslator(
2795 SH_VERTEX_SHADER,
2796 shader_spec,
2797 &resources,
2798 implementation_type,
2799 static_cast<ShCompileOptions>(driver_bug_workarounds));
2800 if (!vertex_translator_.get()) {
2801 LOG(ERROR) << "Could not initialize vertex shader translator.";
2802 Destroy(true);
2803 return false;
2806 fragment_translator_ = shader_translator_cache()->GetTranslator(
2807 SH_FRAGMENT_SHADER,
2808 shader_spec,
2809 &resources,
2810 implementation_type,
2811 static_cast<ShCompileOptions>(driver_bug_workarounds));
2812 if (!fragment_translator_.get()) {
2813 LOG(ERROR) << "Could not initialize fragment shader translator.";
2814 Destroy(true);
2815 return false;
2817 return true;
2820 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2821 for (GLsizei ii = 0; ii < n; ++ii) {
2822 if (GetBuffer(client_ids[ii])) {
2823 return false;
2826 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2827 glGenBuffersARB(n, service_ids.get());
2828 for (GLsizei ii = 0; ii < n; ++ii) {
2829 CreateBuffer(client_ids[ii], service_ids[ii]);
2831 return true;
2834 bool GLES2DecoderImpl::GenFramebuffersHelper(
2835 GLsizei n, const GLuint* client_ids) {
2836 for (GLsizei ii = 0; ii < n; ++ii) {
2837 if (GetFramebuffer(client_ids[ii])) {
2838 return false;
2841 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2842 glGenFramebuffersEXT(n, service_ids.get());
2843 for (GLsizei ii = 0; ii < n; ++ii) {
2844 CreateFramebuffer(client_ids[ii], service_ids[ii]);
2846 return true;
2849 bool GLES2DecoderImpl::GenRenderbuffersHelper(
2850 GLsizei n, const GLuint* client_ids) {
2851 for (GLsizei ii = 0; ii < n; ++ii) {
2852 if (GetRenderbuffer(client_ids[ii])) {
2853 return false;
2856 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2857 glGenRenderbuffersEXT(n, service_ids.get());
2858 for (GLsizei ii = 0; ii < n; ++ii) {
2859 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
2861 return true;
2864 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2865 for (GLsizei ii = 0; ii < n; ++ii) {
2866 if (GetTexture(client_ids[ii])) {
2867 return false;
2870 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
2871 glGenTextures(n, service_ids.get());
2872 for (GLsizei ii = 0; ii < n; ++ii) {
2873 CreateTexture(client_ids[ii], service_ids[ii]);
2875 return true;
2878 void GLES2DecoderImpl::DeleteBuffersHelper(
2879 GLsizei n, const GLuint* client_ids) {
2880 for (GLsizei ii = 0; ii < n; ++ii) {
2881 Buffer* buffer = GetBuffer(client_ids[ii]);
2882 if (buffer && !buffer->IsDeleted()) {
2883 state_.vertex_attrib_manager->Unbind(buffer);
2884 if (state_.bound_array_buffer.get() == buffer) {
2885 state_.bound_array_buffer = NULL;
2887 RemoveBuffer(client_ids[ii]);
2892 void GLES2DecoderImpl::DeleteFramebuffersHelper(
2893 GLsizei n, const GLuint* client_ids) {
2894 bool supports_separate_framebuffer_binds =
2895 features().chromium_framebuffer_multisample;
2897 for (GLsizei ii = 0; ii < n; ++ii) {
2898 Framebuffer* framebuffer =
2899 GetFramebuffer(client_ids[ii]);
2900 if (framebuffer && !framebuffer->IsDeleted()) {
2901 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2902 framebuffer_state_.bound_draw_framebuffer = NULL;
2903 framebuffer_state_.clear_state_dirty = true;
2904 GLenum target = supports_separate_framebuffer_binds ?
2905 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2906 glBindFramebufferEXT(target, GetBackbufferServiceId());
2908 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2909 framebuffer_state_.bound_read_framebuffer = NULL;
2910 GLenum target = supports_separate_framebuffer_binds ?
2911 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2912 glBindFramebufferEXT(target, GetBackbufferServiceId());
2914 OnFboChanged();
2915 RemoveFramebuffer(client_ids[ii]);
2920 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2921 GLsizei n, const GLuint* client_ids) {
2922 bool supports_separate_framebuffer_binds =
2923 features().chromium_framebuffer_multisample;
2924 for (GLsizei ii = 0; ii < n; ++ii) {
2925 Renderbuffer* renderbuffer =
2926 GetRenderbuffer(client_ids[ii]);
2927 if (renderbuffer && !renderbuffer->IsDeleted()) {
2928 if (state_.bound_renderbuffer.get() == renderbuffer) {
2929 state_.bound_renderbuffer = NULL;
2931 // Unbind from current framebuffers.
2932 if (supports_separate_framebuffer_binds) {
2933 if (framebuffer_state_.bound_read_framebuffer.get()) {
2934 framebuffer_state_.bound_read_framebuffer
2935 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
2937 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2938 framebuffer_state_.bound_draw_framebuffer
2939 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
2941 } else {
2942 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2943 framebuffer_state_.bound_draw_framebuffer
2944 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
2947 framebuffer_state_.clear_state_dirty = true;
2948 RemoveRenderbuffer(client_ids[ii]);
2953 void GLES2DecoderImpl::DeleteTexturesHelper(
2954 GLsizei n, const GLuint* client_ids) {
2955 bool supports_separate_framebuffer_binds =
2956 features().chromium_framebuffer_multisample;
2957 for (GLsizei ii = 0; ii < n; ++ii) {
2958 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2959 if (texture_ref) {
2960 Texture* texture = texture_ref->texture();
2961 if (texture->IsAttachedToFramebuffer()) {
2962 framebuffer_state_.clear_state_dirty = true;
2964 // Unbind texture_ref from texture_ref units.
2965 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
2966 state_.texture_units[jj].Unbind(texture_ref);
2968 // Unbind from current framebuffers.
2969 if (supports_separate_framebuffer_binds) {
2970 if (framebuffer_state_.bound_read_framebuffer.get()) {
2971 framebuffer_state_.bound_read_framebuffer
2972 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
2974 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2975 framebuffer_state_.bound_draw_framebuffer
2976 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
2978 } else {
2979 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2980 framebuffer_state_.bound_draw_framebuffer
2981 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
2984 #if defined(OS_MACOSX)
2985 GLuint service_id = texture->service_id();
2986 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2987 ReleaseIOSurfaceForTexture(service_id);
2989 #endif
2990 RemoveTexture(client_ids[ii]);
2995 // } // anonymous namespace
2997 bool GLES2DecoderImpl::MakeCurrent() {
2998 if (!context_.get())
2999 return false;
3001 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
3002 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3004 // Some D3D drivers cannot recover from device lost in the GPU process
3005 // sandbox. Allow a new GPU process to launch.
3006 if (workarounds().exit_on_context_lost) {
3007 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
3008 << " a D3D device in the Chrome GPU process sandbox.";
3009 #if defined(OS_WIN)
3010 base::win::SetShouldCrashOnProcessDetach(false);
3011 #endif
3012 exit(0);
3015 return false;
3018 ProcessFinishedAsyncTransfers();
3020 // Rebind the FBO if it was unbound by the context.
3021 if (workarounds().unbind_fbo_on_context_switch)
3022 RestoreFramebufferBindings();
3024 framebuffer_state_.clear_state_dirty = true;
3026 return true;
3029 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3030 ProcessPendingReadPixels();
3031 if (engine() && query_manager_.get())
3032 query_manager_->ProcessPendingTransferQueries();
3034 // TODO(epenner): Is there a better place to do this?
3035 // This needs to occur before we execute any batch of commands
3036 // from the client, as the client may have recieved an async
3037 // completion while issuing those commands.
3038 // "DidFlushStart" would be ideal if we had such a callback.
3039 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3042 static void RebindCurrentFramebuffer(
3043 GLenum target,
3044 Framebuffer* framebuffer,
3045 GLuint back_buffer_service_id) {
3046 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3048 if (framebuffer_id == 0) {
3049 framebuffer_id = back_buffer_service_id;
3052 glBindFramebufferEXT(target, framebuffer_id);
3055 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3056 framebuffer_state_.clear_state_dirty = true;
3058 if (!features().chromium_framebuffer_multisample) {
3059 RebindCurrentFramebuffer(
3060 GL_FRAMEBUFFER,
3061 framebuffer_state_.bound_draw_framebuffer.get(),
3062 GetBackbufferServiceId());
3063 } else {
3064 RebindCurrentFramebuffer(
3065 GL_READ_FRAMEBUFFER_EXT,
3066 framebuffer_state_.bound_read_framebuffer.get(),
3067 GetBackbufferServiceId());
3068 RebindCurrentFramebuffer(
3069 GL_DRAW_FRAMEBUFFER_EXT,
3070 framebuffer_state_.bound_draw_framebuffer.get(),
3071 GetBackbufferServiceId());
3073 OnFboChanged();
3076 bool GLES2DecoderImpl::CheckFramebufferValid(
3077 Framebuffer* framebuffer,
3078 GLenum target, const char* func_name) {
3079 if (!framebuffer) {
3080 if (backbuffer_needs_clear_bits_) {
3081 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3082 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3083 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3084 glClearStencil(0);
3085 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
3086 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
3087 glClearDepth(1.0f);
3088 state_.SetDeviceDepthMask(GL_TRUE);
3089 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3090 bool reset_draw_buffer = false;
3091 if ((backbuffer_needs_clear_bits_ | GL_COLOR_BUFFER_BIT) != 0 &&
3092 group_->draw_buffer() == GL_NONE) {
3093 reset_draw_buffer = true;
3094 GLenum buf = GL_BACK;
3095 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3096 buf = GL_COLOR_ATTACHMENT0;
3097 glDrawBuffersARB(1, &buf);
3099 glClear(backbuffer_needs_clear_bits_);
3100 if (reset_draw_buffer) {
3101 GLenum buf = GL_NONE;
3102 glDrawBuffersARB(1, &buf);
3104 backbuffer_needs_clear_bits_ = 0;
3105 RestoreClearState();
3107 return true;
3110 if (framebuffer_manager()->IsComplete(framebuffer)) {
3111 return true;
3114 GLenum completeness = framebuffer->IsPossiblyComplete();
3115 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3116 LOCAL_SET_GL_ERROR(
3117 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3118 return false;
3121 // Are all the attachments cleared?
3122 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3123 texture_manager()->HaveUnclearedMips()) {
3124 if (!framebuffer->IsCleared()) {
3125 // Can we clear them?
3126 if (framebuffer->GetStatus(texture_manager(), target) !=
3127 GL_FRAMEBUFFER_COMPLETE) {
3128 LOCAL_SET_GL_ERROR(
3129 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3130 "framebuffer incomplete (clear)");
3131 return false;
3133 ClearUnclearedAttachments(target, framebuffer);
3137 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3138 if (framebuffer->GetStatus(texture_manager(), target) !=
3139 GL_FRAMEBUFFER_COMPLETE) {
3140 LOCAL_SET_GL_ERROR(
3141 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3142 "framebuffer incomplete (check)");
3143 return false;
3145 framebuffer_manager()->MarkAsComplete(framebuffer);
3148 // NOTE: At this point we don't know if the framebuffer is complete but
3149 // we DO know that everything that needs to be cleared has been cleared.
3150 return true;
3153 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3154 if (!features().chromium_framebuffer_multisample) {
3155 bool valid = CheckFramebufferValid(
3156 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3157 func_name);
3159 if (valid)
3160 OnUseFramebuffer();
3162 return valid;
3164 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3165 GL_DRAW_FRAMEBUFFER_EXT,
3166 func_name) &&
3167 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3168 GL_READ_FRAMEBUFFER_EXT,
3169 func_name);
3172 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3173 Framebuffer* framebuffer =
3174 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3175 if (framebuffer != NULL) {
3176 const Framebuffer::Attachment* attachment =
3177 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3178 if (attachment) {
3179 return gfx::Size(attachment->width(), attachment->height());
3181 return gfx::Size(0, 0);
3182 } else if (offscreen_target_frame_buffer_.get()) {
3183 return offscreen_size_;
3184 } else {
3185 return surface_->GetSize();
3189 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3190 Framebuffer* framebuffer =
3191 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3192 if (framebuffer != NULL) {
3193 return framebuffer->GetColorAttachmentTextureType();
3194 } else {
3195 return GL_UNSIGNED_BYTE;
3199 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3200 Framebuffer* framebuffer =
3201 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3202 if (framebuffer != NULL) {
3203 return framebuffer->GetColorAttachmentFormat();
3204 } else if (offscreen_target_frame_buffer_.get()) {
3205 return offscreen_target_color_format_;
3206 } else {
3207 return back_buffer_color_format_;
3211 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3212 Framebuffer* framebuffer =
3213 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3214 if (framebuffer != NULL) {
3215 return framebuffer->GetColorAttachmentFormat();
3216 } else if (offscreen_target_frame_buffer_.get()) {
3217 return offscreen_target_color_format_;
3218 } else {
3219 return back_buffer_color_format_;
3223 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3224 if (!offscreen_saved_color_texture_info_.get())
3225 return;
3226 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3227 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3228 texture_manager()->SetLevelInfo(
3229 offscreen_saved_color_texture_info_.get(),
3230 GL_TEXTURE_2D,
3231 0, // level
3232 GL_RGBA,
3233 offscreen_size_.width(),
3234 offscreen_size_.height(),
3235 1, // depth
3236 0, // border
3237 GL_RGBA,
3238 GL_UNSIGNED_BYTE,
3239 true);
3240 texture_manager()->SetParameteri(
3241 "UpdateParentTextureInfo",
3242 GetErrorState(),
3243 offscreen_saved_color_texture_info_.get(),
3244 GL_TEXTURE_MAG_FILTER,
3245 GL_NEAREST);
3246 texture_manager()->SetParameteri(
3247 "UpdateParentTextureInfo",
3248 GetErrorState(),
3249 offscreen_saved_color_texture_info_.get(),
3250 GL_TEXTURE_MIN_FILTER,
3251 GL_NEAREST);
3252 texture_manager()->SetParameteri(
3253 "UpdateParentTextureInfo",
3254 GetErrorState(),
3255 offscreen_saved_color_texture_info_.get(),
3256 GL_TEXTURE_WRAP_S,
3257 GL_CLAMP_TO_EDGE);
3258 texture_manager()->SetParameteri(
3259 "UpdateParentTextureInfo",
3260 GetErrorState(),
3261 offscreen_saved_color_texture_info_.get(),
3262 GL_TEXTURE_WRAP_T,
3263 GL_CLAMP_TO_EDGE);
3264 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3265 &state_, target);
3266 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3269 void GLES2DecoderImpl::SetResizeCallback(
3270 const base::Callback<void(gfx::Size, float)>& callback) {
3271 resize_callback_ = callback;
3274 Logger* GLES2DecoderImpl::GetLogger() {
3275 return &logger_;
3278 void GLES2DecoderImpl::BeginDecoding() {
3279 gpu_tracer_->BeginDecoding();
3280 gpu_trace_commands_ = gpu_tracer_->IsTracing();
3283 void GLES2DecoderImpl::EndDecoding() {
3284 gpu_tracer_->EndDecoding();
3287 ErrorState* GLES2DecoderImpl::GetErrorState() {
3288 return state_.GetErrorState();
3291 void GLES2DecoderImpl::SetShaderCacheCallback(
3292 const ShaderCacheCallback& callback) {
3293 shader_cache_callback_ = callback;
3296 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3297 const WaitSyncPointCallback& callback) {
3298 wait_sync_point_callback_ = callback;
3301 AsyncPixelTransferManager*
3302 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3303 return async_pixel_transfer_manager_.get();
3306 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3307 async_pixel_transfer_manager_.reset();
3310 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3311 AsyncPixelTransferManager* manager) {
3312 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3315 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3316 uint32* service_texture_id) {
3317 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3318 if (texture_ref) {
3319 *service_texture_id = texture_ref->service_id();
3320 return true;
3322 return false;
3325 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3326 return texture_state_.texture_upload_count +
3327 async_pixel_transfer_manager_->GetTextureUploadCount();
3330 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3331 return texture_state_.total_texture_upload_time +
3332 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3335 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3336 return total_processing_commands_time_;
3339 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3340 total_processing_commands_time_ += time;
3343 void GLES2DecoderImpl::Destroy(bool have_context) {
3344 if (!initialized())
3345 return;
3347 DCHECK(!have_context || context_->IsCurrent(NULL));
3349 // Unbind everything.
3350 state_.vertex_attrib_manager = NULL;
3351 state_.default_vertex_attrib_manager = NULL;
3352 state_.texture_units.clear();
3353 state_.bound_array_buffer = NULL;
3354 state_.current_queries.clear();
3355 framebuffer_state_.bound_read_framebuffer = NULL;
3356 framebuffer_state_.bound_draw_framebuffer = NULL;
3357 state_.bound_renderbuffer = NULL;
3359 if (offscreen_saved_color_texture_info_.get()) {
3360 DCHECK(offscreen_target_color_texture_);
3361 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3362 offscreen_saved_color_texture_->id());
3363 offscreen_saved_color_texture_->Invalidate();
3364 offscreen_saved_color_texture_info_ = NULL;
3366 if (have_context) {
3367 if (copy_texture_CHROMIUM_.get()) {
3368 copy_texture_CHROMIUM_->Destroy();
3369 copy_texture_CHROMIUM_.reset();
3372 if (state_.current_program.get()) {
3373 program_manager()->UnuseProgram(shader_manager(),
3374 state_.current_program.get());
3377 if (attrib_0_buffer_id_) {
3378 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3380 if (fixed_attrib_buffer_id_) {
3381 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3384 if (validation_texture_) {
3385 glDeleteTextures(1, &validation_texture_);
3386 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3387 glDeleteFramebuffersEXT(1, &validation_fbo_);
3390 if (offscreen_target_frame_buffer_.get())
3391 offscreen_target_frame_buffer_->Destroy();
3392 if (offscreen_target_color_texture_.get())
3393 offscreen_target_color_texture_->Destroy();
3394 if (offscreen_target_color_render_buffer_.get())
3395 offscreen_target_color_render_buffer_->Destroy();
3396 if (offscreen_target_depth_render_buffer_.get())
3397 offscreen_target_depth_render_buffer_->Destroy();
3398 if (offscreen_target_stencil_render_buffer_.get())
3399 offscreen_target_stencil_render_buffer_->Destroy();
3400 if (offscreen_saved_frame_buffer_.get())
3401 offscreen_saved_frame_buffer_->Destroy();
3402 if (offscreen_saved_color_texture_.get())
3403 offscreen_saved_color_texture_->Destroy();
3404 if (offscreen_resolved_frame_buffer_.get())
3405 offscreen_resolved_frame_buffer_->Destroy();
3406 if (offscreen_resolved_color_texture_.get())
3407 offscreen_resolved_color_texture_->Destroy();
3408 } else {
3409 if (offscreen_target_frame_buffer_.get())
3410 offscreen_target_frame_buffer_->Invalidate();
3411 if (offscreen_target_color_texture_.get())
3412 offscreen_target_color_texture_->Invalidate();
3413 if (offscreen_target_color_render_buffer_.get())
3414 offscreen_target_color_render_buffer_->Invalidate();
3415 if (offscreen_target_depth_render_buffer_.get())
3416 offscreen_target_depth_render_buffer_->Invalidate();
3417 if (offscreen_target_stencil_render_buffer_.get())
3418 offscreen_target_stencil_render_buffer_->Invalidate();
3419 if (offscreen_saved_frame_buffer_.get())
3420 offscreen_saved_frame_buffer_->Invalidate();
3421 if (offscreen_saved_color_texture_.get())
3422 offscreen_saved_color_texture_->Invalidate();
3423 if (offscreen_resolved_frame_buffer_.get())
3424 offscreen_resolved_frame_buffer_->Invalidate();
3425 if (offscreen_resolved_color_texture_.get())
3426 offscreen_resolved_color_texture_->Invalidate();
3429 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3430 // Otherwise, we can leak objects. http://crbug.com/258772.
3431 // state_.current_program must be reset before group_ is reset because
3432 // the later deletes the ProgramManager object that referred by
3433 // state_.current_program object.
3434 state_.current_program = NULL;
3436 copy_texture_CHROMIUM_.reset();
3438 if (query_manager_.get()) {
3439 query_manager_->Destroy(have_context);
3440 query_manager_.reset();
3443 if (vertex_array_manager_ .get()) {
3444 vertex_array_manager_->Destroy(have_context);
3445 vertex_array_manager_.reset();
3448 offscreen_target_frame_buffer_.reset();
3449 offscreen_target_color_texture_.reset();
3450 offscreen_target_color_render_buffer_.reset();
3451 offscreen_target_depth_render_buffer_.reset();
3452 offscreen_target_stencil_render_buffer_.reset();
3453 offscreen_saved_frame_buffer_.reset();
3454 offscreen_saved_color_texture_.reset();
3455 offscreen_resolved_frame_buffer_.reset();
3456 offscreen_resolved_color_texture_.reset();
3458 // Need to release these before releasing |group_| which may own the
3459 // ShaderTranslatorCache.
3460 fragment_translator_ = NULL;
3461 vertex_translator_ = NULL;
3463 // Should destroy the transfer manager before the texture manager held
3464 // by the context group.
3465 async_pixel_transfer_manager_.reset();
3467 if (group_.get()) {
3468 framebuffer_manager()->RemoveObserver(this);
3469 group_->Destroy(this, have_context);
3470 group_ = NULL;
3473 if (context_.get()) {
3474 context_->ReleaseCurrent(NULL);
3475 context_ = NULL;
3478 #if defined(OS_MACOSX)
3479 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3480 it != texture_to_io_surface_map_.end(); ++it) {
3481 CFRelease(it->second);
3483 texture_to_io_surface_map_.clear();
3484 #endif
3487 void GLES2DecoderImpl::SetSurface(
3488 const scoped_refptr<gfx::GLSurface>& surface) {
3489 DCHECK(context_->IsCurrent(NULL));
3490 DCHECK(surface_.get());
3491 surface_ = surface;
3492 RestoreCurrentFramebufferBindings();
3495 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3496 if (!offscreen_saved_color_texture_.get()) {
3497 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3498 return;
3500 if (!offscreen_saved_color_texture_info_.get()) {
3501 GLuint service_id = offscreen_saved_color_texture_->id();
3502 offscreen_saved_color_texture_info_ = TextureRef::Create(
3503 texture_manager(), 0, service_id);
3504 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3505 GL_TEXTURE_2D);
3506 UpdateParentTextureInfo();
3508 mailbox_manager()->ProduceTexture(
3509 GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
3512 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3513 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3514 if (!is_offscreen) {
3515 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3516 << " with an onscreen framebuffer.";
3517 return false;
3520 if (offscreen_size_ == size)
3521 return true;
3523 offscreen_size_ = size;
3524 int w = offscreen_size_.width();
3525 int h = offscreen_size_.height();
3526 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3527 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3528 << "to allocate storage due to excessive dimensions.";
3529 return false;
3532 // Reallocate the offscreen target buffers.
3533 DCHECK(offscreen_target_color_format_);
3534 if (IsOffscreenBufferMultisampled()) {
3535 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3536 feature_info_, offscreen_size_, offscreen_target_color_format_,
3537 offscreen_target_samples_)) {
3538 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3539 << "to allocate storage for offscreen target color buffer.";
3540 return false;
3542 } else {
3543 if (!offscreen_target_color_texture_->AllocateStorage(
3544 offscreen_size_, offscreen_target_color_format_, false)) {
3545 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3546 << "to allocate storage for offscreen target color texture.";
3547 return false;
3550 if (offscreen_target_depth_format_ &&
3551 !offscreen_target_depth_render_buffer_->AllocateStorage(
3552 feature_info_, offscreen_size_, offscreen_target_depth_format_,
3553 offscreen_target_samples_)) {
3554 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3555 << "to allocate storage for offscreen target depth buffer.";
3556 return false;
3558 if (offscreen_target_stencil_format_ &&
3559 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3560 feature_info_, offscreen_size_, offscreen_target_stencil_format_,
3561 offscreen_target_samples_)) {
3562 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3563 << "to allocate storage for offscreen target stencil buffer.";
3564 return false;
3567 // Attach the offscreen target buffers to the target frame buffer.
3568 if (IsOffscreenBufferMultisampled()) {
3569 offscreen_target_frame_buffer_->AttachRenderBuffer(
3570 GL_COLOR_ATTACHMENT0,
3571 offscreen_target_color_render_buffer_.get());
3572 } else {
3573 offscreen_target_frame_buffer_->AttachRenderTexture(
3574 offscreen_target_color_texture_.get());
3576 if (offscreen_target_depth_format_) {
3577 offscreen_target_frame_buffer_->AttachRenderBuffer(
3578 GL_DEPTH_ATTACHMENT,
3579 offscreen_target_depth_render_buffer_.get());
3581 const bool packed_depth_stencil =
3582 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3583 if (packed_depth_stencil) {
3584 offscreen_target_frame_buffer_->AttachRenderBuffer(
3585 GL_STENCIL_ATTACHMENT,
3586 offscreen_target_depth_render_buffer_.get());
3587 } else if (offscreen_target_stencil_format_) {
3588 offscreen_target_frame_buffer_->AttachRenderBuffer(
3589 GL_STENCIL_ATTACHMENT,
3590 offscreen_target_stencil_render_buffer_.get());
3593 if (offscreen_target_frame_buffer_->CheckStatus() !=
3594 GL_FRAMEBUFFER_COMPLETE) {
3595 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3596 << "because offscreen FBO was incomplete.";
3597 return false;
3600 // Clear the target frame buffer.
3602 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3603 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3604 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3605 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3606 glClearStencil(0);
3607 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
3608 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
3609 glClearDepth(0);
3610 state_.SetDeviceDepthMask(GL_TRUE);
3611 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3612 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3613 RestoreClearState();
3616 // Destroy the offscreen resolved framebuffers.
3617 if (offscreen_resolved_frame_buffer_.get())
3618 offscreen_resolved_frame_buffer_->Destroy();
3619 if (offscreen_resolved_color_texture_.get())
3620 offscreen_resolved_color_texture_->Destroy();
3621 offscreen_resolved_color_texture_.reset();
3622 offscreen_resolved_frame_buffer_.reset();
3624 return true;
3627 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3628 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3629 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3630 return error::kDeferCommandUntilLater;
3632 GLuint width = static_cast<GLuint>(c.width);
3633 GLuint height = static_cast<GLuint>(c.height);
3634 GLfloat scale_factor = c.scale_factor;
3635 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3637 width = std::max(1U, width);
3638 height = std::max(1U, height);
3640 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3641 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3642 // Make sure that we are done drawing to the back buffer before resizing.
3643 glFinish();
3644 #endif
3645 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3646 if (is_offscreen) {
3647 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3648 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3649 << "ResizeOffscreenFrameBuffer failed.";
3650 return error::kLostContext;
3654 if (!resize_callback_.is_null()) {
3655 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3656 DCHECK(context_->IsCurrent(surface_.get()));
3657 if (!context_->IsCurrent(surface_.get())) {
3658 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3659 << "current after resize callback.";
3660 return error::kLostContext;
3664 return error::kNoError;
3667 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3668 if (command_id > kStartPoint && command_id < kNumCommands) {
3669 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3671 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3674 // Decode command with its arguments, and call the corresponding GL function.
3675 // Note: args is a pointer to the command buffer. As such, it could be changed
3676 // by a (malicious) client at any time, so if validation has to happen, it
3677 // should operate on a copy of them.
3678 error::Error GLES2DecoderImpl::DoCommand(
3679 unsigned int command,
3680 unsigned int arg_count,
3681 const void* cmd_data) {
3682 error::Error result = error::kNoError;
3683 if (log_commands()) {
3684 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3685 // VLOG(1), no luck.
3686 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
3687 << GetCommandName(command);
3689 unsigned int command_index = command - kStartPoint - 1;
3690 if (command_index < arraysize(g_command_info)) {
3691 const CommandInfo& info = g_command_info[command_index];
3692 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3693 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3694 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3695 bool doing_gpu_trace = false;
3696 if (gpu_trace_commands_) {
3697 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3698 doing_gpu_trace = true;
3699 gpu_tracer_->Begin(GetCommandName(command), kTraceDecoder);
3703 uint32 immediate_data_size =
3704 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3705 switch (command) {
3706 #define GLES2_CMD_OP(name) \
3707 case cmds::name::kCmdId: \
3708 result = Handle ## name( \
3709 immediate_data_size, \
3710 *static_cast<const gles2::cmds::name*>(cmd_data)); \
3711 break; \
3713 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3714 #undef GLES2_CMD_OP
3717 if (doing_gpu_trace)
3718 gpu_tracer_->End(kTraceDecoder);
3720 if (debug()) {
3721 GLenum error;
3722 while ((error = glGetError()) != GL_NO_ERROR) {
3723 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
3724 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3725 << GetCommandName(command);
3726 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
3729 } else {
3730 result = error::kInvalidArguments;
3732 } else {
3733 result = DoCommonCommand(command, arg_count, cmd_data);
3735 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3736 result = current_decoder_error_;
3737 current_decoder_error_ = error::kNoError;
3739 return result;
3742 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3743 buffer_manager()->RemoveBuffer(client_id);
3746 bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3747 if (GetProgram(client_id)) {
3748 return false;
3750 GLuint service_id = glCreateProgram();
3751 if (service_id != 0) {
3752 CreateProgram(client_id, service_id);
3754 return true;
3757 bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3758 if (GetShader(client_id)) {
3759 return false;
3761 GLuint service_id = glCreateShader(type);
3762 if (service_id != 0) {
3763 CreateShader(client_id, service_id, type);
3765 return true;
3768 void GLES2DecoderImpl::DoFinish() {
3769 glFinish();
3770 ProcessPendingReadPixels();
3771 ProcessPendingQueries();
3774 void GLES2DecoderImpl::DoFlush() {
3775 glFlush();
3776 ProcessPendingQueries();
3779 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3780 GLuint texture_index = texture_unit - GL_TEXTURE0;
3781 if (texture_index >= state_.texture_units.size()) {
3782 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3783 "glActiveTexture", texture_unit, "texture_unit");
3784 return;
3786 state_.active_texture_unit = texture_index;
3787 glActiveTexture(texture_unit);
3790 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
3791 Buffer* buffer = NULL;
3792 GLuint service_id = 0;
3793 if (client_id != 0) {
3794 buffer = GetBuffer(client_id);
3795 if (!buffer) {
3796 if (!group_->bind_generates_resource()) {
3797 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
3798 "glBindBuffer",
3799 "id not generated by glGenBuffers");
3800 return;
3803 // It's a new id so make a buffer buffer for it.
3804 glGenBuffersARB(1, &service_id);
3805 CreateBuffer(client_id, service_id);
3806 buffer = GetBuffer(client_id);
3807 IdAllocatorInterface* id_allocator =
3808 group_->GetIdAllocator(id_namespaces::kBuffers);
3809 id_allocator->MarkAsUsed(client_id);
3812 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3813 if (buffer) {
3814 if (!buffer_manager()->SetTarget(buffer, target)) {
3815 LOCAL_SET_GL_ERROR(
3816 GL_INVALID_OPERATION,
3817 "glBindBuffer", "buffer bound to more than 1 target");
3818 return;
3820 service_id = buffer->service_id();
3822 switch (target) {
3823 case GL_ARRAY_BUFFER:
3824 state_.bound_array_buffer = buffer;
3825 break;
3826 case GL_ELEMENT_ARRAY_BUFFER:
3827 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
3828 break;
3829 default:
3830 NOTREACHED(); // Validation should prevent us getting here.
3831 break;
3833 glBindBuffer(target, service_id);
3836 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3837 bool all_draw_buffers) {
3838 Framebuffer* framebuffer =
3839 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3840 if (!all_draw_buffers || !framebuffer) {
3841 return (GLES2Util::GetChannelsForFormat(
3842 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3844 return framebuffer->HasAlphaMRT();
3847 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
3848 Framebuffer* framebuffer =
3849 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3850 if (framebuffer) {
3851 return framebuffer->HasDepthAttachment();
3853 if (offscreen_target_frame_buffer_.get()) {
3854 return offscreen_target_depth_format_ != 0;
3856 return back_buffer_has_depth_;
3859 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
3860 Framebuffer* framebuffer =
3861 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3862 if (framebuffer) {
3863 return framebuffer->HasStencilAttachment();
3865 if (offscreen_target_frame_buffer_.get()) {
3866 return offscreen_target_stencil_format_ != 0 ||
3867 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3869 return back_buffer_has_stencil_;
3872 void GLES2DecoderImpl::ApplyDirtyState() {
3873 if (framebuffer_state_.clear_state_dirty) {
3874 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
3875 state_.SetDeviceColorMask(state_.color_mask_red,
3876 state_.color_mask_green,
3877 state_.color_mask_blue,
3878 state_.color_mask_alpha && have_alpha);
3880 bool have_depth = BoundFramebufferHasDepthAttachment();
3881 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
3883 bool have_stencil = BoundFramebufferHasStencilAttachment();
3884 state_.SetDeviceStencilMaskSeparate(
3885 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3886 state_.SetDeviceStencilMaskSeparate(
3887 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3889 state_.SetDeviceCapabilityState(
3890 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3891 state_.SetDeviceCapabilityState(
3892 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3893 framebuffer_state_.clear_state_dirty = false;
3897 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
3898 return (offscreen_target_frame_buffer_.get())
3899 ? offscreen_target_frame_buffer_->id()
3900 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
3903 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
3904 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3905 "context", logger_.GetLogPrefix());
3906 // Restore the Framebuffer first because of bugs in Intel drivers.
3907 // Intel drivers incorrectly clip the viewport settings to
3908 // the size of the current framebuffer object.
3909 RestoreFramebufferBindings();
3910 state_.RestoreState(prev_state);
3913 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
3914 GLuint service_id =
3915 framebuffer_state_.bound_draw_framebuffer.get()
3916 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3917 : GetBackbufferServiceId();
3918 if (!features().chromium_framebuffer_multisample) {
3919 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3920 } else {
3921 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
3922 service_id = framebuffer_state_.bound_read_framebuffer.get()
3923 ? framebuffer_state_.bound_read_framebuffer->service_id()
3924 : GetBackbufferServiceId();
3925 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3927 OnFboChanged();
3930 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
3931 state_.RestoreRenderbufferBindings();
3934 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
3935 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3936 if (texture) {
3937 GLenum target = texture->target();
3938 glBindTexture(target, service_id);
3939 glTexParameteri(
3940 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
3941 glTexParameteri(
3942 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
3943 glTexParameteri(
3944 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
3945 glTexParameteri(
3946 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
3947 RestoreTextureUnitBindings(state_.active_texture_unit);
3951 void GLES2DecoderImpl::ClearAllAttributes() const {
3952 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
3953 // other VAOs.
3954 if (feature_info_->feature_flags().native_vertex_array_object)
3955 glBindVertexArrayOES(0);
3957 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
3958 if (i != 0) // Never disable attribute 0
3959 glDisableVertexAttribArray(i);
3960 if(features().angle_instanced_arrays)
3961 glVertexAttribDivisorANGLE(i, 0);
3965 void GLES2DecoderImpl::RestoreAllAttributes() const {
3966 state_.RestoreVertexAttribs();
3969 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
3970 state_.SetIgnoreCachedStateForTest(ignore);
3973 void GLES2DecoderImpl::OnFboChanged() const {
3974 if (workarounds().restore_scissor_on_fbo_change)
3975 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3978 // Called after the FBO is checked for completeness.
3979 void GLES2DecoderImpl::OnUseFramebuffer() const {
3980 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3981 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
3982 // The driver forgets the correct scissor when modifying the FBO binding.
3983 glScissor(state_.scissor_x,
3984 state_.scissor_y,
3985 state_.scissor_width,
3986 state_.scissor_height);
3988 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3989 // it's unclear how this bug works.
3990 glFlush();
3994 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3995 Framebuffer* framebuffer = NULL;
3996 GLuint service_id = 0;
3997 if (client_id != 0) {
3998 framebuffer = GetFramebuffer(client_id);
3999 if (!framebuffer) {
4000 if (!group_->bind_generates_resource()) {
4001 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4002 "glBindFramebuffer",
4003 "id not generated by glGenFramebuffers");
4004 return;
4007 // It's a new id so make a framebuffer framebuffer for it.
4008 glGenFramebuffersEXT(1, &service_id);
4009 CreateFramebuffer(client_id, service_id);
4010 framebuffer = GetFramebuffer(client_id);
4011 IdAllocatorInterface* id_allocator =
4012 group_->GetIdAllocator(id_namespaces::kFramebuffers);
4013 id_allocator->MarkAsUsed(client_id);
4014 } else {
4015 service_id = framebuffer->service_id();
4017 framebuffer->MarkAsValid();
4019 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4021 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4022 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4025 // vmiura: This looks like dup code
4026 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4027 framebuffer_state_.bound_read_framebuffer = framebuffer;
4030 framebuffer_state_.clear_state_dirty = true;
4032 // If we are rendering to the backbuffer get the FBO id for any simulated
4033 // backbuffer.
4034 if (framebuffer == NULL) {
4035 service_id = GetBackbufferServiceId();
4038 glBindFramebufferEXT(target, service_id);
4039 OnFboChanged();
4042 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4043 Renderbuffer* renderbuffer = NULL;
4044 GLuint service_id = 0;
4045 if (client_id != 0) {
4046 renderbuffer = GetRenderbuffer(client_id);
4047 if (!renderbuffer) {
4048 if (!group_->bind_generates_resource()) {
4049 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4050 "glBindRenderbuffer",
4051 "id not generated by glGenRenderbuffers");
4052 return;
4055 // It's a new id so make a renderbuffer for it.
4056 glGenRenderbuffersEXT(1, &service_id);
4057 CreateRenderbuffer(client_id, service_id);
4058 renderbuffer = GetRenderbuffer(client_id);
4059 IdAllocatorInterface* id_allocator =
4060 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
4061 id_allocator->MarkAsUsed(client_id);
4062 } else {
4063 service_id = renderbuffer->service_id();
4065 renderbuffer->MarkAsValid();
4067 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4068 state_.bound_renderbuffer = renderbuffer;
4069 state_.bound_renderbuffer_valid = true;
4070 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4073 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4074 TextureRef* texture_ref = NULL;
4075 GLuint service_id = 0;
4076 if (client_id != 0) {
4077 texture_ref = GetTexture(client_id);
4078 if (!texture_ref) {
4079 if (!group_->bind_generates_resource()) {
4080 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4081 "glBindTexture",
4082 "id not generated by glGenTextures");
4083 return;
4086 // It's a new id so make a texture texture for it.
4087 glGenTextures(1, &service_id);
4088 DCHECK_NE(0u, service_id);
4089 CreateTexture(client_id, service_id);
4090 texture_ref = GetTexture(client_id);
4091 IdAllocatorInterface* id_allocator =
4092 group_->GetIdAllocator(id_namespaces::kTextures);
4093 id_allocator->MarkAsUsed(client_id);
4095 } else {
4096 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4099 // Check the texture exists
4100 if (texture_ref) {
4101 Texture* texture = texture_ref->texture();
4102 // Check that we are not trying to bind it to a different target.
4103 if (texture->target() != 0 && texture->target() != target) {
4104 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4105 "glBindTexture",
4106 "texture bound to more than 1 target.");
4107 return;
4109 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4110 if (texture->target() == 0) {
4111 texture_manager()->SetTarget(texture_ref, target);
4113 glBindTexture(target, texture->service_id());
4114 } else {
4115 glBindTexture(target, 0);
4118 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4119 unit.bind_target = target;
4120 switch (target) {
4121 case GL_TEXTURE_2D:
4122 unit.bound_texture_2d = texture_ref;
4123 break;
4124 case GL_TEXTURE_CUBE_MAP:
4125 unit.bound_texture_cube_map = texture_ref;
4126 break;
4127 case GL_TEXTURE_EXTERNAL_OES:
4128 unit.bound_texture_external_oes = texture_ref;
4129 break;
4130 case GL_TEXTURE_RECTANGLE_ARB:
4131 unit.bound_texture_rectangle_arb = texture_ref;
4132 break;
4133 default:
4134 NOTREACHED(); // Validation should prevent us getting here.
4135 break;
4139 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4140 if (state_.vertex_attrib_manager->Enable(index, false)) {
4141 if (index != 0 ||
4142 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4143 glDisableVertexAttribArray(index);
4145 } else {
4146 LOCAL_SET_GL_ERROR(
4147 GL_INVALID_VALUE,
4148 "glDisableVertexAttribArray", "index out of range");
4152 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4153 GLsizei numAttachments,
4154 const GLenum* attachments) {
4155 Framebuffer* framebuffer =
4156 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4158 // Validates the attachments. If one of them fails
4159 // the whole command fails.
4160 for (GLsizei i = 0; i < numAttachments; ++i) {
4161 if ((framebuffer &&
4162 !validators_->attachment.IsValid(attachments[i])) ||
4163 (!framebuffer &&
4164 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4165 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4166 "glDiscardFramebufferEXT", attachments[i], "attachments");
4167 return;
4171 // Marks each one of them as not cleared
4172 for (GLsizei i = 0; i < numAttachments; ++i) {
4173 if (framebuffer) {
4174 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4175 texture_manager(),
4176 attachments[i],
4177 false);
4178 } else {
4179 switch (attachments[i]) {
4180 case GL_COLOR_EXT:
4181 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4182 break;
4183 case GL_DEPTH_EXT:
4184 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4185 case GL_STENCIL_EXT:
4186 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4187 break;
4188 default:
4189 NOTREACHED();
4190 break;
4195 // If the default framebuffer is bound but we are still rendering to an
4196 // FBO, translate attachment names that refer to default framebuffer
4197 // channels to corresponding framebuffer attachments.
4198 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4199 for (GLsizei i = 0; i < numAttachments; ++i) {
4200 GLenum attachment = attachments[i];
4201 if (!framebuffer && GetBackbufferServiceId()) {
4202 switch (attachment) {
4203 case GL_COLOR_EXT:
4204 attachment = GL_COLOR_ATTACHMENT0;
4205 break;
4206 case GL_DEPTH_EXT:
4207 attachment = GL_DEPTH_ATTACHMENT;
4208 break;
4209 case GL_STENCIL_EXT:
4210 attachment = GL_STENCIL_ATTACHMENT;
4211 break;
4212 default:
4213 NOTREACHED();
4214 return;
4217 translated_attachments[i] = attachment;
4220 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
4223 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4224 if (state_.vertex_attrib_manager->Enable(index, true)) {
4225 glEnableVertexAttribArray(index);
4226 } else {
4227 LOCAL_SET_GL_ERROR(
4228 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4232 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4233 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4234 &state_, target);
4235 if (!texture_ref ||
4236 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4237 LOCAL_SET_GL_ERROR(
4238 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4239 return;
4242 if (target == GL_TEXTURE_CUBE_MAP) {
4243 for (int i = 0; i < 6; ++i) {
4244 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4245 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4246 LOCAL_SET_GL_ERROR(
4247 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4248 return;
4251 } else {
4252 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4253 LOCAL_SET_GL_ERROR(
4254 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4255 return;
4259 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4260 // Workaround for Mac driver bug. In the large scheme of things setting
4261 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4262 // hit so there's probably no need to make this conditional. The bug appears
4263 // to be that if the filtering mode is set to something that doesn't require
4264 // mipmaps for rendering, or is never set to something other than the default,
4265 // then glGenerateMipmap misbehaves.
4266 if (workarounds().set_texture_filter_before_generating_mipmap) {
4267 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4269 glGenerateMipmapEXT(target);
4270 if (workarounds().set_texture_filter_before_generating_mipmap) {
4271 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4272 texture_ref->texture()->min_filter());
4274 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4275 if (error == GL_NO_ERROR) {
4276 texture_manager()->MarkMipmapsGenerated(texture_ref);
4280 bool GLES2DecoderImpl::GetHelper(
4281 GLenum pname, GLint* params, GLsizei* num_written) {
4282 DCHECK(num_written);
4283 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4284 switch (pname) {
4285 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4286 *num_written = 1;
4287 // Return the GL implementation's preferred format and (see below type)
4288 // if we have the GL extension that exposes this. This allows the GPU
4289 // client to use the implementation's preferred format for glReadPixels
4290 // for optimisation.
4292 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4293 // case when requested on integer/floating point buffers but which is
4294 // acceptable on GLES2 and with the GL_OES_read_format extension.
4296 // Therefore if an error occurs we swallow the error and use the
4297 // internal implementation.
4298 if (params) {
4299 if (context_->HasExtension("GL_OES_read_format")) {
4300 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4301 GetErrorState());
4302 glGetIntegerv(pname, params);
4303 if (glGetError() == GL_NO_ERROR)
4304 return true;
4306 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4307 GetBoundReadFrameBufferInternalFormat());
4309 return true;
4310 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4311 *num_written = 1;
4312 if (params) {
4313 if (context_->HasExtension("GL_OES_read_format")) {
4314 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4315 GetErrorState());
4316 glGetIntegerv(pname, params);
4317 if (glGetError() == GL_NO_ERROR)
4318 return true;
4320 *params = GLES2Util::GetPreferredGLReadPixelsType(
4321 GetBoundReadFrameBufferInternalFormat(),
4322 GetBoundReadFrameBufferTextureType());
4324 return true;
4325 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4326 *num_written = 1;
4327 if (params) {
4328 *params = group_->max_fragment_uniform_vectors();
4330 return true;
4331 case GL_MAX_VARYING_VECTORS:
4332 *num_written = 1;
4333 if (params) {
4334 *params = group_->max_varying_vectors();
4336 return true;
4337 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4338 *num_written = 1;
4339 if (params) {
4340 *params = group_->max_vertex_uniform_vectors();
4342 return true;
4345 switch (pname) {
4346 case GL_MAX_VIEWPORT_DIMS:
4347 if (offscreen_target_frame_buffer_.get()) {
4348 *num_written = 2;
4349 if (params) {
4350 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4351 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4353 return true;
4355 return false;
4356 case GL_MAX_SAMPLES:
4357 *num_written = 1;
4358 if (params) {
4359 params[0] = renderbuffer_manager()->max_samples();
4361 return true;
4362 case GL_MAX_RENDERBUFFER_SIZE:
4363 *num_written = 1;
4364 if (params) {
4365 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4367 return true;
4368 case GL_MAX_TEXTURE_SIZE:
4369 *num_written = 1;
4370 if (params) {
4371 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4373 return true;
4374 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4375 *num_written = 1;
4376 if (params) {
4377 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4379 return true;
4380 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4381 *num_written = 1;
4382 if (params) {
4383 params[0] = group_->max_color_attachments();
4385 return true;
4386 case GL_MAX_DRAW_BUFFERS_ARB:
4387 *num_written = 1;
4388 if (params) {
4389 params[0] = group_->max_draw_buffers();
4391 return true;
4392 case GL_ALPHA_BITS:
4393 *num_written = 1;
4394 if (params) {
4395 GLint v = 0;
4396 glGetIntegerv(GL_ALPHA_BITS, &v);
4397 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4399 return true;
4400 case GL_DEPTH_BITS:
4401 *num_written = 1;
4402 if (params) {
4403 GLint v = 0;
4404 glGetIntegerv(GL_DEPTH_BITS, &v);
4405 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4407 return true;
4408 case GL_STENCIL_BITS:
4409 *num_written = 1;
4410 if (params) {
4411 GLint v = 0;
4412 glGetIntegerv(GL_STENCIL_BITS, &v);
4413 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4415 return true;
4416 case GL_COMPRESSED_TEXTURE_FORMATS:
4417 *num_written = validators_->compressed_texture_format.GetValues().size();
4418 if (params) {
4419 for (GLint ii = 0; ii < *num_written; ++ii) {
4420 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4423 return true;
4424 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4425 *num_written = 1;
4426 if (params) {
4427 *params = validators_->compressed_texture_format.GetValues().size();
4429 return true;
4430 case GL_NUM_SHADER_BINARY_FORMATS:
4431 *num_written = 1;
4432 if (params) {
4433 *params = validators_->shader_binary_format.GetValues().size();
4435 return true;
4436 case GL_SHADER_BINARY_FORMATS:
4437 *num_written = validators_->shader_binary_format.GetValues().size();
4438 if (params) {
4439 for (GLint ii = 0; ii < *num_written; ++ii) {
4440 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4443 return true;
4444 case GL_SHADER_COMPILER:
4445 *num_written = 1;
4446 if (params) {
4447 *params = GL_TRUE;
4449 return true;
4450 case GL_ARRAY_BUFFER_BINDING:
4451 *num_written = 1;
4452 if (params) {
4453 if (state_.bound_array_buffer.get()) {
4454 GLuint client_id = 0;
4455 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4456 &client_id);
4457 *params = client_id;
4458 } else {
4459 *params = 0;
4462 return true;
4463 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4464 *num_written = 1;
4465 if (params) {
4466 if (state_.vertex_attrib_manager->element_array_buffer()) {
4467 GLuint client_id = 0;
4468 buffer_manager()->GetClientId(
4469 state_.vertex_attrib_manager->element_array_buffer()->
4470 service_id(), &client_id);
4471 *params = client_id;
4472 } else {
4473 *params = 0;
4476 return true;
4477 case GL_FRAMEBUFFER_BINDING:
4478 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4479 *num_written = 1;
4480 if (params) {
4481 Framebuffer* framebuffer =
4482 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4483 if (framebuffer) {
4484 GLuint client_id = 0;
4485 framebuffer_manager()->GetClientId(
4486 framebuffer->service_id(), &client_id);
4487 *params = client_id;
4488 } else {
4489 *params = 0;
4492 return true;
4493 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4494 *num_written = 1;
4495 if (params) {
4496 Framebuffer* framebuffer =
4497 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4498 if (framebuffer) {
4499 GLuint client_id = 0;
4500 framebuffer_manager()->GetClientId(
4501 framebuffer->service_id(), &client_id);
4502 *params = client_id;
4503 } else {
4504 *params = 0;
4507 return true;
4508 case GL_RENDERBUFFER_BINDING:
4509 *num_written = 1;
4510 if (params) {
4511 Renderbuffer* renderbuffer =
4512 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4513 if (renderbuffer) {
4514 *params = renderbuffer->client_id();
4515 } else {
4516 *params = 0;
4519 return true;
4520 case GL_CURRENT_PROGRAM:
4521 *num_written = 1;
4522 if (params) {
4523 if (state_.current_program.get()) {
4524 GLuint client_id = 0;
4525 program_manager()->GetClientId(
4526 state_.current_program->service_id(), &client_id);
4527 *params = client_id;
4528 } else {
4529 *params = 0;
4532 return true;
4533 case GL_VERTEX_ARRAY_BINDING_OES:
4534 *num_written = 1;
4535 if (params) {
4536 if (state_.vertex_attrib_manager.get() !=
4537 state_.default_vertex_attrib_manager.get()) {
4538 GLuint client_id = 0;
4539 vertex_array_manager_->GetClientId(
4540 state_.vertex_attrib_manager->service_id(), &client_id);
4541 *params = client_id;
4542 } else {
4543 *params = 0;
4546 return true;
4547 case GL_TEXTURE_BINDING_2D:
4548 *num_written = 1;
4549 if (params) {
4550 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4551 if (unit.bound_texture_2d.get()) {
4552 *params = unit.bound_texture_2d->client_id();
4553 } else {
4554 *params = 0;
4557 return true;
4558 case GL_TEXTURE_BINDING_CUBE_MAP:
4559 *num_written = 1;
4560 if (params) {
4561 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4562 if (unit.bound_texture_cube_map.get()) {
4563 *params = unit.bound_texture_cube_map->client_id();
4564 } else {
4565 *params = 0;
4568 return true;
4569 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4570 *num_written = 1;
4571 if (params) {
4572 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4573 if (unit.bound_texture_external_oes.get()) {
4574 *params = unit.bound_texture_external_oes->client_id();
4575 } else {
4576 *params = 0;
4579 return true;
4580 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4581 *num_written = 1;
4582 if (params) {
4583 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4584 if (unit.bound_texture_rectangle_arb.get()) {
4585 *params = unit.bound_texture_rectangle_arb->client_id();
4586 } else {
4587 *params = 0;
4590 return true;
4591 case GL_UNPACK_FLIP_Y_CHROMIUM:
4592 *num_written = 1;
4593 if (params) {
4594 params[0] = unpack_flip_y_;
4596 return true;
4597 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4598 *num_written = 1;
4599 if (params) {
4600 params[0] = unpack_premultiply_alpha_;
4602 return true;
4603 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4604 *num_written = 1;
4605 if (params) {
4606 params[0] = unpack_unpremultiply_alpha_;
4608 return true;
4609 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
4610 *num_written = 1;
4611 if (params) {
4612 params[0] = group_->bind_generates_resource() ? 1 : 0;
4614 return true;
4615 default:
4616 if (pname >= GL_DRAW_BUFFER0_ARB &&
4617 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4618 *num_written = 1;
4619 if (params) {
4620 Framebuffer* framebuffer =
4621 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4622 if (framebuffer) {
4623 params[0] = framebuffer->GetDrawBuffer(pname);
4624 } else { // backbuffer
4625 if (pname == GL_DRAW_BUFFER0_ARB)
4626 params[0] = group_->draw_buffer();
4627 else
4628 params[0] = GL_NONE;
4631 return true;
4633 *num_written = util_.GLGetNumValuesReturned(pname);
4634 return false;
4638 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4639 GLenum pname, GLsizei* num_values) {
4640 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4641 return true;
4643 return GetHelper(pname, NULL, num_values);
4646 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4647 if (GL_MAX_SAMPLES == pname &&
4648 features().use_img_for_multisampled_render_to_texture) {
4649 return GL_MAX_SAMPLES_IMG;
4651 return pname;
4654 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4655 DCHECK(params);
4656 GLsizei num_written = 0;
4657 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4658 scoped_ptr<GLint[]> values(new GLint[num_written]);
4659 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4660 GetHelper(pname, values.get(), &num_written);
4662 for (GLsizei ii = 0; ii < num_written; ++ii) {
4663 params[ii] = static_cast<GLboolean>(values[ii]);
4665 } else {
4666 pname = AdjustGetPname(pname);
4667 glGetBooleanv(pname, params);
4671 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4672 DCHECK(params);
4673 GLsizei num_written = 0;
4674 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4675 if (GetHelper(pname, NULL, &num_written)) {
4676 scoped_ptr<GLint[]> values(new GLint[num_written]);
4677 GetHelper(pname, values.get(), &num_written);
4678 for (GLsizei ii = 0; ii < num_written; ++ii) {
4679 params[ii] = static_cast<GLfloat>(values[ii]);
4681 } else {
4682 pname = AdjustGetPname(pname);
4683 glGetFloatv(pname, params);
4688 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4689 DCHECK(params);
4690 GLsizei num_written;
4691 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4692 !GetHelper(pname, params, &num_written)) {
4693 pname = AdjustGetPname(pname);
4694 glGetIntegerv(pname, params);
4698 void GLES2DecoderImpl::DoGetProgramiv(
4699 GLuint program_id, GLenum pname, GLint* params) {
4700 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4701 if (!program) {
4702 return;
4704 program->GetProgramiv(pname, params);
4707 void GLES2DecoderImpl::DoGetBufferParameteriv(
4708 GLenum target, GLenum pname, GLint* params) {
4709 // Just delegate it. Some validation is actually done before this.
4710 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4711 &state_, target, pname, params);
4714 void GLES2DecoderImpl::DoBindAttribLocation(
4715 GLuint program_id, GLuint index, const char* name) {
4716 if (!StringIsValidForGLES(name)) {
4717 LOCAL_SET_GL_ERROR(
4718 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
4719 return;
4721 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4722 LOCAL_SET_GL_ERROR(
4723 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
4724 return;
4726 if (index >= group_->max_vertex_attribs()) {
4727 LOCAL_SET_GL_ERROR(
4728 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
4729 return;
4731 Program* program = GetProgramInfoNotShader(
4732 program_id, "glBindAttribLocation");
4733 if (!program) {
4734 return;
4736 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4737 glBindAttribLocation(program->service_id(), index, name);
4740 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4741 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
4742 GLuint program = static_cast<GLuint>(c.program);
4743 GLuint index = static_cast<GLuint>(c.index);
4744 Bucket* bucket = GetBucket(c.name_bucket_id);
4745 if (!bucket || bucket->size() == 0) {
4746 return error::kInvalidArguments;
4748 std::string name_str;
4749 if (!bucket->GetAsString(&name_str)) {
4750 return error::kInvalidArguments;
4752 DoBindAttribLocation(program, index, name_str.c_str());
4753 return error::kNoError;
4756 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4757 GLuint program_id, GLint location, const char* name) {
4758 if (!StringIsValidForGLES(name)) {
4759 LOCAL_SET_GL_ERROR(
4760 GL_INVALID_VALUE,
4761 "glBindUniformLocationCHROMIUM", "Invalid character");
4762 return;
4764 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4765 LOCAL_SET_GL_ERROR(
4766 GL_INVALID_OPERATION,
4767 "glBindUniformLocationCHROMIUM", "reserved prefix");
4768 return;
4770 if (location < 0 || static_cast<uint32>(location) >=
4771 (group_->max_fragment_uniform_vectors() +
4772 group_->max_vertex_uniform_vectors()) * 4) {
4773 LOCAL_SET_GL_ERROR(
4774 GL_INVALID_VALUE,
4775 "glBindUniformLocationCHROMIUM", "location out of range");
4776 return;
4778 Program* program = GetProgramInfoNotShader(
4779 program_id, "glBindUniformLocationCHROMIUM");
4780 if (!program) {
4781 return;
4783 if (!program->SetUniformLocationBinding(name, location)) {
4784 LOCAL_SET_GL_ERROR(
4785 GL_INVALID_VALUE,
4786 "glBindUniformLocationCHROMIUM", "location out of range");
4790 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4791 uint32 immediate_data_size,
4792 const cmds::BindUniformLocationCHROMIUMBucket& c) {
4793 GLuint program = static_cast<GLuint>(c.program);
4794 GLint location = static_cast<GLint>(c.location);
4795 Bucket* bucket = GetBucket(c.name_bucket_id);
4796 if (!bucket || bucket->size() == 0) {
4797 return error::kInvalidArguments;
4799 std::string name_str;
4800 if (!bucket->GetAsString(&name_str)) {
4801 return error::kInvalidArguments;
4803 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4804 return error::kNoError;
4807 error::Error GLES2DecoderImpl::HandleDeleteShader(
4808 uint32 immediate_data_size, const cmds::DeleteShader& c) {
4809 GLuint client_id = c.shader;
4810 if (client_id) {
4811 Shader* shader = GetShader(client_id);
4812 if (shader) {
4813 if (!shader->IsDeleted()) {
4814 glDeleteShader(shader->service_id());
4815 shader_manager()->MarkAsDeleted(shader);
4817 } else {
4818 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
4821 return error::kNoError;
4824 error::Error GLES2DecoderImpl::HandleDeleteProgram(
4825 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
4826 GLuint client_id = c.program;
4827 if (client_id) {
4828 Program* program = GetProgram(client_id);
4829 if (program) {
4830 if (!program->IsDeleted()) {
4831 program_manager()->MarkAsDeleted(shader_manager(), program);
4833 } else {
4834 LOCAL_SET_GL_ERROR(
4835 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
4838 return error::kNoError;
4841 void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4842 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4843 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4844 for (GLsizei ii = 0; ii < n; ++ii) {
4845 id_allocator->FreeID(ids[ii]);
4849 error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4850 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
4851 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4852 GLsizei n = static_cast<GLsizei>(c.n);
4853 uint32 data_size;
4854 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4855 return error::kOutOfBounds;
4857 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4858 c.ids_shm_id, c.ids_shm_offset, data_size);
4859 if (n < 0) {
4860 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
4861 return error::kNoError;
4863 if (ids == NULL) {
4864 return error::kOutOfBounds;
4866 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4867 return error::kNoError;
4870 void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4871 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4872 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4873 if (id_offset == 0) {
4874 for (GLsizei ii = 0; ii < n; ++ii) {
4875 ids[ii] = id_allocator->AllocateID();
4877 } else {
4878 for (GLsizei ii = 0; ii < n; ++ii) {
4879 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4880 id_offset = ids[ii] + 1;
4885 error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4886 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
4887 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4888 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4889 GLsizei n = static_cast<GLsizei>(c.n);
4890 uint32 data_size;
4891 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4892 return error::kOutOfBounds;
4894 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4895 c.ids_shm_id, c.ids_shm_offset, data_size);
4896 if (n < 0) {
4897 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
4898 return error::kNoError;
4900 if (ids == NULL) {
4901 return error::kOutOfBounds;
4903 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4904 return error::kNoError;
4907 void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4908 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4909 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4910 for (GLsizei ii = 0; ii < n; ++ii) {
4911 if (!id_allocator->MarkAsUsed(ids[ii])) {
4912 for (GLsizei jj = 0; jj < ii; ++jj) {
4913 id_allocator->FreeID(ids[jj]);
4915 LOCAL_SET_GL_ERROR(
4916 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4917 "attempt to register id that already exists");
4918 return;
4923 error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4924 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
4925 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4926 GLsizei n = static_cast<GLsizei>(c.n);
4927 uint32 data_size;
4928 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4929 return error::kOutOfBounds;
4931 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4932 c.ids_shm_id, c.ids_shm_offset, data_size);
4933 if (n < 0) {
4934 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
4935 return error::kNoError;
4937 if (ids == NULL) {
4938 return error::kOutOfBounds;
4940 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
4941 return error::kNoError;
4944 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
4945 DCHECK(!ShouldDeferDraws());
4946 if (CheckBoundFramebuffersValid("glClear")) {
4947 ApplyDirtyState();
4948 glClear(mask);
4950 return error::kNoError;
4953 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4954 GLenum target, GLenum attachment, GLenum renderbuffertarget,
4955 GLuint client_renderbuffer_id) {
4956 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4957 if (!framebuffer) {
4958 LOCAL_SET_GL_ERROR(
4959 GL_INVALID_OPERATION,
4960 "glFramebufferRenderbuffer", "no framebuffer bound");
4961 return;
4963 GLuint service_id = 0;
4964 Renderbuffer* renderbuffer = NULL;
4965 if (client_renderbuffer_id) {
4966 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4967 if (!renderbuffer) {
4968 LOCAL_SET_GL_ERROR(
4969 GL_INVALID_OPERATION,
4970 "glFramebufferRenderbuffer", "unknown renderbuffer");
4971 return;
4973 service_id = renderbuffer->service_id();
4975 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
4976 glFramebufferRenderbufferEXT(
4977 target, attachment, renderbuffertarget, service_id);
4978 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
4979 if (error == GL_NO_ERROR) {
4980 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
4982 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
4983 framebuffer_state_.clear_state_dirty = true;
4985 OnFboChanged();
4988 void GLES2DecoderImpl::DoDisable(GLenum cap) {
4989 if (SetCapabilityState(cap, false)) {
4990 glDisable(cap);
4994 void GLES2DecoderImpl::DoEnable(GLenum cap) {
4995 if (SetCapabilityState(cap, true)) {
4996 glEnable(cap);
5000 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5001 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5002 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5003 glDepthRange(znear, zfar);
5006 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5007 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5008 state_.sample_coverage_invert = (invert != 0);
5009 glSampleCoverage(state_.sample_coverage_value, invert);
5012 // Assumes framebuffer is complete.
5013 void GLES2DecoderImpl::ClearUnclearedAttachments(
5014 GLenum target, Framebuffer* framebuffer) {
5015 if (target == GL_READ_FRAMEBUFFER_EXT) {
5016 // bind this to the DRAW point, clear then bind back to READ
5017 // TODO(gman): I don't think there is any guarantee that an FBO that
5018 // is complete on the READ attachment will be complete as a DRAW
5019 // attachment.
5020 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5021 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5023 GLbitfield clear_bits = 0;
5024 if (framebuffer->HasUnclearedColorAttachments()) {
5025 glClearColor(
5026 0.0f, 0.0f, 0.0f,
5027 (GLES2Util::GetChannelsForFormat(
5028 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5029 1.0f);
5030 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5031 clear_bits |= GL_COLOR_BUFFER_BIT;
5032 framebuffer->PrepareDrawBuffersForClear();
5035 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5036 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5037 glClearStencil(0);
5038 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
5039 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
5040 clear_bits |= GL_STENCIL_BUFFER_BIT;
5043 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5044 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5045 glClearDepth(1.0f);
5046 state_.SetDeviceDepthMask(GL_TRUE);
5047 clear_bits |= GL_DEPTH_BUFFER_BIT;
5050 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5051 glClear(clear_bits);
5053 if ((clear_bits | GL_COLOR_BUFFER_BIT) != 0)
5054 framebuffer->RestoreDrawBuffersAfterClear();
5056 framebuffer_manager()->MarkAttachmentsAsCleared(
5057 framebuffer, renderbuffer_manager(), texture_manager());
5059 RestoreClearState();
5061 if (target == GL_READ_FRAMEBUFFER_EXT) {
5062 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5063 Framebuffer* draw_framebuffer =
5064 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5065 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5066 GetBackbufferServiceId();
5067 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5071 void GLES2DecoderImpl::RestoreClearState() {
5072 framebuffer_state_.clear_state_dirty = true;
5073 glClearColor(
5074 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5075 state_.color_clear_alpha);
5076 glClearStencil(state_.stencil_clear);
5077 glClearDepth(state_.depth_clear);
5078 if (state_.enable_flags.scissor_test) {
5079 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5083 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5084 Framebuffer* framebuffer =
5085 GetFramebufferInfoForTarget(target);
5086 if (!framebuffer) {
5087 return GL_FRAMEBUFFER_COMPLETE;
5089 GLenum completeness = framebuffer->IsPossiblyComplete();
5090 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5091 return completeness;
5093 return framebuffer->GetStatus(texture_manager(), target);
5096 void GLES2DecoderImpl::DoFramebufferTexture2D(
5097 GLenum target, GLenum attachment, GLenum textarget,
5098 GLuint client_texture_id, GLint level) {
5099 DoFramebufferTexture2DCommon(
5100 "glFramebufferTexture2D", target, attachment,
5101 textarget, client_texture_id, level, 0);
5104 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5105 GLenum target, GLenum attachment, GLenum textarget,
5106 GLuint client_texture_id, GLint level, GLsizei samples) {
5107 DoFramebufferTexture2DCommon(
5108 "glFramebufferTexture2DMultisample", target, attachment,
5109 textarget, client_texture_id, level, samples);
5112 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5113 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5114 GLuint client_texture_id, GLint level, GLsizei samples) {
5115 if (samples > renderbuffer_manager()->max_samples()) {
5116 LOCAL_SET_GL_ERROR(
5117 GL_INVALID_VALUE,
5118 "glFramebufferTexture2DMultisample", "samples too large");
5119 return;
5121 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5122 if (!framebuffer) {
5123 LOCAL_SET_GL_ERROR(
5124 GL_INVALID_OPERATION,
5125 name, "no framebuffer bound.");
5126 return;
5128 GLuint service_id = 0;
5129 TextureRef* texture_ref = NULL;
5130 if (client_texture_id) {
5131 texture_ref = GetTexture(client_texture_id);
5132 if (!texture_ref) {
5133 LOCAL_SET_GL_ERROR(
5134 GL_INVALID_OPERATION,
5135 name, "unknown texture_ref");
5136 return;
5138 service_id = texture_ref->service_id();
5141 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5142 LOCAL_SET_GL_ERROR(
5143 GL_INVALID_VALUE,
5144 name, "level out of range");
5145 return;
5148 if (texture_ref)
5149 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5151 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5152 if (0 == samples) {
5153 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5154 } else {
5155 if (features().use_img_for_multisampled_render_to_texture) {
5156 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5157 service_id, level, samples);
5158 } else {
5159 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5160 service_id, level, samples);
5163 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5164 if (error == GL_NO_ERROR) {
5165 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5166 samples);
5168 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5169 framebuffer_state_.clear_state_dirty = true;
5172 if (texture_ref)
5173 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5175 OnFboChanged();
5178 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5179 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5180 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5181 if (!framebuffer) {
5182 LOCAL_SET_GL_ERROR(
5183 GL_INVALID_OPERATION,
5184 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5185 return;
5187 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5188 const Framebuffer::Attachment* attachment_object =
5189 framebuffer->GetAttachment(attachment);
5190 *params = attachment_object ? attachment_object->object_name() : 0;
5191 } else {
5192 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5193 features().use_img_for_multisampled_render_to_texture) {
5194 pname = GL_TEXTURE_SAMPLES_IMG;
5196 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5200 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5201 GLenum target, GLenum pname, GLint* params) {
5202 Renderbuffer* renderbuffer =
5203 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5204 if (!renderbuffer) {
5205 LOCAL_SET_GL_ERROR(
5206 GL_INVALID_OPERATION,
5207 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5208 return;
5211 EnsureRenderbufferBound();
5212 switch (pname) {
5213 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5214 *params = renderbuffer->internal_format();
5215 break;
5216 case GL_RENDERBUFFER_WIDTH:
5217 *params = renderbuffer->width();
5218 break;
5219 case GL_RENDERBUFFER_HEIGHT:
5220 *params = renderbuffer->height();
5221 break;
5222 case GL_RENDERBUFFER_SAMPLES_EXT:
5223 if (features().use_img_for_multisampled_render_to_texture) {
5224 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5225 params);
5226 } else {
5227 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5228 params);
5230 default:
5231 glGetRenderbufferParameterivEXT(target, pname, params);
5232 break;
5236 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5237 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5238 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5239 GLbitfield mask, GLenum filter) {
5240 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5242 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5243 return;
5246 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5247 BlitFramebufferHelper(
5248 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5249 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5250 state_.enable_flags.scissor_test);
5253 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5254 if (!state_.bound_renderbuffer_valid) {
5255 state_.bound_renderbuffer_valid = true;
5256 glBindRenderbufferEXT(GL_RENDERBUFFER,
5257 state_.bound_renderbuffer.get()
5258 ? state_.bound_renderbuffer->service_id()
5259 : 0);
5263 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5264 const FeatureInfo* feature_info,
5265 GLenum target,
5266 GLsizei samples,
5267 GLenum internal_format,
5268 GLsizei width,
5269 GLsizei height) {
5270 // TODO(sievers): This could be resolved at the GL binding level, but the
5271 // binding process is currently a bit too 'brute force'.
5272 if (feature_info->feature_flags().is_angle) {
5273 glRenderbufferStorageMultisampleANGLE(
5274 target, samples, internal_format, width, height);
5275 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5276 glRenderbufferStorageMultisample(
5277 target, samples, internal_format, width, height);
5278 } else {
5279 glRenderbufferStorageMultisampleEXT(
5280 target, samples, internal_format, width, height);
5284 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5285 GLint srcY0,
5286 GLint srcX1,
5287 GLint srcY1,
5288 GLint dstX0,
5289 GLint dstY0,
5290 GLint dstX1,
5291 GLint dstY1,
5292 GLbitfield mask,
5293 GLenum filter) {
5294 // TODO(sievers): This could be resolved at the GL binding level, but the
5295 // binding process is currently a bit too 'brute force'.
5296 if (feature_info_->feature_flags().is_angle) {
5297 glBlitFramebufferANGLE(
5298 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5299 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5300 glBlitFramebuffer(
5301 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5302 } else {
5303 glBlitFramebufferEXT(
5304 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5308 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5309 GLsizei samples,
5310 GLenum internalformat,
5311 GLsizei width,
5312 GLsizei height) {
5313 if (samples > renderbuffer_manager()->max_samples()) {
5314 LOCAL_SET_GL_ERROR(
5315 GL_INVALID_VALUE,
5316 "glRenderbufferStorageMultisample", "samples too large");
5317 return false;
5320 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5321 height > renderbuffer_manager()->max_renderbuffer_size()) {
5322 LOCAL_SET_GL_ERROR(
5323 GL_INVALID_VALUE,
5324 "glRenderbufferStorageMultisample", "dimensions too large");
5325 return false;
5328 uint32 estimated_size = 0;
5329 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5330 width, height, samples, internalformat, &estimated_size)) {
5331 LOCAL_SET_GL_ERROR(
5332 GL_OUT_OF_MEMORY,
5333 "glRenderbufferStorageMultisample", "dimensions too large");
5334 return false;
5337 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5338 LOCAL_SET_GL_ERROR(
5339 GL_OUT_OF_MEMORY,
5340 "glRenderbufferStorageMultisample", "out of memory");
5341 return false;
5344 return true;
5347 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5348 GLenum target, GLsizei samples, GLenum internalformat,
5349 GLsizei width, GLsizei height) {
5350 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5351 if (!renderbuffer) {
5352 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5353 "glRenderbufferStorageMultisampleCHROMIUM",
5354 "no renderbuffer bound");
5355 return;
5358 if (!ValidateRenderbufferStorageMultisample(
5359 samples, internalformat, width, height)) {
5360 return;
5363 EnsureRenderbufferBound();
5364 GLenum impl_format =
5365 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5366 internalformat);
5367 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5368 "glRenderbufferStorageMultisampleCHROMIUM");
5369 RenderbufferStorageMultisampleHelper(
5370 feature_info_, target, samples, impl_format, width, height);
5371 GLenum error =
5372 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5373 if (error == GL_NO_ERROR) {
5375 if (workarounds().validate_multisample_buffer_allocation) {
5376 if (!VerifyMultisampleRenderbufferIntegrity(
5377 renderbuffer->service_id(), impl_format)) {
5378 LOCAL_SET_GL_ERROR(
5379 GL_OUT_OF_MEMORY,
5380 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5381 return;
5385 // TODO(gman): If renderbuffers tracked which framebuffers they were
5386 // attached to we could just mark those framebuffers as not complete.
5387 framebuffer_manager()->IncFramebufferStateChangeCount();
5388 renderbuffer_manager()->SetInfo(
5389 renderbuffer, samples, internalformat, width, height);
5393 // This is the handler for multisampled_render_to_texture extensions.
5394 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5395 GLenum target, GLsizei samples, GLenum internalformat,
5396 GLsizei width, GLsizei height) {
5397 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5398 if (!renderbuffer) {
5399 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5400 "glRenderbufferStorageMultisampleEXT",
5401 "no renderbuffer bound");
5402 return;
5405 if (!ValidateRenderbufferStorageMultisample(
5406 samples, internalformat, width, height)) {
5407 return;
5410 EnsureRenderbufferBound();
5411 GLenum impl_format =
5412 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5413 internalformat);
5414 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5415 if (features().use_img_for_multisampled_render_to_texture) {
5416 glRenderbufferStorageMultisampleIMG(
5417 target, samples, impl_format, width, height);
5418 } else {
5419 glRenderbufferStorageMultisampleEXT(
5420 target, samples, impl_format, width, height);
5422 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5423 if (error == GL_NO_ERROR) {
5424 // TODO(gman): If renderbuffers tracked which framebuffers they were
5425 // attached to we could just mark those framebuffers as not complete.
5426 framebuffer_manager()->IncFramebufferStateChangeCount();
5427 renderbuffer_manager()->SetInfo(
5428 renderbuffer, samples, internalformat, width, height);
5432 // This function validates the allocation of a multisampled renderbuffer
5433 // by clearing it to a key color, blitting the contents to a texture, and
5434 // reading back the color to ensure it matches the key.
5435 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5436 GLuint renderbuffer, GLenum format) {
5438 // Only validate color buffers.
5439 // These formats have been selected because they are very common or are known
5440 // to be used by the WebGL backbuffer. If problems are observed with other
5441 // color formats they can be added here.
5442 switch(format) {
5443 case GL_RGB:
5444 case GL_RGB8:
5445 case GL_RGBA:
5446 case GL_RGBA8:
5447 break;
5448 default:
5449 return true;
5452 GLint draw_framebuffer, read_framebuffer;
5454 // Cache framebuffer and texture bindings.
5455 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5456 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5458 if (!validation_texture_) {
5459 GLint bound_texture;
5460 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5462 // Create additional resources needed for the verification.
5463 glGenTextures(1, &validation_texture_);
5464 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5465 glGenFramebuffersEXT(1, &validation_fbo_);
5467 // Texture only needs to be 1x1.
5468 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5469 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5470 GL_UNSIGNED_BYTE, NULL);
5472 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5473 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5474 GL_TEXTURE_2D, validation_texture_, 0);
5476 glBindTexture(GL_TEXTURE_2D, bound_texture);
5479 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5480 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5481 GL_RENDERBUFFER, renderbuffer);
5483 // Cache current state and reset it to the values we require.
5484 GLboolean scissor_enabled = false;
5485 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5486 if (scissor_enabled)
5487 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5489 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5490 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5491 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5493 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5494 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5495 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5497 // Clear the buffer to the desired key color.
5498 glClear(GL_COLOR_BUFFER_BIT);
5500 // Blit from the multisample buffer to a standard texture.
5501 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5502 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5504 BlitFramebufferHelper(
5505 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5507 // Read a pixel from the buffer.
5508 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5510 unsigned char pixel[3] = {0, 0, 0};
5511 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5513 // Detach the renderbuffer.
5514 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5515 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5516 GL_RENDERBUFFER, 0);
5518 // Restore cached state.
5519 if (scissor_enabled)
5520 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5522 state_.SetDeviceColorMask(
5523 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5524 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5525 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5526 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5528 // Return true if the pixel matched the desired key color.
5529 return (pixel[0] == 0xFF &&
5530 pixel[1] == 0x00 &&
5531 pixel[2] == 0xFF);
5534 void GLES2DecoderImpl::DoRenderbufferStorage(
5535 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5536 Renderbuffer* renderbuffer =
5537 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5538 if (!renderbuffer) {
5539 LOCAL_SET_GL_ERROR(
5540 GL_INVALID_OPERATION,
5541 "glRenderbufferStorage", "no renderbuffer bound");
5542 return;
5545 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5546 height > renderbuffer_manager()->max_renderbuffer_size()) {
5547 LOCAL_SET_GL_ERROR(
5548 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5549 return;
5552 uint32 estimated_size = 0;
5553 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5554 width, height, 1, internalformat, &estimated_size)) {
5555 LOCAL_SET_GL_ERROR(
5556 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5557 return;
5560 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5561 LOCAL_SET_GL_ERROR(
5562 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5563 return;
5566 EnsureRenderbufferBound();
5567 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5568 glRenderbufferStorageEXT(
5569 target,
5570 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5571 internalformat),
5572 width,
5573 height);
5574 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5575 if (error == GL_NO_ERROR) {
5576 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5577 // we could just mark those framebuffers as not complete.
5578 framebuffer_manager()->IncFramebufferStateChangeCount();
5579 renderbuffer_manager()->SetInfo(
5580 renderbuffer, 1, internalformat, width, height);
5584 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5585 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5586 Program* program = GetProgramInfoNotShader(
5587 program_id, "glLinkProgram");
5588 if (!program) {
5589 return;
5592 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5593 ShaderTranslator* vertex_translator = NULL;
5594 ShaderTranslator* fragment_translator = NULL;
5595 if (use_shader_translator_) {
5596 vertex_translator = vertex_translator_.get();
5597 fragment_translator = fragment_translator_.get();
5599 if (program->Link(shader_manager(),
5600 vertex_translator,
5601 fragment_translator,
5602 workarounds().count_all_in_varyings_packing ?
5603 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5604 shader_cache_callback_)) {
5605 if (program == state_.current_program.get()) {
5606 if (workarounds().use_current_program_after_successful_link)
5607 glUseProgram(program->service_id());
5608 if (workarounds().clear_uniforms_before_first_program_use)
5609 program_manager()->ClearUniforms(program);
5614 void GLES2DecoderImpl::DoTexParameterf(
5615 GLenum target, GLenum pname, GLfloat param) {
5616 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5617 &state_, target);
5618 if (!texture) {
5619 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5620 return;
5623 texture_manager()->SetParameterf(
5624 "glTexParameterf", GetErrorState(), texture, pname, param);
5627 void GLES2DecoderImpl::DoTexParameteri(
5628 GLenum target, GLenum pname, GLint param) {
5629 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5630 &state_, target);
5631 if (!texture) {
5632 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5633 return;
5636 texture_manager()->SetParameteri(
5637 "glTexParameteri", GetErrorState(), texture, pname, param);
5640 void GLES2DecoderImpl::DoTexParameterfv(
5641 GLenum target, GLenum pname, const GLfloat* params) {
5642 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5643 &state_, target);
5644 if (!texture) {
5645 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5646 return;
5649 texture_manager()->SetParameterf(
5650 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5653 void GLES2DecoderImpl::DoTexParameteriv(
5654 GLenum target, GLenum pname, const GLint* params) {
5655 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5656 &state_, target);
5657 if (!texture) {
5658 LOCAL_SET_GL_ERROR(
5659 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5660 return;
5663 texture_manager()->SetParameteri(
5664 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5667 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5668 if (!state_.current_program.get()) {
5669 // The program does not exist.
5670 LOCAL_SET_GL_ERROR(
5671 GL_INVALID_OPERATION, function_name, "no program in use");
5672 return false;
5674 if (!state_.current_program->InUse()) {
5675 LOCAL_SET_GL_ERROR(
5676 GL_INVALID_OPERATION, function_name, "program not linked");
5677 return false;
5679 return true;
5682 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5683 GLint location, const char* function_name) {
5684 if (!CheckCurrentProgram(function_name)) {
5685 return false;
5687 return location != -1;
5690 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5691 GLint fake_location,
5692 const char* function_name,
5693 Program::UniformApiType api_type,
5694 GLint* real_location,
5695 GLenum* type,
5696 GLsizei* count) {
5697 DCHECK(type);
5698 DCHECK(count);
5699 DCHECK(real_location);
5701 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5702 return false;
5704 GLint array_index = -1;
5705 const Program::UniformInfo* info =
5706 state_.current_program->GetUniformInfoByFakeLocation(
5707 fake_location, real_location, &array_index);
5708 if (!info) {
5709 LOCAL_SET_GL_ERROR(
5710 GL_INVALID_OPERATION, function_name, "unknown location");
5711 return false;
5714 if ((api_type & info->accepts_api_type) == 0) {
5715 LOCAL_SET_GL_ERROR(
5716 GL_INVALID_OPERATION, function_name,
5717 "wrong uniform function for type");
5718 return false;
5720 if (*count > 1 && !info->is_array) {
5721 LOCAL_SET_GL_ERROR(
5722 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5723 return false;
5725 *count = std::min(info->size - array_index, *count);
5726 if (*count <= 0) {
5727 return false;
5729 *type = info->type;
5730 return true;
5733 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5734 GLenum type = 0;
5735 GLsizei count = 1;
5736 GLint real_location = -1;
5737 if (!PrepForSetUniformByLocation(fake_location,
5738 "glUniform1i",
5739 Program::kUniform1i,
5740 &real_location,
5741 &type,
5742 &count)) {
5743 return;
5745 if (!state_.current_program->SetSamplers(
5746 state_.texture_units.size(), fake_location, 1, &v0)) {
5747 LOCAL_SET_GL_ERROR(
5748 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
5749 return;
5751 glUniform1i(real_location, v0);
5754 void GLES2DecoderImpl::DoUniform1iv(
5755 GLint fake_location, GLsizei count, const GLint *value) {
5756 GLenum type = 0;
5757 GLint real_location = -1;
5758 if (!PrepForSetUniformByLocation(fake_location,
5759 "glUniform1iv",
5760 Program::kUniform1i,
5761 &real_location,
5762 &type,
5763 &count)) {
5764 return;
5766 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5767 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5768 if (!state_.current_program->SetSamplers(
5769 state_.texture_units.size(), fake_location, count, value)) {
5770 LOCAL_SET_GL_ERROR(
5771 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
5772 return;
5775 glUniform1iv(real_location, count, value);
5778 void GLES2DecoderImpl::DoUniform1fv(
5779 GLint fake_location, GLsizei count, const GLfloat* value) {
5780 GLenum type = 0;
5781 GLint real_location = -1;
5782 if (!PrepForSetUniformByLocation(fake_location,
5783 "glUniform1fv",
5784 Program::kUniform1f,
5785 &real_location,
5786 &type,
5787 &count)) {
5788 return;
5790 if (type == GL_BOOL) {
5791 scoped_ptr<GLint[]> temp(new GLint[count]);
5792 for (GLsizei ii = 0; ii < count; ++ii) {
5793 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5795 DoUniform1iv(real_location, count, temp.get());
5796 } else {
5797 glUniform1fv(real_location, count, value);
5801 void GLES2DecoderImpl::DoUniform2fv(
5802 GLint fake_location, GLsizei count, const GLfloat* value) {
5803 GLenum type = 0;
5804 GLint real_location = -1;
5805 if (!PrepForSetUniformByLocation(fake_location,
5806 "glUniform2fv",
5807 Program::kUniform2f,
5808 &real_location,
5809 &type,
5810 &count)) {
5811 return;
5813 if (type == GL_BOOL_VEC2) {
5814 GLsizei num_values = count * 2;
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 glUniform2iv(real_location, count, temp.get());
5820 } else {
5821 glUniform2fv(real_location, count, value);
5825 void GLES2DecoderImpl::DoUniform3fv(
5826 GLint fake_location, GLsizei count, const GLfloat* value) {
5827 GLenum type = 0;
5828 GLint real_location = -1;
5829 if (!PrepForSetUniformByLocation(fake_location,
5830 "glUniform3fv",
5831 Program::kUniform3f,
5832 &real_location,
5833 &type,
5834 &count)) {
5835 return;
5837 if (type == GL_BOOL_VEC3) {
5838 GLsizei num_values = count * 3;
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 glUniform3iv(real_location, count, temp.get());
5844 } else {
5845 glUniform3fv(real_location, count, value);
5849 void GLES2DecoderImpl::DoUniform4fv(
5850 GLint fake_location, GLsizei count, const GLfloat* value) {
5851 GLenum type = 0;
5852 GLint real_location = -1;
5853 if (!PrepForSetUniformByLocation(fake_location,
5854 "glUniform4fv",
5855 Program::kUniform4f,
5856 &real_location,
5857 &type,
5858 &count)) {
5859 return;
5861 if (type == GL_BOOL_VEC4) {
5862 GLsizei num_values = count * 4;
5863 scoped_ptr<GLint[]> temp(new GLint[num_values]);
5864 for (GLsizei ii = 0; ii < num_values; ++ii) {
5865 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5867 glUniform4iv(real_location, count, temp.get());
5868 } else {
5869 glUniform4fv(real_location, count, value);
5873 void GLES2DecoderImpl::DoUniform2iv(
5874 GLint fake_location, GLsizei count, const GLint* value) {
5875 GLenum type = 0;
5876 GLint real_location = -1;
5877 if (!PrepForSetUniformByLocation(fake_location,
5878 "glUniform2iv",
5879 Program::kUniform2i,
5880 &real_location,
5881 &type,
5882 &count)) {
5883 return;
5885 glUniform2iv(real_location, count, value);
5888 void GLES2DecoderImpl::DoUniform3iv(
5889 GLint fake_location, GLsizei count, const GLint* value) {
5890 GLenum type = 0;
5891 GLint real_location = -1;
5892 if (!PrepForSetUniformByLocation(fake_location,
5893 "glUniform3iv",
5894 Program::kUniform3i,
5895 &real_location,
5896 &type,
5897 &count)) {
5898 return;
5900 glUniform3iv(real_location, count, value);
5903 void GLES2DecoderImpl::DoUniform4iv(
5904 GLint fake_location, GLsizei count, const GLint* value) {
5905 GLenum type = 0;
5906 GLint real_location = -1;
5907 if (!PrepForSetUniformByLocation(fake_location,
5908 "glUniform4iv",
5909 Program::kUniform4i,
5910 &real_location,
5911 &type,
5912 &count)) {
5913 return;
5915 glUniform4iv(real_location, count, value);
5918 void GLES2DecoderImpl::DoUniformMatrix2fv(
5919 GLint fake_location, GLsizei count, GLboolean transpose,
5920 const GLfloat* value) {
5921 GLenum type = 0;
5922 GLint real_location = -1;
5923 if (!PrepForSetUniformByLocation(fake_location,
5924 "glUniformMatrix2fv",
5925 Program::kUniformMatrix2f,
5926 &real_location,
5927 &type,
5928 &count)) {
5929 return;
5931 glUniformMatrix2fv(real_location, count, transpose, value);
5934 void GLES2DecoderImpl::DoUniformMatrix3fv(
5935 GLint fake_location, GLsizei count, GLboolean transpose,
5936 const GLfloat* value) {
5937 GLenum type = 0;
5938 GLint real_location = -1;
5939 if (!PrepForSetUniformByLocation(fake_location,
5940 "glUniformMatrix3fv",
5941 Program::kUniformMatrix3f,
5942 &real_location,
5943 &type,
5944 &count)) {
5945 return;
5947 glUniformMatrix3fv(real_location, count, transpose, value);
5950 void GLES2DecoderImpl::DoUniformMatrix4fv(
5951 GLint fake_location, GLsizei count, GLboolean transpose,
5952 const GLfloat* value) {
5953 GLenum type = 0;
5954 GLint real_location = -1;
5955 if (!PrepForSetUniformByLocation(fake_location,
5956 "glUniformMatrix4fv",
5957 Program::kUniformMatrix4f,
5958 &real_location,
5959 &type,
5960 &count)) {
5961 return;
5963 glUniformMatrix4fv(real_location, count, transpose, value);
5966 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
5967 GLuint service_id = 0;
5968 Program* program = NULL;
5969 if (program_id) {
5970 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5971 if (!program) {
5972 return;
5974 if (!program->IsValid()) {
5975 // Program was not linked successfully. (ie, glLinkProgram)
5976 LOCAL_SET_GL_ERROR(
5977 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
5978 return;
5980 service_id = program->service_id();
5982 if (state_.current_program.get()) {
5983 program_manager()->UnuseProgram(shader_manager(),
5984 state_.current_program.get());
5986 state_.current_program = program;
5987 LogClientServiceMapping("glUseProgram", program_id, service_id);
5988 glUseProgram(service_id);
5989 if (state_.current_program.get()) {
5990 program_manager()->UseProgram(state_.current_program.get());
5991 if (workarounds().clear_uniforms_before_first_program_use)
5992 program_manager()->ClearUniforms(program);
5996 void GLES2DecoderImpl::RenderWarning(
5997 const char* filename, int line, const std::string& msg) {
5998 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6001 void GLES2DecoderImpl::PerformanceWarning(
6002 const char* filename, int line, const std::string& msg) {
6003 logger_.LogMessage(filename, line,
6004 std::string("PERFORMANCE WARNING: ") + msg);
6007 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6008 Texture* texture, GLenum textarget) {
6009 // Image is already in use if texture is attached to a framebuffer.
6010 if (texture && !texture->IsAttachedToFramebuffer()) {
6011 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6012 if (image) {
6013 ScopedGLErrorSuppressor suppressor(
6014 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6015 GetErrorState());
6016 glBindTexture(textarget, texture->service_id());
6017 image->WillUseTexImage();
6018 RestoreCurrentTextureBindings(&state_, textarget);
6023 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6024 Texture* texture, GLenum textarget) {
6025 // Image is still in use if texture is attached to a framebuffer.
6026 if (texture && !texture->IsAttachedToFramebuffer()) {
6027 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6028 if (image) {
6029 ScopedGLErrorSuppressor suppressor(
6030 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6031 GetErrorState());
6032 glBindTexture(textarget, texture->service_id());
6033 image->DidUseTexImage();
6034 RestoreCurrentTextureBindings(&state_, textarget);
6039 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6040 DCHECK(state_.current_program.get());
6041 if (!texture_manager()->HaveUnrenderableTextures() &&
6042 !texture_manager()->HaveImages()) {
6043 return true;
6046 bool textures_set = false;
6047 const Program::SamplerIndices& sampler_indices =
6048 state_.current_program->sampler_indices();
6049 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6050 const Program::UniformInfo* uniform_info =
6051 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6052 DCHECK(uniform_info);
6053 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6054 GLuint texture_unit_index = uniform_info->texture_units[jj];
6055 if (texture_unit_index < state_.texture_units.size()) {
6056 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6057 TextureRef* texture_ref =
6058 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6059 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6060 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6061 textures_set = true;
6062 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6063 glBindTexture(
6064 textarget,
6065 texture_manager()->black_texture_id(uniform_info->type));
6066 LOCAL_RENDER_WARNING(
6067 std::string("texture bound to texture unit ") +
6068 base::IntToString(texture_unit_index) +
6069 " is not renderable. It maybe non-power-of-2 and have"
6070 " incompatible texture filtering or is not"
6071 " 'texture complete'");
6072 continue;
6075 if (textarget != GL_TEXTURE_CUBE_MAP) {
6076 Texture* texture = texture_ref->texture();
6077 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6078 if (image && !texture->IsAttachedToFramebuffer()) {
6079 ScopedGLErrorSuppressor suppressor(
6080 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6081 textures_set = true;
6082 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6083 image->WillUseTexImage();
6084 continue;
6088 // else: should this be an error?
6091 return !textures_set;
6094 void GLES2DecoderImpl::RestoreStateForTextures() {
6095 DCHECK(state_.current_program.get());
6096 const Program::SamplerIndices& sampler_indices =
6097 state_.current_program->sampler_indices();
6098 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6099 const Program::UniformInfo* uniform_info =
6100 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6101 DCHECK(uniform_info);
6102 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6103 GLuint texture_unit_index = uniform_info->texture_units[jj];
6104 if (texture_unit_index < state_.texture_units.size()) {
6105 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6106 TextureRef* texture_ref =
6107 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6108 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6109 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6110 // Get the texture_ref info that was previously bound here.
6111 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6112 ? texture_unit.bound_texture_2d.get()
6113 : texture_unit.bound_texture_cube_map.get();
6114 glBindTexture(texture_unit.bind_target,
6115 texture_ref ? texture_ref->service_id() : 0);
6116 continue;
6119 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6120 Texture* texture = texture_ref->texture();
6121 gfx::GLImage* image =
6122 texture->GetLevelImage(texture_unit.bind_target, 0);
6123 if (image && !texture->IsAttachedToFramebuffer()) {
6124 ScopedGLErrorSuppressor suppressor(
6125 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6126 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6127 image->DidUseTexImage();
6128 continue;
6134 // Set the active texture back to whatever the user had it as.
6135 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6138 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6139 // Only check if there are some uncleared textures.
6140 if (!texture_manager()->HaveUnsafeTextures()) {
6141 return true;
6144 // 1: Check all textures we are about to render with.
6145 if (state_.current_program.get()) {
6146 const Program::SamplerIndices& sampler_indices =
6147 state_.current_program->sampler_indices();
6148 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6149 const Program::UniformInfo* uniform_info =
6150 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6151 DCHECK(uniform_info);
6152 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6153 GLuint texture_unit_index = uniform_info->texture_units[jj];
6154 if (texture_unit_index < state_.texture_units.size()) {
6155 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6156 TextureRef* texture_ref =
6157 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6158 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6159 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6160 return false;
6167 return true;
6170 bool GLES2DecoderImpl::IsDrawValid(
6171 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
6172 // NOTE: We specifically do not check current_program->IsValid() because
6173 // it could never be invalid since glUseProgram would have failed. While
6174 // glLinkProgram could later mark the program as invalid the previous
6175 // valid program will still function if it is still the current program.
6176 if (!state_.current_program.get()) {
6177 // The program does not exist.
6178 // But GL says no ERROR.
6179 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6180 return false;
6183 return state_.vertex_attrib_manager
6184 ->ValidateBindings(function_name,
6185 this,
6186 feature_info_.get(),
6187 state_.current_program.get(),
6188 max_vertex_accessed,
6189 primcount);
6192 bool GLES2DecoderImpl::SimulateAttrib0(
6193 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6194 DCHECK(simulated);
6195 *simulated = false;
6197 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6198 return true;
6200 const VertexAttrib* attrib =
6201 state_.vertex_attrib_manager->GetVertexAttrib(0);
6202 // If it's enabled or it's not used then we don't need to do anything.
6203 bool attrib_0_used =
6204 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6205 if (attrib->enabled() && attrib_0_used) {
6206 return true;
6209 // Make a buffer with a single repeated vec4 value enough to
6210 // simulate the constant value that is supposed to be here.
6211 // This is required to emulate GLES2 on GL.
6212 GLuint num_vertices = max_vertex_accessed + 1;
6213 uint32 size_needed = 0;
6215 if (num_vertices == 0 ||
6216 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6217 size_needed > 0x7FFFFFFFU) {
6218 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6219 return false;
6222 LOCAL_PERFORMANCE_WARNING(
6223 "Attribute 0 is disabled. This has signficant performance penalty");
6225 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6226 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6228 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6229 if (new_buffer) {
6230 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6231 GLenum error = glGetError();
6232 if (error != GL_NO_ERROR) {
6233 LOCAL_SET_GL_ERROR(
6234 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6235 return false;
6239 const Vec4& value = state_.attrib_values[0];
6240 if (new_buffer ||
6241 (attrib_0_used &&
6242 (!attrib_0_buffer_matches_value_ ||
6243 (value.v[0] != attrib_0_value_.v[0] ||
6244 value.v[1] != attrib_0_value_.v[1] ||
6245 value.v[2] != attrib_0_value_.v[2] ||
6246 value.v[3] != attrib_0_value_.v[3])))) {
6247 std::vector<Vec4> temp(num_vertices, value);
6248 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6249 attrib_0_buffer_matches_value_ = true;
6250 attrib_0_value_ = value;
6251 attrib_0_size_ = size_needed;
6254 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6256 if (attrib->divisor())
6257 glVertexAttribDivisorANGLE(0, 0);
6259 *simulated = true;
6260 return true;
6263 void GLES2DecoderImpl::RestoreStateForAttrib(
6264 GLuint attrib_index, bool restore_array_binding) {
6265 const VertexAttrib* attrib =
6266 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6267 if (restore_array_binding) {
6268 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6269 Buffer* buffer = attrib->buffer();
6270 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6271 glVertexAttribPointer(
6272 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6273 attrib->gl_stride(), ptr);
6275 if (attrib->divisor())
6276 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6277 glBindBuffer(
6278 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6279 state_.bound_array_buffer->service_id() : 0);
6281 // Never touch vertex attribute 0's state (in particular, never
6282 // disable it) when running on desktop GL because it will never be
6283 // re-enabled.
6284 if (attrib_index != 0 ||
6285 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6286 if (attrib->enabled()) {
6287 glEnableVertexAttribArray(attrib_index);
6288 } else {
6289 glDisableVertexAttribArray(attrib_index);
6294 bool GLES2DecoderImpl::SimulateFixedAttribs(
6295 const char* function_name,
6296 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6297 DCHECK(simulated);
6298 *simulated = false;
6299 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6300 return true;
6302 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6303 return true;
6306 LOCAL_PERFORMANCE_WARNING(
6307 "GL_FIXED attributes have a signficant performance penalty");
6309 // NOTE: we could be smart and try to check if a buffer is used
6310 // twice in 2 different attribs, find the overlapping parts and therefore
6311 // duplicate the minimum amount of data but this whole code path is not meant
6312 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6313 // tests so we just add to the buffer attrib used.
6315 GLuint elements_needed = 0;
6316 const VertexAttribManager::VertexAttribList& enabled_attribs =
6317 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6318 for (VertexAttribManager::VertexAttribList::const_iterator it =
6319 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6320 const VertexAttrib* attrib = *it;
6321 const Program::VertexAttrib* attrib_info =
6322 state_.current_program->GetAttribInfoByLocation(attrib->index());
6323 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6324 max_vertex_accessed);
6325 GLuint num_vertices = max_accessed + 1;
6326 if (num_vertices == 0) {
6327 LOCAL_SET_GL_ERROR(
6328 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6329 return false;
6331 if (attrib_info &&
6332 attrib->CanAccess(max_accessed) &&
6333 attrib->type() == GL_FIXED) {
6334 uint32 elements_used = 0;
6335 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6336 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6337 LOCAL_SET_GL_ERROR(
6338 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6339 return false;
6344 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6345 uint32 size_needed = 0;
6346 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6347 size_needed > 0x7FFFFFFFU) {
6348 LOCAL_SET_GL_ERROR(
6349 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6350 return false;
6353 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6355 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6356 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6357 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6358 GLenum error = glGetError();
6359 if (error != GL_NO_ERROR) {
6360 LOCAL_SET_GL_ERROR(
6361 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6362 return false;
6366 // Copy the elements and convert to float
6367 GLintptr offset = 0;
6368 for (VertexAttribManager::VertexAttribList::const_iterator it =
6369 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6370 const VertexAttrib* attrib = *it;
6371 const Program::VertexAttrib* attrib_info =
6372 state_.current_program->GetAttribInfoByLocation(attrib->index());
6373 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6374 max_vertex_accessed);
6375 GLuint num_vertices = max_accessed + 1;
6376 if (num_vertices == 0) {
6377 LOCAL_SET_GL_ERROR(
6378 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6379 return false;
6381 if (attrib_info &&
6382 attrib->CanAccess(max_accessed) &&
6383 attrib->type() == GL_FIXED) {
6384 int num_elements = attrib->size() * kSizeOfFloat;
6385 int size = num_elements * num_vertices;
6386 scoped_ptr<float[]> data(new float[size]);
6387 const int32* src = reinterpret_cast<const int32 *>(
6388 attrib->buffer()->GetRange(attrib->offset(), size));
6389 const int32* end = src + num_elements;
6390 float* dst = data.get();
6391 while (src != end) {
6392 *dst++ = static_cast<float>(*src++) / 65536.0f;
6394 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6395 glVertexAttribPointer(
6396 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6397 reinterpret_cast<GLvoid*>(offset));
6398 offset += size;
6401 *simulated = true;
6402 return true;
6405 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6406 // There's no need to call glVertexAttribPointer because we shadow all the
6407 // settings and passing GL_FIXED to it will not work.
6408 glBindBuffer(
6409 GL_ARRAY_BUFFER,
6410 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6411 : 0);
6414 error::Error GLES2DecoderImpl::DoDrawArrays(
6415 const char* function_name,
6416 bool instanced,
6417 GLenum mode,
6418 GLint first,
6419 GLsizei count,
6420 GLsizei primcount) {
6421 error::Error error = WillAccessBoundFramebufferForDraw();
6422 if (error != error::kNoError)
6423 return error;
6424 if (!validators_->draw_mode.IsValid(mode)) {
6425 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6426 return error::kNoError;
6428 if (count < 0) {
6429 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6430 return error::kNoError;
6432 if (primcount < 0) {
6433 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6434 return error::kNoError;
6436 if (!CheckBoundFramebuffersValid(function_name)) {
6437 return error::kNoError;
6439 // We have to check this here because the prototype for glDrawArrays
6440 // is GLint not GLsizei.
6441 if (first < 0) {
6442 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6443 return error::kNoError;
6446 if (count == 0 || (instanced && primcount == 0)) {
6447 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6448 return error::kNoError;
6451 GLuint max_vertex_accessed = first + count - 1;
6452 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6453 if (!ClearUnclearedTextures()) {
6454 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6455 return error::kNoError;
6457 bool simulated_attrib_0 = false;
6458 if (!SimulateAttrib0(
6459 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6460 return error::kNoError;
6462 bool simulated_fixed_attribs = false;
6463 if (SimulateFixedAttribs(
6464 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6465 primcount)) {
6466 bool textures_set = !PrepareTexturesForRender();
6467 ApplyDirtyState();
6468 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6469 if (!instanced) {
6470 glDrawArrays(mode, first, count);
6471 } else {
6472 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6474 if (textures_set) {
6475 RestoreStateForTextures();
6477 if (simulated_fixed_attribs) {
6478 RestoreStateForSimulatedFixedAttribs();
6481 if (simulated_attrib_0) {
6482 // We don't have to restore attrib 0 generic data at the end of this
6483 // function even if it is simulated. This is because we will simulate
6484 // it in each draw call, and attrib 0 generic data queries use cached
6485 // values instead of passing down to the underlying driver.
6486 RestoreStateForAttrib(0, false);
6489 return error::kNoError;
6492 error::Error GLES2DecoderImpl::HandleDrawArrays(
6493 uint32 immediate_data_size, const cmds::DrawArrays& c) {
6494 return DoDrawArrays("glDrawArrays",
6495 false,
6496 static_cast<GLenum>(c.mode),
6497 static_cast<GLint>(c.first),
6498 static_cast<GLsizei>(c.count),
6502 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6503 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
6504 if (!features().angle_instanced_arrays) {
6505 LOCAL_SET_GL_ERROR(
6506 GL_INVALID_OPERATION,
6507 "glDrawArraysInstancedANGLE", "function not available");
6508 return error::kNoError;
6510 return DoDrawArrays("glDrawArraysIntancedANGLE",
6511 true,
6512 static_cast<GLenum>(c.mode),
6513 static_cast<GLint>(c.first),
6514 static_cast<GLsizei>(c.count),
6515 static_cast<GLsizei>(c.primcount));
6518 error::Error GLES2DecoderImpl::DoDrawElements(
6519 const char* function_name,
6520 bool instanced,
6521 GLenum mode,
6522 GLsizei count,
6523 GLenum type,
6524 int32 offset,
6525 GLsizei primcount) {
6526 error::Error error = WillAccessBoundFramebufferForDraw();
6527 if (error != error::kNoError)
6528 return error;
6529 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6530 LOCAL_SET_GL_ERROR(
6531 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6532 return error::kNoError;
6535 if (count < 0) {
6536 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6537 return error::kNoError;
6539 if (offset < 0) {
6540 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6541 return error::kNoError;
6543 if (!validators_->draw_mode.IsValid(mode)) {
6544 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6545 return error::kNoError;
6547 if (!validators_->index_type.IsValid(type)) {
6548 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6549 return error::kNoError;
6551 if (primcount < 0) {
6552 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6553 return error::kNoError;
6556 if (!CheckBoundFramebuffersValid(function_name)) {
6557 return error::kNoError;
6560 if (count == 0 || (instanced && primcount == 0)) {
6561 return error::kNoError;
6564 GLuint max_vertex_accessed;
6565 Buffer* element_array_buffer =
6566 state_.vertex_attrib_manager->element_array_buffer();
6568 if (!element_array_buffer->GetMaxValueForRange(
6569 offset, count, type, &max_vertex_accessed)) {
6570 LOCAL_SET_GL_ERROR(
6571 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6572 return error::kNoError;
6575 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6576 if (!ClearUnclearedTextures()) {
6577 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6578 return error::kNoError;
6580 bool simulated_attrib_0 = false;
6581 if (!SimulateAttrib0(
6582 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6583 return error::kNoError;
6585 bool simulated_fixed_attribs = false;
6586 if (SimulateFixedAttribs(
6587 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6588 primcount)) {
6589 bool textures_set = !PrepareTexturesForRender();
6590 ApplyDirtyState();
6591 // TODO(gman): Refactor to hide these details in BufferManager or
6592 // VertexAttribManager.
6593 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6594 bool used_client_side_array = false;
6595 if (element_array_buffer->IsClientSideArray()) {
6596 used_client_side_array = true;
6597 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6598 indices = element_array_buffer->GetRange(offset, 0);
6601 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6602 if (!instanced) {
6603 glDrawElements(mode, count, type, indices);
6604 } else {
6605 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6608 if (used_client_side_array) {
6609 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6610 element_array_buffer->service_id());
6613 if (textures_set) {
6614 RestoreStateForTextures();
6616 if (simulated_fixed_attribs) {
6617 RestoreStateForSimulatedFixedAttribs();
6620 if (simulated_attrib_0) {
6621 // We don't have to restore attrib 0 generic data at the end of this
6622 // function even if it is simulated. This is because we will simulate
6623 // it in each draw call, and attrib 0 generic data queries use cached
6624 // values instead of passing down to the underlying driver.
6625 RestoreStateForAttrib(0, false);
6628 return error::kNoError;
6631 error::Error GLES2DecoderImpl::HandleDrawElements(
6632 uint32 immediate_data_size, const cmds::DrawElements& c) {
6633 return DoDrawElements("glDrawElements",
6634 false,
6635 static_cast<GLenum>(c.mode),
6636 static_cast<GLsizei>(c.count),
6637 static_cast<GLenum>(c.type),
6638 static_cast<int32>(c.index_offset),
6642 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
6643 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
6644 if (!features().angle_instanced_arrays) {
6645 LOCAL_SET_GL_ERROR(
6646 GL_INVALID_OPERATION,
6647 "glDrawElementsInstancedANGLE", "function not available");
6648 return error::kNoError;
6650 return DoDrawElements("glDrawElementsInstancedANGLE",
6651 true,
6652 static_cast<GLenum>(c.mode),
6653 static_cast<GLsizei>(c.count),
6654 static_cast<GLenum>(c.type),
6655 static_cast<int32>(c.index_offset),
6656 static_cast<GLsizei>(c.primcount));
6659 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6660 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6661 GLuint max_vertex_accessed = 0;
6662 Buffer* buffer = GetBuffer(buffer_id);
6663 if (!buffer) {
6664 // TODO(gman): Should this be a GL error or a command buffer error?
6665 LOCAL_SET_GL_ERROR(
6666 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
6667 } else {
6668 if (!buffer->GetMaxValueForRange(
6669 offset, count, type, &max_vertex_accessed)) {
6670 // TODO(gman): Should this be a GL error or a command buffer error?
6671 LOCAL_SET_GL_ERROR(
6672 GL_INVALID_OPERATION,
6673 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6676 return max_vertex_accessed;
6679 // Calls glShaderSource for the various versions of the ShaderSource command.
6680 // Assumes that data / data_size points to a piece of memory that is in range
6681 // of whatever context it came from (shared memory, immediate memory, bucket
6682 // memory.)
6683 error::Error GLES2DecoderImpl::ShaderSourceHelper(
6684 GLuint client_id, const char* data, uint32 data_size) {
6685 std::string str(data, data + data_size);
6686 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6687 if (!shader) {
6688 return error::kNoError;
6690 // Note: We don't actually call glShaderSource here. We wait until
6691 // the call to glCompileShader.
6692 shader->UpdateSource(str.c_str());
6693 return error::kNoError;
6696 error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
6697 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
6698 Bucket* bucket = GetBucket(c.data_bucket_id);
6699 if (!bucket || bucket->size() == 0) {
6700 return error::kInvalidArguments;
6702 return ShaderSourceHelper(
6703 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6704 bucket->size() - 1);
6707 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6708 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
6709 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6710 if (!shader) {
6711 return;
6713 ShaderTranslator* translator = NULL;
6714 if (use_shader_translator_) {
6715 translator = shader->shader_type() == GL_VERTEX_SHADER ?
6716 vertex_translator_.get() : fragment_translator_.get();
6719 program_manager()->DoCompileShader(
6720 shader,
6721 translator,
6722 feature_info_->feature_flags().angle_translated_shader_source ?
6723 ProgramManager::kANGLE : ProgramManager::kGL);
6726 void GLES2DecoderImpl::DoGetShaderiv(
6727 GLuint shader_id, GLenum pname, GLint* params) {
6728 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6729 if (!shader) {
6730 return;
6732 switch (pname) {
6733 case GL_SHADER_SOURCE_LENGTH:
6734 *params = shader->source() ? shader->source()->size() + 1 : 0;
6735 return;
6736 case GL_COMPILE_STATUS:
6737 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
6738 return;
6739 case GL_INFO_LOG_LENGTH:
6740 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
6741 return;
6742 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6743 *params = shader->translated_source() ?
6744 shader->translated_source()->size() + 1 : 0;
6745 return;
6746 default:
6747 break;
6749 glGetShaderiv(shader->service_id(), pname, params);
6752 error::Error GLES2DecoderImpl::HandleGetShaderSource(
6753 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
6754 GLuint shader_id = c.shader;
6755 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6756 Bucket* bucket = CreateBucket(bucket_id);
6757 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6758 if (!shader || !shader->source()) {
6759 bucket->SetSize(0);
6760 return error::kNoError;
6762 bucket->SetFromString(shader->source()->c_str());
6763 return error::kNoError;
6766 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6767 uint32 immediate_data_size,
6768 const cmds::GetTranslatedShaderSourceANGLE& c) {
6769 GLuint shader_id = c.shader;
6770 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6771 Bucket* bucket = CreateBucket(bucket_id);
6772 Shader* shader = GetShaderInfoNotProgram(
6773 shader_id, "glGetTranslatedShaderSourceANGLE");
6774 if (!shader) {
6775 bucket->SetSize(0);
6776 return error::kNoError;
6779 bucket->SetFromString(shader->translated_source() ?
6780 shader->translated_source()->c_str() : NULL);
6781 return error::kNoError;
6784 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
6785 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
6786 GLuint program_id = c.program;
6787 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6788 Bucket* bucket = CreateBucket(bucket_id);
6789 Program* program = GetProgramInfoNotShader(
6790 program_id, "glGetProgramInfoLog");
6791 if (!program || !program->log_info()) {
6792 bucket->SetFromString("");
6793 return error::kNoError;
6795 bucket->SetFromString(program->log_info()->c_str());
6796 return error::kNoError;
6799 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
6800 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
6801 GLuint shader_id = c.shader;
6802 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6803 Bucket* bucket = CreateBucket(bucket_id);
6804 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6805 if (!shader || !shader->log_info()) {
6806 bucket->SetFromString("");
6807 return error::kNoError;
6809 bucket->SetFromString(shader->log_info()->c_str());
6810 return error::kNoError;
6813 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6814 return state_.GetEnabled(cap);
6817 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
6818 const Buffer* buffer = GetBuffer(client_id);
6819 return buffer && buffer->IsValid() && !buffer->IsDeleted();
6822 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
6823 const Framebuffer* framebuffer =
6824 GetFramebuffer(client_id);
6825 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
6828 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
6829 // IsProgram is true for programs as soon as they are created, until they are
6830 // deleted and no longer in use.
6831 const Program* program = GetProgram(client_id);
6832 return program != NULL && !program->IsDeleted();
6835 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
6836 const Renderbuffer* renderbuffer =
6837 GetRenderbuffer(client_id);
6838 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
6841 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
6842 // IsShader is true for shaders as soon as they are created, until they
6843 // are deleted and not attached to any programs.
6844 const Shader* shader = GetShader(client_id);
6845 return shader != NULL && !shader->IsDeleted();
6848 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
6849 const TextureRef* texture_ref = GetTexture(client_id);
6850 return texture_ref && texture_ref->texture()->IsValid();
6853 void GLES2DecoderImpl::DoAttachShader(
6854 GLuint program_client_id, GLint shader_client_id) {
6855 Program* program = GetProgramInfoNotShader(
6856 program_client_id, "glAttachShader");
6857 if (!program) {
6858 return;
6860 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6861 if (!shader) {
6862 return;
6864 if (!program->AttachShader(shader_manager(), shader)) {
6865 LOCAL_SET_GL_ERROR(
6866 GL_INVALID_OPERATION,
6867 "glAttachShader",
6868 "can not attach more than one shader of the same type.");
6869 return;
6871 glAttachShader(program->service_id(), shader->service_id());
6874 void GLES2DecoderImpl::DoDetachShader(
6875 GLuint program_client_id, GLint shader_client_id) {
6876 Program* program = GetProgramInfoNotShader(
6877 program_client_id, "glDetachShader");
6878 if (!program) {
6879 return;
6881 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6882 if (!shader) {
6883 return;
6885 if (!program->DetachShader(shader_manager(), shader)) {
6886 LOCAL_SET_GL_ERROR(
6887 GL_INVALID_OPERATION,
6888 "glDetachShader", "shader not attached to program");
6889 return;
6891 glDetachShader(program->service_id(), shader->service_id());
6894 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
6895 Program* program = GetProgramInfoNotShader(
6896 program_client_id, "glValidateProgram");
6897 if (!program) {
6898 return;
6900 program->Validate();
6903 void GLES2DecoderImpl::GetVertexAttribHelper(
6904 const VertexAttrib* attrib, GLenum pname, GLint* params) {
6905 switch (pname) {
6906 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6907 Buffer* buffer = attrib->buffer();
6908 if (buffer && !buffer->IsDeleted()) {
6909 GLuint client_id;
6910 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6911 *params = client_id;
6913 break;
6915 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6916 *params = attrib->enabled();
6917 break;
6918 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6919 *params = attrib->size();
6920 break;
6921 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6922 *params = attrib->gl_stride();
6923 break;
6924 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6925 *params = attrib->type();
6926 break;
6927 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6928 *params = attrib->normalized();
6929 break;
6930 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6931 *params = attrib->divisor();
6932 break;
6933 default:
6934 NOTREACHED();
6935 break;
6939 void GLES2DecoderImpl::DoGetTexParameterfv(
6940 GLenum target, GLenum pname, GLfloat* params) {
6941 InitTextureMaxAnisotropyIfNeeded(target, pname);
6942 glGetTexParameterfv(target, pname, params);
6945 void GLES2DecoderImpl::DoGetTexParameteriv(
6946 GLenum target, GLenum pname, GLint* params) {
6947 InitTextureMaxAnisotropyIfNeeded(target, pname);
6948 glGetTexParameteriv(target, pname, params);
6951 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
6952 GLenum target, GLenum pname) {
6953 if (!workarounds().init_texture_max_anisotropy)
6954 return;
6955 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
6956 !validators_->texture_parameter.IsValid(pname)) {
6957 return;
6960 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
6961 &state_, target);
6962 if (!texture_ref) {
6963 LOCAL_SET_GL_ERROR(
6964 GL_INVALID_OPERATION,
6965 "glGetTexParamter{fi}v", "unknown texture for target");
6966 return;
6968 Texture* texture = texture_ref->texture();
6969 texture->InitTextureMaxAnisotropyIfNeeded(target);
6972 void GLES2DecoderImpl::DoGetVertexAttribfv(
6973 GLuint index, GLenum pname, GLfloat* params) {
6974 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6975 if (!attrib) {
6976 LOCAL_SET_GL_ERROR(
6977 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
6978 return;
6980 switch (pname) {
6981 case GL_CURRENT_VERTEX_ATTRIB: {
6982 const Vec4& value = state_.attrib_values[index];
6983 params[0] = value.v[0];
6984 params[1] = value.v[1];
6985 params[2] = value.v[2];
6986 params[3] = value.v[3];
6987 break;
6989 default: {
6990 GLint value = 0;
6991 GetVertexAttribHelper(attrib, pname, &value);
6992 *params = static_cast<GLfloat>(value);
6993 break;
6998 void GLES2DecoderImpl::DoGetVertexAttribiv(
6999 GLuint index, GLenum pname, GLint* params) {
7000 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7001 if (!attrib) {
7002 LOCAL_SET_GL_ERROR(
7003 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
7004 return;
7006 switch (pname) {
7007 case GL_CURRENT_VERTEX_ATTRIB: {
7008 const Vec4& value = state_.attrib_values[index];
7009 params[0] = static_cast<GLint>(value.v[0]);
7010 params[1] = static_cast<GLint>(value.v[1]);
7011 params[2] = static_cast<GLint>(value.v[2]);
7012 params[3] = static_cast<GLint>(value.v[3]);
7013 break;
7015 default:
7016 GetVertexAttribHelper(attrib, pname, params);
7017 break;
7021 bool GLES2DecoderImpl::SetVertexAttribValue(
7022 const char* function_name, GLuint index, const GLfloat* value) {
7023 if (index >= state_.attrib_values.size()) {
7024 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7025 return false;
7027 Vec4& v = state_.attrib_values[index];
7028 v.v[0] = value[0];
7029 v.v[1] = value[1];
7030 v.v[2] = value[2];
7031 v.v[3] = value[3];
7032 return true;
7035 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7036 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7037 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7038 glVertexAttrib1f(index, v0);
7042 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7043 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7044 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7045 glVertexAttrib2f(index, v0, v1);
7049 void GLES2DecoderImpl::DoVertexAttrib3f(
7050 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7051 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7052 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7053 glVertexAttrib3f(index, v0, v1, v2);
7057 void GLES2DecoderImpl::DoVertexAttrib4f(
7058 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7059 GLfloat v[4] = { v0, v1, v2, v3, };
7060 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7061 glVertexAttrib4f(index, v0, v1, v2, v3);
7065 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7066 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7067 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7068 glVertexAttrib1fv(index, v);
7072 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7073 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7074 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7075 glVertexAttrib2fv(index, v);
7079 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7080 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7081 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7082 glVertexAttrib3fv(index, v);
7086 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7087 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7088 glVertexAttrib4fv(index, v);
7092 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7093 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
7095 if (!state_.bound_array_buffer.get() ||
7096 state_.bound_array_buffer->IsDeleted()) {
7097 if (state_.vertex_attrib_manager.get() ==
7098 state_.default_vertex_attrib_manager.get()) {
7099 LOCAL_SET_GL_ERROR(
7100 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7101 return error::kNoError;
7102 } else if (c.offset != 0) {
7103 LOCAL_SET_GL_ERROR(
7104 GL_INVALID_VALUE,
7105 "glVertexAttribPointer", "client side arrays are not allowed");
7106 return error::kNoError;
7110 GLuint indx = c.indx;
7111 GLint size = c.size;
7112 GLenum type = c.type;
7113 GLboolean normalized = c.normalized;
7114 GLsizei stride = c.stride;
7115 GLsizei offset = c.offset;
7116 const void* ptr = reinterpret_cast<const void*>(offset);
7117 if (!validators_->vertex_attrib_type.IsValid(type)) {
7118 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7119 return error::kNoError;
7121 if (!validators_->vertex_attrib_size.IsValid(size)) {
7122 LOCAL_SET_GL_ERROR(
7123 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7124 return error::kNoError;
7126 if (indx >= group_->max_vertex_attribs()) {
7127 LOCAL_SET_GL_ERROR(
7128 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7129 return error::kNoError;
7131 if (stride < 0) {
7132 LOCAL_SET_GL_ERROR(
7133 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7134 return error::kNoError;
7136 if (stride > 255) {
7137 LOCAL_SET_GL_ERROR(
7138 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7139 return error::kNoError;
7141 if (offset < 0) {
7142 LOCAL_SET_GL_ERROR(
7143 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7144 return error::kNoError;
7146 GLsizei component_size =
7147 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7148 if (offset % component_size > 0) {
7149 LOCAL_SET_GL_ERROR(
7150 GL_INVALID_OPERATION,
7151 "glVertexAttribPointer", "offset not valid for type");
7152 return error::kNoError;
7154 if (stride % component_size > 0) {
7155 LOCAL_SET_GL_ERROR(
7156 GL_INVALID_OPERATION,
7157 "glVertexAttribPointer", "stride not valid for type");
7158 return error::kNoError;
7160 state_.vertex_attrib_manager
7161 ->SetAttribInfo(indx,
7162 state_.bound_array_buffer.get(),
7163 size,
7164 type,
7165 normalized,
7166 stride,
7167 stride != 0 ? stride : component_size * size,
7168 offset);
7169 if (type != GL_FIXED) {
7170 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7172 return error::kNoError;
7175 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7176 GLsizei height) {
7177 state_.viewport_x = x;
7178 state_.viewport_y = y;
7179 state_.viewport_width = std::min(width, viewport_max_width_);
7180 state_.viewport_height = std::min(height, viewport_max_height_);
7181 glViewport(x, y, width, height);
7184 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7185 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
7186 if (!features().angle_instanced_arrays) {
7187 LOCAL_SET_GL_ERROR(
7188 GL_INVALID_OPERATION,
7189 "glVertexAttribDivisorANGLE", "function not available");
7190 return error::kNoError;
7192 GLuint index = c.index;
7193 GLuint divisor = c.divisor;
7194 if (index >= group_->max_vertex_attribs()) {
7195 LOCAL_SET_GL_ERROR(
7196 GL_INVALID_VALUE,
7197 "glVertexAttribDivisorANGLE", "index out of range");
7198 return error::kNoError;
7201 state_.vertex_attrib_manager->SetDivisor(
7202 index,
7203 divisor);
7204 glVertexAttribDivisorANGLE(index, divisor);
7205 return error::kNoError;
7208 template <typename pixel_data_type>
7209 static void WriteAlphaData(
7210 void *pixels, uint32 row_count, uint32 channel_count,
7211 uint32 alpha_channel_index, uint32 unpadded_row_size,
7212 uint32 padded_row_size, pixel_data_type alpha_value) {
7213 DCHECK_GT(channel_count, 0U);
7214 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7215 uint32 unpadded_row_size_in_elements =
7216 unpadded_row_size / sizeof(pixel_data_type);
7217 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7218 uint32 padded_row_size_in_elements =
7219 padded_row_size / sizeof(pixel_data_type);
7220 pixel_data_type* dst =
7221 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7222 for (uint32 yy = 0; yy < row_count; ++yy) {
7223 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7224 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7225 *d = alpha_value;
7227 dst += padded_row_size_in_elements;
7231 void GLES2DecoderImpl::FinishReadPixels(
7232 const cmds::ReadPixels& c,
7233 GLuint buffer) {
7234 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7235 GLsizei width = c.width;
7236 GLsizei height = c.height;
7237 GLenum format = c.format;
7238 GLenum type = c.type;
7239 typedef cmds::ReadPixels::Result Result;
7240 uint32 pixels_size;
7241 Result* result = NULL;
7242 if (c.result_shm_id != 0) {
7243 result = GetSharedMemoryAs<Result*>(
7244 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7245 if (!result) {
7246 if (buffer != 0) {
7247 glDeleteBuffersARB(1, &buffer);
7249 return;
7252 GLES2Util::ComputeImageDataSizes(
7253 width, height, format, type, state_.pack_alignment, &pixels_size,
7254 NULL, NULL);
7255 void* pixels = GetSharedMemoryAs<void*>(
7256 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7257 if (!pixels) {
7258 if (buffer != 0) {
7259 glDeleteBuffersARB(1, &buffer);
7261 return;
7264 if (buffer != 0) {
7265 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7266 void* data;
7267 if (features().map_buffer_range) {
7268 data = glMapBufferRange(
7269 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7270 } else {
7271 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7273 memcpy(pixels, data, pixels_size);
7274 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7275 // have to restore the state.
7276 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7277 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7278 glDeleteBuffersARB(1, &buffer);
7281 if (result != NULL) {
7282 *result = true;
7285 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7286 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7287 if ((channels_exist & 0x0008) == 0 &&
7288 workarounds().clear_alpha_in_readpixels) {
7289 // Set the alpha to 255 because some drivers are buggy in this regard.
7290 uint32 temp_size;
7292 uint32 unpadded_row_size;
7293 uint32 padded_row_size;
7294 if (!GLES2Util::ComputeImageDataSizes(
7295 width, 2, format, type, state_.pack_alignment, &temp_size,
7296 &unpadded_row_size, &padded_row_size)) {
7297 return;
7300 uint32 channel_count = 0;
7301 uint32 alpha_channel = 0;
7302 switch (format) {
7303 case GL_RGBA:
7304 case GL_BGRA_EXT:
7305 channel_count = 4;
7306 alpha_channel = 3;
7307 break;
7308 case GL_ALPHA:
7309 channel_count = 1;
7310 alpha_channel = 0;
7311 break;
7314 if (channel_count > 0) {
7315 switch (type) {
7316 case GL_UNSIGNED_BYTE:
7317 WriteAlphaData<uint8>(
7318 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7319 padded_row_size, 0xFF);
7320 break;
7321 case GL_FLOAT:
7322 WriteAlphaData<float>(
7323 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7324 padded_row_size, 1.0f);
7325 break;
7326 case GL_HALF_FLOAT:
7327 WriteAlphaData<uint16>(
7328 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7329 padded_row_size, 0x3C00);
7330 break;
7337 error::Error GLES2DecoderImpl::HandleReadPixels(
7338 uint32 immediate_data_size, const cmds::ReadPixels& c) {
7339 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7340 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7341 if (fbo_error != error::kNoError)
7342 return fbo_error;
7343 GLint x = c.x;
7344 GLint y = c.y;
7345 GLsizei width = c.width;
7346 GLsizei height = c.height;
7347 GLenum format = c.format;
7348 GLenum type = c.type;
7349 GLboolean async = c.async;
7350 if (width < 0 || height < 0) {
7351 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7352 return error::kNoError;
7354 typedef cmds::ReadPixels::Result Result;
7355 uint32 pixels_size;
7356 if (!GLES2Util::ComputeImageDataSizes(
7357 width, height, format, type, state_.pack_alignment, &pixels_size,
7358 NULL, NULL)) {
7359 return error::kOutOfBounds;
7361 void* pixels = GetSharedMemoryAs<void*>(
7362 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7363 if (!pixels) {
7364 return error::kOutOfBounds;
7366 Result* result = NULL;
7367 if (c.result_shm_id != 0) {
7368 result = GetSharedMemoryAs<Result*>(
7369 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7370 if (!result) {
7371 return error::kOutOfBounds;
7375 if (!validators_->read_pixel_format.IsValid(format)) {
7376 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7377 return error::kNoError;
7379 if (!validators_->read_pixel_type.IsValid(type)) {
7380 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7381 return error::kNoError;
7383 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7384 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7385 // format and type are acceptable enums but not guaranteed to be supported
7386 // for this framebuffer. Have to ask gl if they are valid.
7387 GLint preferred_format = 0;
7388 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7389 GLint preferred_type = 0;
7390 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7391 if (format != static_cast<GLenum>(preferred_format) ||
7392 type != static_cast<GLenum>(preferred_type)) {
7393 LOCAL_SET_GL_ERROR(
7394 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7395 "with the current read framebuffer");
7396 return error::kNoError;
7399 if (width == 0 || height == 0) {
7400 return error::kNoError;
7403 // Get the size of the current fbo or backbuffer.
7404 gfx::Size max_size = GetBoundReadFrameBufferSize();
7406 int32 max_x;
7407 int32 max_y;
7408 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7409 LOCAL_SET_GL_ERROR(
7410 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7411 return error::kNoError;
7414 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7415 return error::kNoError;
7418 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7420 ScopedResolvedFrameBufferBinder binder(this, false, true);
7422 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7423 // The user requested an out of range area. Get the results 1 line
7424 // at a time.
7425 uint32 temp_size;
7426 uint32 unpadded_row_size;
7427 uint32 padded_row_size;
7428 if (!GLES2Util::ComputeImageDataSizes(
7429 width, 2, format, type, state_.pack_alignment, &temp_size,
7430 &unpadded_row_size, &padded_row_size)) {
7431 LOCAL_SET_GL_ERROR(
7432 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7433 return error::kNoError;
7436 GLint dest_x_offset = std::max(-x, 0);
7437 uint32 dest_row_offset;
7438 if (!GLES2Util::ComputeImageDataSizes(
7439 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7440 NULL, NULL)) {
7441 LOCAL_SET_GL_ERROR(
7442 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7443 return error::kNoError;
7446 // Copy each row into the larger dest rect.
7447 int8* dst = static_cast<int8*>(pixels);
7448 GLint read_x = std::max(0, x);
7449 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7450 GLint read_width = read_end_x - read_x;
7451 for (GLint yy = 0; yy < height; ++yy) {
7452 GLint ry = y + yy;
7454 // Clear the row.
7455 memset(dst, 0, unpadded_row_size);
7457 // If the row is in range, copy it.
7458 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7459 glReadPixels(
7460 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7462 dst += padded_row_size;
7464 } else {
7465 if (async && features().use_async_readpixels) {
7466 GLuint buffer;
7467 glGenBuffersARB(1, &buffer);
7468 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7469 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7470 GLenum error = glGetError();
7471 if (error == GL_NO_ERROR) {
7472 glReadPixels(x, y, width, height, format, type, 0);
7473 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7474 new FenceCallback()));
7475 WaitForReadPixels(base::Bind(
7476 &GLES2DecoderImpl::FinishReadPixels,
7477 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7478 <GLES2DecoderImpl>(this),
7479 c, buffer));
7480 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7481 return error::kNoError;
7482 } else {
7483 // On error, unbind pack buffer and fall through to sync readpixels
7484 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7487 glReadPixels(x, y, width, height, format, type, pixels);
7489 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7490 if (error == GL_NO_ERROR) {
7491 if (result != NULL) {
7492 *result = true;
7494 FinishReadPixels(c, 0);
7497 return error::kNoError;
7500 error::Error GLES2DecoderImpl::HandlePixelStorei(
7501 uint32 immediate_data_size, const cmds::PixelStorei& c) {
7502 GLenum pname = c.pname;
7503 GLenum param = c.param;
7504 if (!validators_->pixel_store.IsValid(pname)) {
7505 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7506 return error::kNoError;
7508 switch (pname) {
7509 case GL_PACK_ALIGNMENT:
7510 case GL_UNPACK_ALIGNMENT:
7511 if (!validators_->pixel_store_alignment.IsValid(param)) {
7512 LOCAL_SET_GL_ERROR(
7513 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7514 return error::kNoError;
7516 break;
7517 case GL_UNPACK_FLIP_Y_CHROMIUM:
7518 unpack_flip_y_ = (param != 0);
7519 return error::kNoError;
7520 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7521 unpack_premultiply_alpha_ = (param != 0);
7522 return error::kNoError;
7523 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7524 unpack_unpremultiply_alpha_ = (param != 0);
7525 return error::kNoError;
7526 default:
7527 break;
7529 glPixelStorei(pname, param);
7530 switch (pname) {
7531 case GL_PACK_ALIGNMENT:
7532 state_.pack_alignment = param;
7533 break;
7534 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7535 state_.pack_reverse_row_order = (param != 0);
7536 break;
7537 case GL_UNPACK_ALIGNMENT:
7538 state_.unpack_alignment = param;
7539 break;
7540 default:
7541 // Validation should have prevented us from getting here.
7542 NOTREACHED();
7543 break;
7545 return error::kNoError;
7548 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7549 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
7550 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7552 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7554 if (!supports_post_sub_buffer_) {
7555 LOCAL_SET_GL_ERROR(
7556 GL_INVALID_OPERATION,
7557 "glPostSubBufferCHROMIUM", "command not supported by surface");
7558 return error::kNoError;
7560 bool is_tracing;
7561 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7562 &is_tracing);
7563 if (is_tracing) {
7564 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7565 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7566 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7567 is_offscreen ? offscreen_size_ : surface_->GetSize());
7569 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7570 return error::kNoError;
7571 } else {
7572 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7573 return error::kLostContext;
7577 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
7578 uint32 immediate_data_size,
7579 const cmds::ScheduleOverlayPlaneCHROMIUM& c) {
7580 NOTIMPLEMENTED() << "Overlay supported isn't finished.";
7581 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
7582 "glScheduleOverlayPlaneCHROMIUM",
7583 "function not implemented");
7584 return error::kNoError;
7587 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7588 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7589 const std::string& name_str) {
7590 if (!StringIsValidForGLES(name_str.c_str())) {
7591 LOCAL_SET_GL_ERROR(
7592 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
7593 return error::kNoError;
7595 Program* program = GetProgramInfoNotShader(
7596 client_id, "glGetAttribLocation");
7597 if (!program) {
7598 return error::kNoError;
7600 if (!program->IsValid()) {
7601 LOCAL_SET_GL_ERROR(
7602 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7603 return error::kNoError;
7605 GLint* location = GetSharedMemoryAs<GLint*>(
7606 location_shm_id, location_shm_offset, sizeof(GLint));
7607 if (!location) {
7608 return error::kOutOfBounds;
7610 // Require the client to init this incase the context is lost and we are no
7611 // longer executing commands.
7612 if (*location != -1) {
7613 return error::kGenericError;
7615 *location = program->GetAttribLocation(name_str);
7616 return error::kNoError;
7619 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
7620 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
7621 Bucket* bucket = GetBucket(c.name_bucket_id);
7622 if (!bucket) {
7623 return error::kInvalidArguments;
7625 std::string name_str;
7626 if (!bucket->GetAsString(&name_str)) {
7627 return error::kInvalidArguments;
7629 return GetAttribLocationHelper(
7630 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7633 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7634 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7635 const std::string& name_str) {
7636 if (!StringIsValidForGLES(name_str.c_str())) {
7637 LOCAL_SET_GL_ERROR(
7638 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
7639 return error::kNoError;
7641 Program* program = GetProgramInfoNotShader(
7642 client_id, "glGetUniformLocation");
7643 if (!program) {
7644 return error::kNoError;
7646 if (!program->IsValid()) {
7647 LOCAL_SET_GL_ERROR(
7648 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7649 return error::kNoError;
7651 GLint* location = GetSharedMemoryAs<GLint*>(
7652 location_shm_id, location_shm_offset, sizeof(GLint));
7653 if (!location) {
7654 return error::kOutOfBounds;
7656 // Require the client to init this incase the context is lost an we are no
7657 // longer executing commands.
7658 if (*location != -1) {
7659 return error::kGenericError;
7661 *location = program->GetUniformFakeLocation(name_str);
7662 return error::kNoError;
7665 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
7666 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
7667 Bucket* bucket = GetBucket(c.name_bucket_id);
7668 if (!bucket) {
7669 return error::kInvalidArguments;
7671 std::string name_str;
7672 if (!bucket->GetAsString(&name_str)) {
7673 return error::kInvalidArguments;
7675 return GetUniformLocationHelper(
7676 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7679 error::Error GLES2DecoderImpl::HandleGetString(
7680 uint32 immediate_data_size, const cmds::GetString& c) {
7681 GLenum name = static_cast<GLenum>(c.name);
7682 if (!validators_->string_type.IsValid(name)) {
7683 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
7684 return error::kNoError;
7686 const char* str = reinterpret_cast<const char*>(glGetString(name));
7687 std::string extensions;
7688 switch (name) {
7689 case GL_VERSION:
7690 str = "OpenGL ES 2.0 Chromium";
7691 break;
7692 case GL_SHADING_LANGUAGE_VERSION:
7693 str = "OpenGL ES GLSL ES 1.0 Chromium";
7694 break;
7695 case GL_RENDERER:
7696 case GL_VENDOR:
7697 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7698 // They are used by WEBGL_debug_renderer_info.
7699 if (!force_webgl_glsl_validation_)
7700 str = "Chromium";
7701 break;
7702 case GL_EXTENSIONS:
7704 // For WebGL contexts, strip out the OES derivatives and
7705 // EXT frag depth extensions if they have not been enabled.
7706 if (force_webgl_glsl_validation_) {
7707 extensions = feature_info_->extensions();
7708 if (!derivatives_explicitly_enabled_) {
7709 size_t offset = extensions.find(kOESDerivativeExtension);
7710 if (std::string::npos != offset) {
7711 extensions.replace(offset, arraysize(kOESDerivativeExtension),
7712 std::string());
7715 if (!frag_depth_explicitly_enabled_) {
7716 size_t offset = extensions.find(kEXTFragDepthExtension);
7717 if (std::string::npos != offset) {
7718 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
7719 std::string());
7722 if (!draw_buffers_explicitly_enabled_) {
7723 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7724 if (std::string::npos != offset) {
7725 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
7726 std::string());
7729 if (!shader_texture_lod_explicitly_enabled_) {
7730 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
7731 if (std::string::npos != offset) {
7732 extensions.replace(offset,
7733 arraysize(kEXTShaderTextureLodExtension),
7734 std::string());
7737 } else {
7738 extensions = feature_info_->extensions().c_str();
7740 if (supports_post_sub_buffer_)
7741 extensions += " GL_CHROMIUM_post_sub_buffer";
7742 str = extensions.c_str();
7744 break;
7745 default:
7746 break;
7748 Bucket* bucket = CreateBucket(c.bucket_id);
7749 bucket->SetFromString(str);
7750 return error::kNoError;
7753 error::Error GLES2DecoderImpl::HandleBufferData(
7754 uint32 immediate_data_size, const cmds::BufferData& c) {
7755 GLenum target = static_cast<GLenum>(c.target);
7756 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7757 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7758 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7759 GLenum usage = static_cast<GLenum>(c.usage);
7760 const void* data = NULL;
7761 if (data_shm_id != 0 || data_shm_offset != 0) {
7762 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7763 if (!data) {
7764 return error::kOutOfBounds;
7767 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
7768 return error::kNoError;
7771 void GLES2DecoderImpl::DoBufferSubData(
7772 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
7773 // Just delegate it. Some validation is actually done before this.
7774 buffer_manager()->ValidateAndDoBufferSubData(
7775 &state_, target, offset, size, data);
7778 bool GLES2DecoderImpl::ClearLevel(
7779 unsigned service_id,
7780 unsigned bind_target,
7781 unsigned target,
7782 int level,
7783 unsigned internal_format,
7784 unsigned format,
7785 unsigned type,
7786 int width,
7787 int height,
7788 bool is_texture_immutable) {
7789 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7790 if (feature_info_->feature_flags().angle_depth_texture &&
7791 (channels & GLES2Util::kDepth) != 0) {
7792 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7793 // on depth formats.
7794 GLuint fb = 0;
7795 glGenFramebuffersEXT(1, &fb);
7796 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7798 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7799 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7800 GL_DEPTH_ATTACHMENT;
7802 glFramebufferTexture2DEXT(
7803 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7804 // ANGLE promises a depth only attachment ok.
7805 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7806 GL_FRAMEBUFFER_COMPLETE) {
7807 return false;
7809 glClearStencil(0);
7810 state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
7811 state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
7812 glClearDepth(1.0f);
7813 state_.SetDeviceDepthMask(GL_TRUE);
7814 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
7815 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7817 RestoreClearState();
7819 glDeleteFramebuffersEXT(1, &fb);
7820 Framebuffer* framebuffer =
7821 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7822 GLuint fb_service_id =
7823 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7824 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7825 return true;
7828 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7830 uint32 size;
7831 uint32 padded_row_size;
7832 if (!GLES2Util::ComputeImageDataSizes(
7833 width, height, format, type, state_.unpack_alignment, &size,
7834 NULL, &padded_row_size)) {
7835 return false;
7838 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7840 int tile_height;
7842 if (size > kMaxZeroSize) {
7843 if (kMaxZeroSize < padded_row_size) {
7844 // That'd be an awfully large texture.
7845 return false;
7847 // We should never have a large total size with a zero row size.
7848 DCHECK_GT(padded_row_size, 0U);
7849 tile_height = kMaxZeroSize / padded_row_size;
7850 if (!GLES2Util::ComputeImageDataSizes(
7851 width, tile_height, format, type, state_.unpack_alignment, &size,
7852 NULL, NULL)) {
7853 return false;
7855 } else {
7856 tile_height = height;
7859 // Assumes the size has already been checked.
7860 scoped_ptr<char[]> zero(new char[size]);
7861 memset(zero.get(), 0, size);
7862 glBindTexture(bind_target, service_id);
7864 GLint y = 0;
7865 while (y < height) {
7866 GLint h = y + tile_height > height ? height - y : tile_height;
7867 if (is_texture_immutable || h != height) {
7868 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7869 } else {
7870 glTexImage2D(
7871 target, level, internal_format, width, h, 0, format, type,
7872 zero.get());
7874 y += tile_height;
7876 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7877 &state_, bind_target);
7878 glBindTexture(bind_target, texture ? texture->service_id() : 0);
7879 return true;
7882 namespace {
7884 const int kS3TCBlockWidth = 4;
7885 const int kS3TCBlockHeight = 4;
7886 const int kS3TCDXT1BlockSize = 8;
7887 const int kS3TCDXT3AndDXT5BlockSize = 16;
7889 bool IsValidDXTSize(GLint level, GLsizei size) {
7890 return (size == 1) ||
7891 (size == 2) || !(size % kS3TCBlockWidth);
7894 bool IsValidPVRTCSize(GLint level, GLsizei size) {
7895 // Ensure that the size is a power of two
7896 return (size & (size - 1)) == 0;
7899 } // anonymous namespace.
7901 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7902 const char* function_name,
7903 GLsizei width, GLsizei height, GLenum format, size_t size) {
7904 unsigned int bytes_required = 0;
7906 switch (format) {
7907 case GL_ATC_RGB_AMD:
7908 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7909 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7910 case GL_ETC1_RGB8_OES: {
7911 int num_blocks_across =
7912 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7913 int num_blocks_down =
7914 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7915 int num_blocks = num_blocks_across * num_blocks_down;
7916 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7917 break;
7919 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
7920 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
7921 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7922 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7923 int num_blocks_across =
7924 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7925 int num_blocks_down =
7926 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7927 int num_blocks = num_blocks_across * num_blocks_down;
7928 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7929 break;
7931 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
7932 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
7933 bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
7934 break;
7936 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
7937 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
7938 bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
7939 break;
7941 default:
7942 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7943 return false;
7946 if (size != bytes_required) {
7947 LOCAL_SET_GL_ERROR(
7948 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7949 return false;
7952 return true;
7955 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7956 const char* function_name,
7957 GLint level, GLsizei width, GLsizei height, GLenum format) {
7958 switch (format) {
7959 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7960 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7961 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7962 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7963 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
7964 LOCAL_SET_GL_ERROR(
7965 GL_INVALID_OPERATION, function_name,
7966 "width or height invalid for level");
7967 return false;
7969 return true;
7971 case GL_ATC_RGB_AMD:
7972 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
7973 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
7974 case GL_ETC1_RGB8_OES: {
7975 if (width <= 0 || height <= 0) {
7976 LOCAL_SET_GL_ERROR(
7977 GL_INVALID_OPERATION, function_name,
7978 "width or height invalid for level");
7979 return false;
7981 return true;
7983 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
7984 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
7985 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
7986 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
7987 if (!IsValidPVRTCSize(level, width) ||
7988 !IsValidPVRTCSize(level, height)) {
7989 LOCAL_SET_GL_ERROR(
7990 GL_INVALID_OPERATION, function_name,
7991 "width or height invalid for level");
7992 return false;
7994 return true;
7996 default:
7997 return false;
8001 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8002 const char* function_name,
8003 GLenum target, GLint level, GLint xoffset, GLint yoffset,
8004 GLsizei width, GLsizei height, GLenum format,
8005 Texture* texture) {
8006 if (xoffset < 0 || yoffset < 0) {
8007 LOCAL_SET_GL_ERROR(
8008 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
8009 return false;
8012 switch (format) {
8013 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8014 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8015 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8016 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8017 const int kBlockWidth = 4;
8018 const int kBlockHeight = 4;
8019 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
8020 LOCAL_SET_GL_ERROR(
8021 GL_INVALID_OPERATION, function_name,
8022 "xoffset or yoffset not multiple of 4");
8023 return false;
8025 GLsizei tex_width = 0;
8026 GLsizei tex_height = 0;
8027 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8028 width - xoffset > tex_width ||
8029 height - yoffset > tex_height) {
8030 LOCAL_SET_GL_ERROR(
8031 GL_INVALID_OPERATION, function_name, "dimensions out of range");
8032 return false;
8034 return ValidateCompressedTexDimensions(
8035 function_name, level, width, height, format);
8037 case GL_ATC_RGB_AMD:
8038 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8039 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
8040 LOCAL_SET_GL_ERROR(
8041 GL_INVALID_OPERATION, function_name,
8042 "not supported for ATC textures");
8043 return false;
8045 case GL_ETC1_RGB8_OES: {
8046 LOCAL_SET_GL_ERROR(
8047 GL_INVALID_OPERATION, function_name,
8048 "not supported for ECT1_RGB8_OES textures");
8049 return false;
8051 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8052 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8053 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8054 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8055 if ((xoffset != 0) || (yoffset != 0)) {
8056 LOCAL_SET_GL_ERROR(
8057 GL_INVALID_OPERATION, function_name,
8058 "xoffset and yoffset must be zero");
8059 return false;
8061 GLsizei tex_width = 0;
8062 GLsizei tex_height = 0;
8063 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8064 width != tex_width ||
8065 height != tex_height) {
8066 LOCAL_SET_GL_ERROR(
8067 GL_INVALID_OPERATION, function_name,
8068 "dimensions must match existing texture level dimensions");
8069 return false;
8071 return ValidateCompressedTexDimensions(
8072 function_name, level, width, height, format);
8074 default:
8075 return false;
8079 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
8080 GLenum target,
8081 GLint level,
8082 GLenum internal_format,
8083 GLsizei width,
8084 GLsizei height,
8085 GLint border,
8086 GLsizei image_size,
8087 const void* data) {
8088 // TODO(gman): Validate image_size is correct for width, height and format.
8089 if (!validators_->texture_target.IsValid(target)) {
8090 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8091 "glCompressedTexImage2D", target, "target");
8092 return error::kNoError;
8094 if (!validators_->compressed_texture_format.IsValid(
8095 internal_format)) {
8096 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8097 "glCompressedTexImage2D", internal_format, "internal_format");
8098 return error::kNoError;
8100 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8101 border != 0) {
8102 LOCAL_SET_GL_ERROR(
8103 GL_INVALID_VALUE,
8104 "glCompressedTexImage2D", "dimensions out of range");
8105 return error::kNoError;
8107 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8108 &state_, target);
8109 if (!texture_ref) {
8110 LOCAL_SET_GL_ERROR(
8111 GL_INVALID_VALUE,
8112 "glCompressedTexImage2D", "unknown texture target");
8113 return error::kNoError;
8115 Texture* texture = texture_ref->texture();
8116 if (texture->IsImmutable()) {
8117 LOCAL_SET_GL_ERROR(
8118 GL_INVALID_OPERATION,
8119 "glCompressedTexImage2D", "texture is immutable");
8120 return error::kNoError;
8123 if (!ValidateCompressedTexDimensions(
8124 "glCompressedTexImage2D", level, width, height, internal_format) ||
8125 !ValidateCompressedTexFuncData(
8126 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8127 return error::kNoError;
8130 if (!EnsureGPUMemoryAvailable(image_size)) {
8131 LOCAL_SET_GL_ERROR(
8132 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8133 return error::kNoError;
8136 if (texture->IsAttachedToFramebuffer()) {
8137 framebuffer_state_.clear_state_dirty = true;
8140 scoped_ptr<int8[]> zero;
8141 if (!data) {
8142 zero.reset(new int8[image_size]);
8143 memset(zero.get(), 0, image_size);
8144 data = zero.get();
8146 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8147 glCompressedTexImage2D(
8148 target, level, internal_format, width, height, border, image_size, data);
8149 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8150 if (error == GL_NO_ERROR) {
8151 texture_manager()->SetLevelInfo(
8152 texture_ref, target, level, internal_format,
8153 width, height, 1, border, 0, 0, true);
8155 return error::kNoError;
8158 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8159 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
8160 GLenum target = static_cast<GLenum>(c.target);
8161 GLint level = static_cast<GLint>(c.level);
8162 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8163 GLsizei width = static_cast<GLsizei>(c.width);
8164 GLsizei height = static_cast<GLsizei>(c.height);
8165 GLint border = static_cast<GLint>(c.border);
8166 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8167 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8168 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8169 const void* data = NULL;
8170 if (data_shm_id != 0 || data_shm_offset != 0) {
8171 data = GetSharedMemoryAs<const void*>(
8172 data_shm_id, data_shm_offset, image_size);
8173 if (!data) {
8174 return error::kOutOfBounds;
8177 return DoCompressedTexImage2D(
8178 target, level, internal_format, width, height, border, image_size, data);
8181 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8182 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
8183 GLenum target = static_cast<GLenum>(c.target);
8184 GLint level = static_cast<GLint>(c.level);
8185 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8186 GLsizei width = static_cast<GLsizei>(c.width);
8187 GLsizei height = static_cast<GLsizei>(c.height);
8188 GLint border = static_cast<GLint>(c.border);
8189 Bucket* bucket = GetBucket(c.bucket_id);
8190 if (!bucket) {
8191 return error::kInvalidArguments;
8193 uint32 data_size = bucket->size();
8194 GLsizei imageSize = data_size;
8195 const void* data = bucket->GetData(0, data_size);
8196 if (!data) {
8197 return error::kInvalidArguments;
8199 return DoCompressedTexImage2D(
8200 target, level, internal_format, width, height, border,
8201 imageSize, data);
8204 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8205 uint32 immediate_data_size,
8206 const cmds::CompressedTexSubImage2DBucket& c) {
8207 GLenum target = static_cast<GLenum>(c.target);
8208 GLint level = static_cast<GLint>(c.level);
8209 GLint xoffset = static_cast<GLint>(c.xoffset);
8210 GLint yoffset = static_cast<GLint>(c.yoffset);
8211 GLsizei width = static_cast<GLsizei>(c.width);
8212 GLsizei height = static_cast<GLsizei>(c.height);
8213 GLenum format = static_cast<GLenum>(c.format);
8214 Bucket* bucket = GetBucket(c.bucket_id);
8215 if (!bucket) {
8216 return error::kInvalidArguments;
8218 uint32 data_size = bucket->size();
8219 GLsizei imageSize = data_size;
8220 const void* data = bucket->GetData(0, data_size);
8221 if (!data) {
8222 return error::kInvalidArguments;
8224 if (!validators_->texture_target.IsValid(target)) {
8225 LOCAL_SET_GL_ERROR(
8226 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8227 return error::kNoError;
8229 if (!validators_->compressed_texture_format.IsValid(format)) {
8230 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8231 "glCompressedTexSubImage2D", format, "format");
8232 return error::kNoError;
8234 if (width < 0) {
8235 LOCAL_SET_GL_ERROR(
8236 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8237 return error::kNoError;
8239 if (height < 0) {
8240 LOCAL_SET_GL_ERROR(
8241 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8242 return error::kNoError;
8244 if (imageSize < 0) {
8245 LOCAL_SET_GL_ERROR(
8246 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8247 return error::kNoError;
8249 DoCompressedTexSubImage2D(
8250 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8251 return error::kNoError;
8254 error::Error GLES2DecoderImpl::HandleTexImage2D(
8255 uint32 immediate_data_size, const cmds::TexImage2D& c) {
8256 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8257 "width", c.width, "height", c.height);
8258 // Set as failed for now, but if it successed, this will be set to not failed.
8259 texture_state_.tex_image_2d_failed = true;
8260 GLenum target = static_cast<GLenum>(c.target);
8261 GLint level = static_cast<GLint>(c.level);
8262 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8263 // for internalformat.
8264 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8265 GLsizei width = static_cast<GLsizei>(c.width);
8266 GLsizei height = static_cast<GLsizei>(c.height);
8267 GLint border = static_cast<GLint>(c.border);
8268 GLenum format = static_cast<GLenum>(c.format);
8269 GLenum type = static_cast<GLenum>(c.type);
8270 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8271 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8272 uint32 pixels_size;
8273 if (!GLES2Util::ComputeImageDataSizes(
8274 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
8275 NULL)) {
8276 return error::kOutOfBounds;
8278 const void* pixels = NULL;
8279 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8280 pixels = GetSharedMemoryAs<const void*>(
8281 pixels_shm_id, pixels_shm_offset, pixels_size);
8282 if (!pixels) {
8283 return error::kOutOfBounds;
8287 TextureManager::DoTextImage2DArguments args = {
8288 target, level, internal_format, width, height, border, format, type,
8289 pixels, pixels_size};
8290 texture_manager()->ValidateAndDoTexImage2D(
8291 &texture_state_, &state_, &framebuffer_state_, args);
8292 return error::kNoError;
8295 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8296 GLenum target,
8297 GLint level,
8298 GLint xoffset,
8299 GLint yoffset,
8300 GLsizei width,
8301 GLsizei height,
8302 GLenum format,
8303 GLsizei image_size,
8304 const void * data) {
8305 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8306 &state_, target);
8307 if (!texture_ref) {
8308 LOCAL_SET_GL_ERROR(
8309 GL_INVALID_OPERATION,
8310 "glCompressedTexSubImage2D", "unknown texture for target");
8311 return;
8313 Texture* texture = texture_ref->texture();
8314 GLenum type = 0;
8315 GLenum internal_format = 0;
8316 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8317 LOCAL_SET_GL_ERROR(
8318 GL_INVALID_OPERATION,
8319 "glCompressedTexSubImage2D", "level does not exist.");
8320 return;
8322 if (internal_format != format) {
8323 LOCAL_SET_GL_ERROR(
8324 GL_INVALID_OPERATION,
8325 "glCompressedTexSubImage2D", "format does not match internal format.");
8326 return;
8328 if (!texture->ValidForTexture(
8329 target, level, xoffset, yoffset, width, height, type)) {
8330 LOCAL_SET_GL_ERROR(
8331 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8332 return;
8335 if (!ValidateCompressedTexFuncData(
8336 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8337 !ValidateCompressedTexSubDimensions(
8338 "glCompressedTexSubImage2D",
8339 target, level, xoffset, yoffset, width, height, format, texture)) {
8340 return;
8344 // Note: There is no need to deal with texture cleared tracking here
8345 // because the validation above means you can only get here if the level
8346 // is already a matching compressed format and in that case
8347 // CompressedTexImage2D already cleared the texture.
8348 glCompressedTexSubImage2D(
8349 target, level, xoffset, yoffset, width, height, format, image_size, data);
8352 static void Clip(
8353 GLint start, GLint range, GLint sourceRange,
8354 GLint* out_start, GLint* out_range) {
8355 DCHECK(out_start);
8356 DCHECK(out_range);
8357 if (start < 0) {
8358 range += start;
8359 start = 0;
8361 GLint end = start + range;
8362 if (end > sourceRange) {
8363 range -= end - sourceRange;
8365 *out_start = start;
8366 *out_range = range;
8369 void GLES2DecoderImpl::DoCopyTexImage2D(
8370 GLenum target,
8371 GLint level,
8372 GLenum internal_format,
8373 GLint x,
8374 GLint y,
8375 GLsizei width,
8376 GLsizei height,
8377 GLint border) {
8378 DCHECK(!ShouldDeferReads());
8379 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8380 &state_, target);
8381 if (!texture_ref) {
8382 LOCAL_SET_GL_ERROR(
8383 GL_INVALID_OPERATION,
8384 "glCopyTexImage2D", "unknown texture for target");
8385 return;
8387 Texture* texture = texture_ref->texture();
8388 if (texture->IsImmutable()) {
8389 LOCAL_SET_GL_ERROR(
8390 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8391 return;
8393 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8394 border != 0) {
8395 LOCAL_SET_GL_ERROR(
8396 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8397 return;
8399 if (!texture_manager()->ValidateFormatAndTypeCombination(
8400 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8401 GL_UNSIGNED_BYTE)) {
8402 return;
8405 // Check we have compatible formats.
8406 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8407 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8408 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8410 if ((channels_needed & channels_exist) != channels_needed) {
8411 LOCAL_SET_GL_ERROR(
8412 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
8413 return;
8416 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8417 LOCAL_SET_GL_ERROR(
8418 GL_INVALID_OPERATION,
8419 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8420 return;
8423 uint32 estimated_size = 0;
8424 if (!GLES2Util::ComputeImageDataSizes(
8425 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8426 &estimated_size, NULL, NULL)) {
8427 LOCAL_SET_GL_ERROR(
8428 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8429 return;
8432 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8433 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
8434 return;
8437 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8438 return;
8441 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
8442 ScopedResolvedFrameBufferBinder binder(this, false, true);
8443 gfx::Size size = GetBoundReadFrameBufferSize();
8445 if (texture->IsAttachedToFramebuffer()) {
8446 framebuffer_state_.clear_state_dirty = true;
8449 // Clip to size to source dimensions
8450 GLint copyX = 0;
8451 GLint copyY = 0;
8452 GLint copyWidth = 0;
8453 GLint copyHeight = 0;
8454 Clip(x, width, size.width(), &copyX, &copyWidth);
8455 Clip(y, height, size.height(), &copyY, &copyHeight);
8457 if (copyX != x ||
8458 copyY != y ||
8459 copyWidth != width ||
8460 copyHeight != height) {
8461 // some part was clipped so clear the texture.
8462 if (!ClearLevel(
8463 texture->service_id(), texture->target(),
8464 target, level, internal_format, internal_format, GL_UNSIGNED_BYTE,
8465 width, height, texture->IsImmutable())) {
8466 LOCAL_SET_GL_ERROR(
8467 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
8468 return;
8470 if (copyHeight > 0 && copyWidth > 0) {
8471 GLint dx = copyX - x;
8472 GLint dy = copyY - y;
8473 GLint destX = dx;
8474 GLint destY = dy;
8475 ScopedModifyPixels modify(texture_ref);
8476 glCopyTexSubImage2D(target, level,
8477 destX, destY, copyX, copyY,
8478 copyWidth, copyHeight);
8480 } else {
8481 ScopedModifyPixels modify(texture_ref);
8482 glCopyTexImage2D(target, level, internal_format,
8483 copyX, copyY, copyWidth, copyHeight, border);
8485 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
8486 if (error == GL_NO_ERROR) {
8487 texture_manager()->SetLevelInfo(
8488 texture_ref, target, level, internal_format, width, height, 1,
8489 border, internal_format, GL_UNSIGNED_BYTE, true);
8493 void GLES2DecoderImpl::DoCopyTexSubImage2D(
8494 GLenum target,
8495 GLint level,
8496 GLint xoffset,
8497 GLint yoffset,
8498 GLint x,
8499 GLint y,
8500 GLsizei width,
8501 GLsizei height) {
8502 DCHECK(!ShouldDeferReads());
8503 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8504 &state_, target);
8505 if (!texture_ref) {
8506 LOCAL_SET_GL_ERROR(
8507 GL_INVALID_OPERATION,
8508 "glCopyTexSubImage2D", "unknown texture for target");
8509 return;
8511 Texture* texture = texture_ref->texture();
8512 GLenum type = 0;
8513 GLenum format = 0;
8514 if (!texture->GetLevelType(target, level, &type, &format) ||
8515 !texture->ValidForTexture(
8516 target, level, xoffset, yoffset, width, height, type)) {
8517 LOCAL_SET_GL_ERROR(
8518 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8519 return;
8521 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8522 LOCAL_SET_GL_ERROR(
8523 GL_INVALID_OPERATION,
8524 "glCopyTexSubImage2D", "async upload pending for texture");
8525 return;
8528 // Check we have compatible formats.
8529 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8530 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8531 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8533 if (!channels_needed ||
8534 (channels_needed & channels_exist) != channels_needed) {
8535 LOCAL_SET_GL_ERROR(
8536 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8537 return;
8540 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8541 LOCAL_SET_GL_ERROR(
8542 GL_INVALID_OPERATION,
8543 "glCopySubImage2D", "can not be used with depth or stencil textures");
8544 return;
8547 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8548 return;
8551 ScopedResolvedFrameBufferBinder binder(this, false, true);
8552 gfx::Size size = GetBoundReadFrameBufferSize();
8553 GLint copyX = 0;
8554 GLint copyY = 0;
8555 GLint copyWidth = 0;
8556 GLint copyHeight = 0;
8557 Clip(x, width, size.width(), &copyX, &copyWidth);
8558 Clip(y, height, size.height(), &copyY, &copyHeight);
8560 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
8561 LOCAL_SET_GL_ERROR(
8562 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
8563 return;
8566 if (copyX != x ||
8567 copyY != y ||
8568 copyWidth != width ||
8569 copyHeight != height) {
8570 // some part was clipped so clear the sub rect.
8571 uint32 pixels_size = 0;
8572 if (!GLES2Util::ComputeImageDataSizes(
8573 width, height, format, type, state_.unpack_alignment, &pixels_size,
8574 NULL, NULL)) {
8575 LOCAL_SET_GL_ERROR(
8576 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8577 return;
8579 scoped_ptr<char[]> zero(new char[pixels_size]);
8580 memset(zero.get(), 0, pixels_size);
8581 ScopedModifyPixels modify(texture_ref);
8582 glTexSubImage2D(
8583 target, level, xoffset, yoffset, width, height,
8584 format, type, zero.get());
8587 if (copyHeight > 0 && copyWidth > 0) {
8588 GLint dx = copyX - x;
8589 GLint dy = copyY - y;
8590 GLint destX = xoffset + dx;
8591 GLint destY = yoffset + dy;
8592 ScopedModifyPixels modify(texture_ref);
8593 glCopyTexSubImage2D(target, level,
8594 destX, destY, copyX, copyY,
8595 copyWidth, copyHeight);
8599 bool GLES2DecoderImpl::ValidateTexSubImage2D(
8600 error::Error* error,
8601 const char* function_name,
8602 GLenum target,
8603 GLint level,
8604 GLint xoffset,
8605 GLint yoffset,
8606 GLsizei width,
8607 GLsizei height,
8608 GLenum format,
8609 GLenum type,
8610 const void * data) {
8611 (*error) = error::kNoError;
8612 if (!validators_->texture_target.IsValid(target)) {
8613 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8614 return false;
8616 if (width < 0) {
8617 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8618 return false;
8620 if (height < 0) {
8621 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8622 return false;
8624 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8625 &state_, target);
8626 if (!texture_ref) {
8627 LOCAL_SET_GL_ERROR(
8628 GL_INVALID_OPERATION,
8629 function_name, "unknown texture for target");
8630 return false;
8632 Texture* texture = texture_ref->texture();
8633 GLenum current_type = 0;
8634 GLenum internal_format = 0;
8635 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
8636 LOCAL_SET_GL_ERROR(
8637 GL_INVALID_OPERATION, function_name, "level does not exist.");
8638 return false;
8640 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
8641 function_name, format, type, internal_format, level)) {
8642 return false;
8644 if (type != current_type) {
8645 LOCAL_SET_GL_ERROR(
8646 GL_INVALID_OPERATION,
8647 function_name, "type does not match type of texture.");
8648 return false;
8650 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
8651 LOCAL_SET_GL_ERROR(
8652 GL_INVALID_OPERATION,
8653 function_name, "async upload pending for texture");
8654 return false;
8656 if (!texture->ValidForTexture(
8657 target, level, xoffset, yoffset, width, height, type)) {
8658 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8659 return false;
8661 if ((GLES2Util::GetChannelsForFormat(format) &
8662 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
8663 LOCAL_SET_GL_ERROR(
8664 GL_INVALID_OPERATION,
8665 function_name, "can not supply data for depth or stencil textures");
8666 return false;
8668 if (data == NULL) {
8669 (*error) = error::kOutOfBounds;
8670 return false;
8672 return true;
8675 error::Error GLES2DecoderImpl::DoTexSubImage2D(
8676 GLenum target,
8677 GLint level,
8678 GLint xoffset,
8679 GLint yoffset,
8680 GLsizei width,
8681 GLsizei height,
8682 GLenum format,
8683 GLenum type,
8684 const void * data) {
8685 error::Error error = error::kNoError;
8686 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8687 xoffset, yoffset, width, height, format, type, data)) {
8688 return error;
8690 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8691 &state_, target);
8692 Texture* texture = texture_ref->texture();
8693 GLsizei tex_width = 0;
8694 GLsizei tex_height = 0;
8695 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
8696 DCHECK(ok);
8697 if (xoffset != 0 || yoffset != 0 ||
8698 width != tex_width || height != tex_height) {
8699 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8700 target, level)) {
8701 LOCAL_SET_GL_ERROR(
8702 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8703 return error::kNoError;
8705 ScopedTextureUploadTimer timer(&texture_state_);
8706 glTexSubImage2D(
8707 target, level, xoffset, yoffset, width, height, format, type, data);
8708 return error::kNoError;
8711 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
8712 !texture->IsImmutable()) {
8713 ScopedTextureUploadTimer timer(&texture_state_);
8714 GLenum internal_format;
8715 GLenum tex_type;
8716 texture->GetLevelType(target, level, &tex_type, &internal_format);
8717 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
8718 // to look it up.
8719 glTexImage2D(
8720 target, level, internal_format, width, height, 0, format, type, data);
8721 } else {
8722 ScopedTextureUploadTimer timer(&texture_state_);
8723 glTexSubImage2D(
8724 target, level, xoffset, yoffset, width, height, format, type, data);
8726 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
8727 return error::kNoError;
8730 error::Error GLES2DecoderImpl::HandleTexSubImage2D(
8731 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
8732 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
8733 "width", c.width, "height", c.height);
8734 GLboolean internal = static_cast<GLboolean>(c.internal);
8735 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
8736 return error::kNoError;
8738 GLenum target = static_cast<GLenum>(c.target);
8739 GLint level = static_cast<GLint>(c.level);
8740 GLint xoffset = static_cast<GLint>(c.xoffset);
8741 GLint yoffset = static_cast<GLint>(c.yoffset);
8742 GLsizei width = static_cast<GLsizei>(c.width);
8743 GLsizei height = static_cast<GLsizei>(c.height);
8744 GLenum format = static_cast<GLenum>(c.format);
8745 GLenum type = static_cast<GLenum>(c.type);
8746 uint32 data_size;
8747 if (!GLES2Util::ComputeImageDataSizes(
8748 width, height, format, type, state_.unpack_alignment, &data_size,
8749 NULL, NULL)) {
8750 return error::kOutOfBounds;
8752 const void* pixels = GetSharedMemoryAs<const void*>(
8753 c.pixels_shm_id, c.pixels_shm_offset, data_size);
8754 return DoTexSubImage2D(
8755 target, level, xoffset, yoffset, width, height, format, type, pixels);
8758 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
8759 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
8760 GLuint index = static_cast<GLuint>(c.index);
8761 GLenum pname = static_cast<GLenum>(c.pname);
8762 typedef cmds::GetVertexAttribPointerv::Result Result;
8763 Result* result = GetSharedMemoryAs<Result*>(
8764 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8765 if (!result) {
8766 return error::kOutOfBounds;
8768 // Check that the client initialized the result.
8769 if (result->size != 0) {
8770 return error::kInvalidArguments;
8772 if (!validators_->vertex_pointer.IsValid(pname)) {
8773 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8774 "glGetVertexAttribPointerv", pname, "pname");
8775 return error::kNoError;
8777 if (index >= group_->max_vertex_attribs()) {
8778 LOCAL_SET_GL_ERROR(
8779 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
8780 return error::kNoError;
8782 result->SetNumResults(1);
8783 *result->GetData() =
8784 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
8785 return error::kNoError;
8788 bool GLES2DecoderImpl::GetUniformSetup(
8789 GLuint program_id, GLint fake_location,
8790 uint32 shm_id, uint32 shm_offset,
8791 error::Error* error, GLint* real_location,
8792 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8793 DCHECK(error);
8794 DCHECK(service_id);
8795 DCHECK(result_pointer);
8796 DCHECK(result_type);
8797 DCHECK(real_location);
8798 *error = error::kNoError;
8799 // Make sure we have enough room for the result on failure.
8800 SizedResult<GLint>* result;
8801 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8802 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8803 if (!result) {
8804 *error = error::kOutOfBounds;
8805 return false;
8807 *result_pointer = result;
8808 // Set the result size to 0 so the client does not have to check for success.
8809 result->SetNumResults(0);
8810 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8811 if (!program) {
8812 return false;
8814 if (!program->IsValid()) {
8815 // Program was not linked successfully. (ie, glLinkProgram)
8816 LOCAL_SET_GL_ERROR(
8817 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
8818 return false;
8820 *service_id = program->service_id();
8821 GLint array_index = -1;
8822 const Program::UniformInfo* uniform_info =
8823 program->GetUniformInfoByFakeLocation(
8824 fake_location, real_location, &array_index);
8825 if (!uniform_info) {
8826 // No such location.
8827 LOCAL_SET_GL_ERROR(
8828 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
8829 return false;
8831 GLenum type = uniform_info->type;
8832 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8833 if (size == 0) {
8834 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
8835 return false;
8837 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8838 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8839 if (!result) {
8840 *error = error::kOutOfBounds;
8841 return false;
8843 result->size = size;
8844 *result_type = type;
8845 return true;
8848 error::Error GLES2DecoderImpl::HandleGetUniformiv(
8849 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
8850 GLuint program = c.program;
8851 GLint fake_location = c.location;
8852 GLuint service_id;
8853 GLenum result_type;
8854 GLint real_location = -1;
8855 Error error;
8856 void* result;
8857 if (GetUniformSetup(
8858 program, fake_location, c.params_shm_id, c.params_shm_offset,
8859 &error, &real_location, &service_id, &result, &result_type)) {
8860 glGetUniformiv(
8861 service_id, real_location,
8862 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
8864 return error;
8867 error::Error GLES2DecoderImpl::HandleGetUniformfv(
8868 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
8869 GLuint program = c.program;
8870 GLint fake_location = c.location;
8871 GLuint service_id;
8872 GLint real_location = -1;
8873 Error error;
8874 typedef cmds::GetUniformfv::Result Result;
8875 Result* result;
8876 GLenum result_type;
8877 if (GetUniformSetup(
8878 program, fake_location, c.params_shm_id, c.params_shm_offset,
8879 &error, &real_location, &service_id,
8880 reinterpret_cast<void**>(&result), &result_type)) {
8881 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8882 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8883 GLsizei num_values = result->GetNumResults();
8884 scoped_ptr<GLint[]> temp(new GLint[num_values]);
8885 glGetUniformiv(service_id, real_location, temp.get());
8886 GLfloat* dst = result->GetData();
8887 for (GLsizei ii = 0; ii < num_values; ++ii) {
8888 dst[ii] = (temp[ii] != 0);
8890 } else {
8891 glGetUniformfv(service_id, real_location, result->GetData());
8894 return error;
8897 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
8898 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
8899 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8900 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
8901 typedef cmds::GetShaderPrecisionFormat::Result Result;
8902 Result* result = GetSharedMemoryAs<Result*>(
8903 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8904 if (!result) {
8905 return error::kOutOfBounds;
8907 // Check that the client initialized the result.
8908 if (result->success != 0) {
8909 return error::kInvalidArguments;
8911 if (!validators_->shader_type.IsValid(shader_type)) {
8912 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8913 "glGetShaderPrecisionFormat", shader_type, "shader_type");
8914 return error::kNoError;
8916 if (!validators_->shader_precision.IsValid(precision_type)) {
8917 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8918 "glGetShaderPrecisionFormat", precision_type, "precision_type");
8919 return error::kNoError;
8922 result->success = 1; // true
8924 GLint range[2] = { 0, 0 };
8925 GLint precision = 0;
8926 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
8928 result->min_range = range[0];
8929 result->max_range = range[1];
8930 result->precision = precision;
8932 return error::kNoError;
8935 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
8936 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
8937 uint32 result_size = c.result_size;
8938 GLuint program_id = static_cast<GLuint>(c.program);
8939 Program* program = GetProgramInfoNotShader(
8940 program_id, "glGetAttachedShaders");
8941 if (!program) {
8942 return error::kNoError;
8944 typedef cmds::GetAttachedShaders::Result Result;
8945 uint32 max_count = Result::ComputeMaxResults(result_size);
8946 Result* result = GetSharedMemoryAs<Result*>(
8947 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8948 if (!result) {
8949 return error::kOutOfBounds;
8951 // Check that the client initialized the result.
8952 if (result->size != 0) {
8953 return error::kInvalidArguments;
8955 GLsizei count = 0;
8956 glGetAttachedShaders(
8957 program->service_id(), max_count, &count, result->GetData());
8958 for (GLsizei ii = 0; ii < count; ++ii) {
8959 if (!shader_manager()->GetClientId(result->GetData()[ii],
8960 &result->GetData()[ii])) {
8961 NOTREACHED();
8962 return error::kGenericError;
8965 result->SetNumResults(count);
8966 return error::kNoError;
8969 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
8970 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
8971 GLuint program_id = c.program;
8972 GLuint index = c.index;
8973 uint32 name_bucket_id = c.name_bucket_id;
8974 typedef cmds::GetActiveUniform::Result Result;
8975 Result* result = GetSharedMemoryAs<Result*>(
8976 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8977 if (!result) {
8978 return error::kOutOfBounds;
8980 // Check that the client initialized the result.
8981 if (result->success != 0) {
8982 return error::kInvalidArguments;
8984 Program* program = GetProgramInfoNotShader(
8985 program_id, "glGetActiveUniform");
8986 if (!program) {
8987 return error::kNoError;
8989 const Program::UniformInfo* uniform_info =
8990 program->GetUniformInfo(index);
8991 if (!uniform_info) {
8992 LOCAL_SET_GL_ERROR(
8993 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
8994 return error::kNoError;
8996 result->success = 1; // true.
8997 result->size = uniform_info->size;
8998 result->type = uniform_info->type;
8999 Bucket* bucket = CreateBucket(name_bucket_id);
9000 bucket->SetFromString(uniform_info->name.c_str());
9001 return error::kNoError;
9004 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
9005 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
9006 GLuint program_id = c.program;
9007 GLuint index = c.index;
9008 uint32 name_bucket_id = c.name_bucket_id;
9009 typedef cmds::GetActiveAttrib::Result Result;
9010 Result* result = GetSharedMemoryAs<Result*>(
9011 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9012 if (!result) {
9013 return error::kOutOfBounds;
9015 // Check that the client initialized the result.
9016 if (result->success != 0) {
9017 return error::kInvalidArguments;
9019 Program* program = GetProgramInfoNotShader(
9020 program_id, "glGetActiveAttrib");
9021 if (!program) {
9022 return error::kNoError;
9024 const Program::VertexAttrib* attrib_info =
9025 program->GetAttribInfo(index);
9026 if (!attrib_info) {
9027 LOCAL_SET_GL_ERROR(
9028 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
9029 return error::kNoError;
9031 result->success = 1; // true.
9032 result->size = attrib_info->size;
9033 result->type = attrib_info->type;
9034 Bucket* bucket = CreateBucket(name_bucket_id);
9035 bucket->SetFromString(attrib_info->name.c_str());
9036 return error::kNoError;
9039 error::Error GLES2DecoderImpl::HandleShaderBinary(
9040 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
9041 #if 1 // No binary shader support.
9042 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
9043 return error::kNoError;
9044 #else
9045 GLsizei n = static_cast<GLsizei>(c.n);
9046 if (n < 0) {
9047 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
9048 return error::kNoError;
9050 GLsizei length = static_cast<GLsizei>(c.length);
9051 if (length < 0) {
9052 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
9053 return error::kNoError;
9055 uint32 data_size;
9056 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
9057 return error::kOutOfBounds;
9059 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
9060 c.shaders_shm_id, c.shaders_shm_offset, data_size);
9061 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
9062 const void* binary = GetSharedMemoryAs<const void*>(
9063 c.binary_shm_id, c.binary_shm_offset, length);
9064 if (shaders == NULL || binary == NULL) {
9065 return error::kOutOfBounds;
9067 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9068 for (GLsizei ii = 0; ii < n; ++ii) {
9069 Shader* shader = GetShader(shaders[ii]);
9070 if (!shader) {
9071 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
9072 return error::kNoError;
9074 service_ids[ii] = shader->service_id();
9076 // TODO(gman): call glShaderBinary
9077 return error::kNoError;
9078 #endif
9081 void GLES2DecoderImpl::DoSwapBuffers() {
9082 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
9084 int this_frame_number = frame_number_++;
9085 // TRACE_EVENT for gpu tests:
9086 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9087 TRACE_EVENT_SCOPE_THREAD,
9088 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9089 "width", (is_offscreen ? offscreen_size_.width() :
9090 surface_->GetSize().width()));
9091 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9092 "offscreen", is_offscreen,
9093 "frame", this_frame_number);
9095 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9098 bool is_tracing;
9099 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9100 &is_tracing);
9101 if (is_tracing) {
9102 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
9103 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
9104 is_offscreen ? offscreen_size_ : surface_->GetSize());
9107 // If offscreen then don't actually SwapBuffers to the display. Just copy
9108 // the rendered frame to another frame buffer.
9109 if (is_offscreen) {
9110 TRACE_EVENT2("gpu", "Offscreen",
9111 "width", offscreen_size_.width(), "height", offscreen_size_.height());
9112 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
9113 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9114 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9115 // fix this.
9116 if (workarounds().needs_offscreen_buffer_workaround) {
9117 offscreen_saved_frame_buffer_->Create();
9118 glFinish();
9121 // Allocate the offscreen saved color texture.
9122 DCHECK(offscreen_saved_color_format_);
9123 offscreen_saved_color_texture_->AllocateStorage(
9124 offscreen_size_, offscreen_saved_color_format_, false);
9126 offscreen_saved_frame_buffer_->AttachRenderTexture(
9127 offscreen_saved_color_texture_.get());
9128 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
9129 if (offscreen_saved_frame_buffer_->CheckStatus() !=
9130 GL_FRAMEBUFFER_COMPLETE) {
9131 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9132 << "because offscreen saved FBO was incomplete.";
9133 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9134 return;
9137 // Clear the offscreen color texture.
9138 // TODO(piman): Is this still necessary?
9140 ScopedFrameBufferBinder binder(this,
9141 offscreen_saved_frame_buffer_->id());
9142 glClearColor(0, 0, 0, 0);
9143 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9144 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
9145 glClear(GL_COLOR_BUFFER_BIT);
9146 RestoreClearState();
9150 UpdateParentTextureInfo();
9153 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
9154 return;
9155 ScopedGLErrorSuppressor suppressor(
9156 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9158 if (IsOffscreenBufferMultisampled()) {
9159 // For multisampled buffers, resolve the frame buffer.
9160 ScopedResolvedFrameBufferBinder binder(this, true, false);
9161 } else {
9162 ScopedFrameBufferBinder binder(this,
9163 offscreen_target_frame_buffer_->id());
9165 if (offscreen_target_buffer_preserved_) {
9166 // Copy the target frame buffer to the saved offscreen texture.
9167 offscreen_saved_color_texture_->Copy(
9168 offscreen_saved_color_texture_->size(),
9169 offscreen_saved_color_format_);
9170 } else {
9171 // Flip the textures in the parent context via the texture manager.
9172 if (!!offscreen_saved_color_texture_info_.get())
9173 offscreen_saved_color_texture_info_->texture()->
9174 SetServiceId(offscreen_target_color_texture_->id());
9176 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9177 offscreen_target_frame_buffer_->AttachRenderTexture(
9178 offscreen_target_color_texture_.get());
9181 // Ensure the side effects of the copy are visible to the parent
9182 // context. There is no need to do this for ANGLE because it uses a
9183 // single D3D device for all contexts.
9184 if (!feature_info_->feature_flags().is_angle)
9185 glFlush();
9187 } else {
9188 if (!surface_->SwapBuffers()) {
9189 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9190 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9195 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9196 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
9197 Bucket* bucket = GetBucket(c.bucket_id);
9198 if (!bucket || bucket->size() == 0) {
9199 return error::kInvalidArguments;
9201 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9202 Result* result = GetSharedMemoryAs<Result*>(
9203 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9204 if (!result) {
9205 return error::kOutOfBounds;
9207 // Check that the client initialized the result.
9208 if (*result != 0) {
9209 return error::kInvalidArguments;
9211 std::string feature_str;
9212 if (!bucket->GetAsString(&feature_str)) {
9213 return error::kInvalidArguments;
9216 // TODO(gman): make this some kind of table to function pointer thingy.
9217 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9218 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9219 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9220 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9221 // TODO(gman): decide how to remove the need for this const_cast.
9222 // I could make validators_ non const but that seems bad as this is the only
9223 // place it is needed. I could make some special friend class of validators
9224 // just to allow this to set them. That seems silly. I could refactor this
9225 // code to use the extension mechanism or the initialization attributes to
9226 // turn this feature on. Given that the only real point of this is to make
9227 // the conformance tests pass and given that there is lots of real work that
9228 // needs to be done it seems like refactoring for one to one of those
9229 // methods is a very low priority.
9230 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9231 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9232 force_webgl_glsl_validation_ = true;
9233 InitializeShaderTranslator();
9234 } else {
9235 return error::kNoError;
9238 *result = 1; // true.
9239 return error::kNoError;
9242 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9243 uint32 immediate_data_size,
9244 const cmds::GetRequestableExtensionsCHROMIUM& c) {
9245 Bucket* bucket = CreateBucket(c.bucket_id);
9246 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9247 info->Initialize(disallowed_features_);
9248 bucket->SetFromString(info->extensions().c_str());
9249 return error::kNoError;
9252 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9253 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
9254 Bucket* bucket = GetBucket(c.bucket_id);
9255 if (!bucket || bucket->size() == 0) {
9256 return error::kInvalidArguments;
9258 std::string feature_str;
9259 if (!bucket->GetAsString(&feature_str)) {
9260 return error::kInvalidArguments;
9263 bool desire_webgl_glsl_validation =
9264 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9265 bool desire_standard_derivatives = false;
9266 bool desire_frag_depth = false;
9267 bool desire_draw_buffers = false;
9268 bool desire_shader_texture_lod = false;
9269 if (force_webgl_glsl_validation_) {
9270 desire_standard_derivatives =
9271 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9272 desire_frag_depth =
9273 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9274 desire_draw_buffers =
9275 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9276 desire_shader_texture_lod =
9277 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
9280 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9281 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9282 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9283 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9284 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
9285 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
9286 frag_depth_explicitly_enabled_ |= desire_frag_depth;
9287 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
9288 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
9289 InitializeShaderTranslator();
9292 UpdateCapabilities();
9294 return error::kNoError;
9297 error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
9298 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
9299 GLuint count = c.count;
9300 uint32 pnames_size;
9301 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9302 return error::kOutOfBounds;
9304 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9305 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9306 if (pnames == NULL) {
9307 return error::kOutOfBounds;
9310 // We have to copy them since we use them twice so the client
9311 // can't change them between the time we validate them and the time we use
9312 // them.
9313 scoped_ptr<GLenum[]> enums(new GLenum[count]);
9314 memcpy(enums.get(), pnames, pnames_size);
9316 // Count up the space needed for the result.
9317 uint32 num_results = 0;
9318 for (GLuint ii = 0; ii < count; ++ii) {
9319 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9320 if (num == 0) {
9321 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9322 "glGetMultipleCHROMIUM", enums[ii], "pname");
9323 return error::kNoError;
9325 // Num will never be more than 4.
9326 DCHECK_LE(num, 4u);
9327 if (!SafeAddUint32(num_results, num, &num_results)) {
9328 return error::kOutOfBounds;
9332 uint32 result_size = 0;
9333 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9334 return error::kOutOfBounds;
9337 if (result_size != static_cast<uint32>(c.size)) {
9338 LOCAL_SET_GL_ERROR(
9339 GL_INVALID_VALUE,
9340 "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
9341 return error::kNoError;
9344 GLint* results = GetSharedMemoryAs<GLint*>(
9345 c.results_shm_id, c.results_shm_offset, result_size);
9346 if (results == NULL) {
9347 return error::kOutOfBounds;
9350 // Check the results have been cleared in case the context was lost.
9351 for (uint32 ii = 0; ii < num_results; ++ii) {
9352 if (results[ii]) {
9353 return error::kInvalidArguments;
9357 // Get each result.
9358 GLint* start = results;
9359 for (GLuint ii = 0; ii < count; ++ii) {
9360 GLsizei num_written = 0;
9361 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
9362 !GetHelper(enums[ii], results, &num_written)) {
9363 DoGetIntegerv(enums[ii], results);
9365 results += num_written;
9368 // Just to verify. Should this be a DCHECK?
9369 if (static_cast<uint32>(results - start) != num_results) {
9370 return error::kOutOfBounds;
9373 return error::kNoError;
9376 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
9377 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
9378 GLuint program_id = static_cast<GLuint>(c.program);
9379 uint32 bucket_id = c.bucket_id;
9380 Bucket* bucket = CreateBucket(bucket_id);
9381 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
9382 Program* program = NULL;
9383 program = GetProgram(program_id);
9384 if (!program || !program->IsValid()) {
9385 return error::kNoError;
9387 program->GetProgramInfo(program_manager(), bucket);
9388 return error::kNoError;
9391 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9392 switch (reset_status_) {
9393 case GL_NO_ERROR:
9394 // TODO(kbr): improve the precision of the error code in this case.
9395 // Consider delegating to context for error code if MakeCurrent fails.
9396 return error::kUnknown;
9397 case GL_GUILTY_CONTEXT_RESET_ARB:
9398 return error::kGuilty;
9399 case GL_INNOCENT_CONTEXT_RESET_ARB:
9400 return error::kInnocent;
9401 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9402 return error::kUnknown;
9405 NOTREACHED();
9406 return error::kUnknown;
9409 bool GLES2DecoderImpl::WasContextLost() {
9410 if (reset_status_ != GL_NO_ERROR) {
9411 return true;
9413 if (context_->WasAllocatedUsingRobustnessExtension()) {
9414 GLenum status = GL_NO_ERROR;
9415 if (has_robustness_extension_)
9416 status = glGetGraphicsResetStatusARB();
9417 if (status != GL_NO_ERROR) {
9418 // The graphics card was reset. Signal a lost context to the application.
9419 reset_status_ = status;
9420 reset_by_robustness_extension_ = true;
9421 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
9422 << " context lost via ARB/EXT_robustness. Reset status = "
9423 << GLES2Util::GetStringEnum(status);
9424 return true;
9427 return false;
9430 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9431 return WasContextLost() && reset_by_robustness_extension_;
9434 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9435 // Only loses the context once.
9436 if (reset_status_ != GL_NO_ERROR) {
9437 return;
9440 // Marks this context as lost.
9441 reset_status_ = reset_status;
9442 current_decoder_error_ = error::kLostContext;
9445 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9446 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9447 return error::kUnknownCommand;
9450 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9451 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9452 group_->mailbox_manager()->PullTextureUpdates();
9453 if (wait_sync_point_callback_.is_null())
9454 return error::kNoError;
9456 return wait_sync_point_callback_.Run(c.sync_point) ?
9457 error::kNoError : error::kDeferCommandUntilLater;
9460 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
9461 uint32 immediate_data_size, const cmds::DiscardBackbufferCHROMIUM& c) {
9462 if (surface_->DeferDraws())
9463 return error::kDeferCommandUntilLater;
9464 if (!surface_->SetBackbufferAllocation(false))
9465 return error::kLostContext;
9466 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
9467 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
9468 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
9469 return error::kNoError;
9472 bool GLES2DecoderImpl::GenQueriesEXTHelper(
9473 GLsizei n, const GLuint* client_ids) {
9474 for (GLsizei ii = 0; ii < n; ++ii) {
9475 if (query_manager_->GetQuery(client_ids[ii])) {
9476 return false;
9479 query_manager_->GenQueries(n, client_ids);
9480 return true;
9483 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9484 GLsizei n, const GLuint* client_ids) {
9485 for (GLsizei ii = 0; ii < n; ++ii) {
9486 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9487 if (query && !query->IsDeleted()) {
9488 ContextState::QueryMap::iterator it =
9489 state_.current_queries.find(query->target());
9490 if (it != state_.current_queries.end())
9491 state_.current_queries.erase(it);
9493 query->Destroy(true);
9495 query_manager_->RemoveQuery(client_ids[ii]);
9499 bool GLES2DecoderImpl::ProcessPendingQueries() {
9500 if (query_manager_.get() == NULL) {
9501 return false;
9503 if (!query_manager_->ProcessPendingQueries()) {
9504 current_decoder_error_ = error::kOutOfBounds;
9506 return query_manager_->HavePendingQueries();
9509 // Note that if there are no pending readpixels right now,
9510 // this function will call the callback immediately.
9511 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9512 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9513 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9514 } else {
9515 callback.Run();
9519 void GLES2DecoderImpl::ProcessPendingReadPixels() {
9520 while (!pending_readpixel_fences_.empty() &&
9521 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9522 std::vector<base::Closure> callbacks =
9523 pending_readpixel_fences_.front()->callbacks;
9524 pending_readpixel_fences_.pop();
9525 for (size_t i = 0; i < callbacks.size(); i++) {
9526 callbacks[i].Run();
9531 bool GLES2DecoderImpl::HasMoreIdleWork() {
9532 return !pending_readpixel_fences_.empty() ||
9533 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
9536 void GLES2DecoderImpl::PerformIdleWork() {
9537 ProcessPendingReadPixels();
9538 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
9539 return;
9540 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
9541 ProcessFinishedAsyncTransfers();
9544 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
9545 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
9546 GLenum target = static_cast<GLenum>(c.target);
9547 GLuint client_id = static_cast<GLuint>(c.id);
9548 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9549 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9551 switch (target) {
9552 case GL_COMMANDS_ISSUED_CHROMIUM:
9553 case GL_LATENCY_QUERY_CHROMIUM:
9554 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9555 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
9556 case GL_GET_ERROR_QUERY_CHROMIUM:
9557 break;
9558 case GL_COMMANDS_COMPLETED_CHROMIUM:
9559 if (!features().chromium_sync_query) {
9560 LOCAL_SET_GL_ERROR(
9561 GL_INVALID_OPERATION, "glBeginQueryEXT",
9562 "not enabled for commands completed queries");
9563 return error::kNoError;
9565 break;
9566 default:
9567 if (!features().occlusion_query_boolean) {
9568 LOCAL_SET_GL_ERROR(
9569 GL_INVALID_OPERATION, "glBeginQueryEXT",
9570 "not enabled for occlusion queries");
9571 return error::kNoError;
9573 break;
9576 if (state_.current_queries.find(target) != state_.current_queries.end()) {
9577 LOCAL_SET_GL_ERROR(
9578 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9579 return error::kNoError;
9582 if (client_id == 0) {
9583 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
9584 return error::kNoError;
9587 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9588 if (!query) {
9589 if (!query_manager_->IsValidQuery(client_id)) {
9590 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9591 "glBeginQueryEXT",
9592 "id not made by glGenQueriesEXT");
9593 return error::kNoError;
9595 query = query_manager_->CreateQuery(
9596 target, client_id, sync_shm_id, sync_shm_offset);
9599 if (query->target() != target) {
9600 LOCAL_SET_GL_ERROR(
9601 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9602 return error::kNoError;
9603 } else if (query->shm_id() != sync_shm_id ||
9604 query->shm_offset() != sync_shm_offset) {
9605 DLOG(ERROR) << "Shared memory used by query not the same as before";
9606 return error::kInvalidArguments;
9609 if (!query_manager_->BeginQuery(query)) {
9610 return error::kOutOfBounds;
9613 state_.current_queries[target] = query;
9614 return error::kNoError;
9617 error::Error GLES2DecoderImpl::HandleEndQueryEXT(
9618 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
9619 GLenum target = static_cast<GLenum>(c.target);
9620 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9621 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
9623 if (it == state_.current_queries.end()) {
9624 LOCAL_SET_GL_ERROR(
9625 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
9626 return error::kNoError;
9629 QueryManager::Query* query = it->second.get();
9630 if (!query_manager_->EndQuery(query, submit_count)) {
9631 return error::kOutOfBounds;
9634 query_manager_->ProcessPendingTransferQueries();
9636 state_.current_queries.erase(it);
9637 return error::kNoError;
9640 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9641 GLsizei n, const GLuint* client_ids) {
9642 for (GLsizei ii = 0; ii < n; ++ii) {
9643 if (GetVertexAttribManager(client_ids[ii])) {
9644 return false;
9648 if (!features().native_vertex_array_object) {
9649 // Emulated VAO
9650 for (GLsizei ii = 0; ii < n; ++ii) {
9651 CreateVertexAttribManager(client_ids[ii], 0, true);
9653 } else {
9654 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9656 glGenVertexArraysOES(n, service_ids.get());
9657 for (GLsizei ii = 0; ii < n; ++ii) {
9658 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
9662 return true;
9665 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9666 GLsizei n, const GLuint* client_ids) {
9667 for (GLsizei ii = 0; ii < n; ++ii) {
9668 VertexAttribManager* vao =
9669 GetVertexAttribManager(client_ids[ii]);
9670 if (vao && !vao->IsDeleted()) {
9671 if (state_.vertex_attrib_manager.get() == vao) {
9672 DoBindVertexArrayOES(0);
9674 RemoveVertexAttribManager(client_ids[ii]);
9679 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9680 VertexAttribManager* vao = NULL;
9681 if (client_id != 0) {
9682 vao = GetVertexAttribManager(client_id);
9683 if (!vao) {
9684 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9685 // only allows names that have been previously generated. As such, we do
9686 // not generate new names here.
9687 LOCAL_SET_GL_ERROR(
9688 GL_INVALID_OPERATION,
9689 "glBindVertexArrayOES", "bad vertex array id.");
9690 current_decoder_error_ = error::kNoError;
9691 return;
9693 } else {
9694 vao = state_.default_vertex_attrib_manager.get();
9697 // Only set the VAO state if it's changed
9698 if (state_.vertex_attrib_manager.get() != vao) {
9699 state_.vertex_attrib_manager = vao;
9700 if (!features().native_vertex_array_object) {
9701 EmulateVertexArrayState();
9702 } else {
9703 GLuint service_id = vao->service_id();
9704 glBindVertexArrayOES(service_id);
9709 // Used when OES_vertex_array_object isn't natively supported
9710 void GLES2DecoderImpl::EmulateVertexArrayState() {
9711 // Setup the Vertex attribute state
9712 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9713 RestoreStateForAttrib(vv, true);
9716 // Setup the element buffer
9717 Buffer* element_array_buffer =
9718 state_.vertex_attrib_manager->element_array_buffer();
9719 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9720 element_array_buffer ? element_array_buffer->service_id() : 0);
9723 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9724 const VertexAttribManager* vao =
9725 GetVertexAttribManager(client_id);
9726 return vao && vao->IsValid() && !vao->IsDeleted();
9729 #if defined(OS_MACOSX)
9730 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9731 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9732 texture_id);
9733 if (it != texture_to_io_surface_map_.end()) {
9734 // Found a previous IOSurface bound to this texture; release it.
9735 IOSurfaceRef surface = it->second;
9736 CFRelease(surface);
9737 texture_to_io_surface_map_.erase(it);
9740 #endif
9742 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9743 GLenum target, GLsizei width, GLsizei height,
9744 GLuint io_surface_id, GLuint plane) {
9745 #if defined(OS_MACOSX)
9746 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
9747 LOCAL_SET_GL_ERROR(
9748 GL_INVALID_OPERATION,
9749 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9750 return;
9753 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9754 // This might be supported in the future, and if we could require
9755 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9756 // could delete a lot of code. For now, perform strict validation so we
9757 // know what's going on.
9758 LOCAL_SET_GL_ERROR(
9759 GL_INVALID_OPERATION,
9760 "glTexImageIOSurface2DCHROMIUM",
9761 "requires TEXTURE_RECTANGLE_ARB target");
9762 return;
9765 // Default target might be conceptually valid, but disallow it to avoid
9766 // accidents.
9767 TextureRef* texture_ref =
9768 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
9769 if (!texture_ref) {
9770 LOCAL_SET_GL_ERROR(
9771 GL_INVALID_OPERATION,
9772 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
9773 return;
9776 // Look up the new IOSurface. Note that because of asynchrony
9777 // between processes this might fail; during live resizing the
9778 // plugin process might allocate and release an IOSurface before
9779 // this process gets a chance to look it up. Hold on to any old
9780 // IOSurface in this case.
9781 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
9782 if (!surface) {
9783 LOCAL_SET_GL_ERROR(
9784 GL_INVALID_OPERATION,
9785 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9786 return;
9789 // Release any IOSurface previously bound to this texture.
9790 ReleaseIOSurfaceForTexture(texture_ref->service_id());
9792 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9793 texture_to_io_surface_map_.insert(
9794 std::make_pair(texture_ref->service_id(), surface));
9796 CGLContextObj context =
9797 static_cast<CGLContextObj>(context_->GetHandle());
9799 CGLError err = CGLTexImageIOSurface2D(
9800 context,
9801 target,
9802 GL_RGBA,
9803 width,
9804 height,
9805 GL_BGRA,
9806 GL_UNSIGNED_INT_8_8_8_8_REV,
9807 surface,
9808 plane);
9810 if (err != kCGLNoError) {
9811 LOCAL_SET_GL_ERROR(
9812 GL_INVALID_OPERATION,
9813 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9814 return;
9817 texture_manager()->SetLevelInfo(
9818 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
9819 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9821 #else
9822 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9823 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9824 #endif
9827 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9828 switch (internalformat) {
9829 case GL_RGB565:
9830 return GL_RGB;
9831 case GL_RGBA4:
9832 return GL_RGBA;
9833 case GL_RGB5_A1:
9834 return GL_RGBA;
9835 case GL_RGB8_OES:
9836 return GL_RGB;
9837 case GL_RGBA8_OES:
9838 return GL_RGBA;
9839 case GL_LUMINANCE8_ALPHA8_EXT:
9840 return GL_LUMINANCE_ALPHA;
9841 case GL_LUMINANCE8_EXT:
9842 return GL_LUMINANCE;
9843 case GL_ALPHA8_EXT:
9844 return GL_ALPHA;
9845 case GL_RGBA32F_EXT:
9846 return GL_RGBA;
9847 case GL_RGB32F_EXT:
9848 return GL_RGB;
9849 case GL_ALPHA32F_EXT:
9850 return GL_ALPHA;
9851 case GL_LUMINANCE32F_EXT:
9852 return GL_LUMINANCE;
9853 case GL_LUMINANCE_ALPHA32F_EXT:
9854 return GL_LUMINANCE_ALPHA;
9855 case GL_RGBA16F_EXT:
9856 return GL_RGBA;
9857 case GL_RGB16F_EXT:
9858 return GL_RGB;
9859 case GL_ALPHA16F_EXT:
9860 return GL_ALPHA;
9861 case GL_LUMINANCE16F_EXT:
9862 return GL_LUMINANCE;
9863 case GL_LUMINANCE_ALPHA16F_EXT:
9864 return GL_LUMINANCE_ALPHA;
9865 case GL_BGRA8_EXT:
9866 return GL_BGRA_EXT;
9867 default:
9868 return GL_NONE;
9872 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9873 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
9874 GLenum internal_format, GLenum dest_type) {
9875 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
9877 TextureRef* dest_texture_ref = GetTexture(dest_id);
9878 TextureRef* source_texture_ref = GetTexture(source_id);
9880 if (!source_texture_ref || !dest_texture_ref) {
9881 LOCAL_SET_GL_ERROR(
9882 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
9883 return;
9886 if (GL_TEXTURE_2D != target) {
9887 LOCAL_SET_GL_ERROR(
9888 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
9889 return;
9892 Texture* source_texture = source_texture_ref->texture();
9893 Texture* dest_texture = dest_texture_ref->texture();
9894 if (dest_texture->target() != GL_TEXTURE_2D ||
9895 (source_texture->target() != GL_TEXTURE_2D &&
9896 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
9897 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
9898 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9899 "glCopyTextureCHROMIUM",
9900 "invalid texture target binding");
9901 return;
9904 int source_width, source_height, dest_width, dest_height;
9906 gfx::GLImage* image =
9907 source_texture->GetLevelImage(source_texture->target(), 0);
9908 if (image) {
9909 gfx::Size size = image->GetSize();
9910 source_width = size.width();
9911 source_height = size.height();
9912 if (source_width <= 0 || source_height <= 0) {
9913 LOCAL_SET_GL_ERROR(
9914 GL_INVALID_VALUE,
9915 "glCopyTextureChromium", "invalid image size");
9916 return;
9918 } else {
9919 if (!source_texture->GetLevelSize(
9920 source_texture->target(), 0, &source_width, &source_height)) {
9921 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9922 "glCopyTextureChromium",
9923 "source texture has no level 0");
9924 return;
9927 // Check that this type of texture is allowed.
9928 if (!texture_manager()->ValidForTarget(
9929 source_texture->target(), level, source_width, source_height, 1)) {
9930 LOCAL_SET_GL_ERROR(
9931 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
9932 return;
9936 // Clear the source texture if necessary.
9937 if (!texture_manager()->ClearTextureLevel(
9938 this, source_texture_ref, source_texture->target(), 0)) {
9939 LOCAL_SET_GL_ERROR(
9940 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
9941 return;
9944 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9945 // needed because it takes 10s of milliseconds to initialize.
9946 if (!copy_texture_CHROMIUM_.get()) {
9947 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9948 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
9949 copy_texture_CHROMIUM_->Initialize(this);
9950 RestoreCurrentFramebufferBindings();
9951 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
9952 return;
9955 GLenum dest_type_previous;
9956 GLenum dest_internal_format;
9957 bool dest_level_defined = dest_texture->GetLevelSize(
9958 GL_TEXTURE_2D, level, &dest_width, &dest_height);
9960 if (dest_level_defined) {
9961 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
9962 &dest_internal_format);
9965 // Resize the destination texture to the dimensions of the source texture.
9966 if (!dest_level_defined || dest_width != source_width ||
9967 dest_height != source_height ||
9968 dest_internal_format != internal_format ||
9969 dest_type_previous != dest_type) {
9970 // Ensure that the glTexImage2D succeeds.
9971 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9972 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
9973 glTexImage2D(
9974 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
9975 0, internal_format, dest_type, NULL);
9976 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
9977 if (error != GL_NO_ERROR) {
9978 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
9979 return;
9982 texture_manager()->SetLevelInfo(
9983 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
9984 source_height, 1, 0, internal_format, dest_type, true);
9985 } else {
9986 texture_manager()->SetLevelCleared(
9987 dest_texture_ref, GL_TEXTURE_2D, level, true);
9990 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
9991 ScopedModifyPixels modify(dest_texture_ref);
9993 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9994 // before presenting.
9995 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9996 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9997 // instead of using default matrix crbug.com/226218.
9998 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9999 0.0f, 1.0f, 0.0f, 0.0f,
10000 0.0f, 0.0f, 1.0f, 0.0f,
10001 0.0f, 0.0f, 0.0f, 1.0f};
10002 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
10003 this,
10004 source_texture->target(),
10005 dest_texture->target(),
10006 source_texture->service_id(),
10007 dest_texture->service_id(), level,
10008 source_width, source_height,
10009 unpack_flip_y_,
10010 unpack_premultiply_alpha_,
10011 unpack_unpremultiply_alpha_,
10012 default_matrix);
10013 } else {
10014 copy_texture_CHROMIUM_->DoCopyTexture(
10015 this,
10016 source_texture->target(),
10017 dest_texture->target(),
10018 source_texture->service_id(),
10019 dest_texture->service_id(), level,
10020 source_width, source_height,
10021 unpack_flip_y_,
10022 unpack_premultiply_alpha_,
10023 unpack_unpremultiply_alpha_);
10026 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
10029 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
10030 switch (internalformat) {
10031 case GL_RGB565:
10032 return GL_UNSIGNED_SHORT_5_6_5;
10033 case GL_RGBA4:
10034 return GL_UNSIGNED_SHORT_4_4_4_4;
10035 case GL_RGB5_A1:
10036 return GL_UNSIGNED_SHORT_5_5_5_1;
10037 case GL_RGB8_OES:
10038 return GL_UNSIGNED_BYTE;
10039 case GL_RGBA8_OES:
10040 return GL_UNSIGNED_BYTE;
10041 case GL_LUMINANCE8_ALPHA8_EXT:
10042 return GL_UNSIGNED_BYTE;
10043 case GL_LUMINANCE8_EXT:
10044 return GL_UNSIGNED_BYTE;
10045 case GL_ALPHA8_EXT:
10046 return GL_UNSIGNED_BYTE;
10047 case GL_RGBA32F_EXT:
10048 return GL_FLOAT;
10049 case GL_RGB32F_EXT:
10050 return GL_FLOAT;
10051 case GL_ALPHA32F_EXT:
10052 return GL_FLOAT;
10053 case GL_LUMINANCE32F_EXT:
10054 return GL_FLOAT;
10055 case GL_LUMINANCE_ALPHA32F_EXT:
10056 return GL_FLOAT;
10057 case GL_RGBA16F_EXT:
10058 return GL_HALF_FLOAT_OES;
10059 case GL_RGB16F_EXT:
10060 return GL_HALF_FLOAT_OES;
10061 case GL_ALPHA16F_EXT:
10062 return GL_HALF_FLOAT_OES;
10063 case GL_LUMINANCE16F_EXT:
10064 return GL_HALF_FLOAT_OES;
10065 case GL_LUMINANCE_ALPHA16F_EXT:
10066 return GL_HALF_FLOAT_OES;
10067 case GL_BGRA8_EXT:
10068 return GL_UNSIGNED_BYTE;
10069 default:
10070 return GL_NONE;
10074 void GLES2DecoderImpl::DoTexStorage2DEXT(
10075 GLenum target,
10076 GLint levels,
10077 GLenum internal_format,
10078 GLsizei width,
10079 GLsizei height) {
10080 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10081 "width", width, "height", height);
10082 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
10083 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
10084 LOCAL_SET_GL_ERROR(
10085 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
10086 return;
10088 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10089 &state_, target);
10090 if (!texture_ref) {
10091 LOCAL_SET_GL_ERROR(
10092 GL_INVALID_OPERATION,
10093 "glTexStorage2DEXT", "unknown texture for target");
10094 return;
10096 Texture* texture = texture_ref->texture();
10097 if (texture->IsAttachedToFramebuffer()) {
10098 framebuffer_state_.clear_state_dirty = true;
10100 if (texture->IsImmutable()) {
10101 LOCAL_SET_GL_ERROR(
10102 GL_INVALID_OPERATION,
10103 "glTexStorage2DEXT", "texture is immutable");
10104 return;
10107 GLenum format = ExtractFormatFromStorageFormat(internal_format);
10108 GLenum type = ExtractTypeFromStorageFormat(internal_format);
10111 GLsizei level_width = width;
10112 GLsizei level_height = height;
10113 uint32 estimated_size = 0;
10114 for (int ii = 0; ii < levels; ++ii) {
10115 uint32 level_size = 0;
10116 if (!GLES2Util::ComputeImageDataSizes(
10117 level_width, level_height, format, type, state_.unpack_alignment,
10118 &estimated_size, NULL, NULL) ||
10119 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
10120 LOCAL_SET_GL_ERROR(
10121 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
10122 return;
10124 level_width = std::max(1, level_width >> 1);
10125 level_height = std::max(1, level_height >> 1);
10127 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10128 LOCAL_SET_GL_ERROR(
10129 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
10130 return;
10134 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10135 glTexStorage2DEXT(target, levels, internal_format, width, height);
10136 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10137 if (error == GL_NO_ERROR) {
10138 GLsizei level_width = width;
10139 GLsizei level_height = height;
10140 for (int ii = 0; ii < levels; ++ii) {
10141 texture_manager()->SetLevelInfo(
10142 texture_ref, target, ii, format,
10143 level_width, level_height, 1, 0, format, type, false);
10144 level_width = std::max(1, level_width >> 1);
10145 level_height = std::max(1, level_height >> 1);
10147 texture->SetImmutable(true);
10151 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10152 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
10153 return error::kUnknownCommand;
10156 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10157 const GLbyte* data) {
10158 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10159 "context", logger_.GetLogPrefix(),
10160 "mailbox[0]", static_cast<unsigned char>(data[0]));
10162 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10163 &state_, target);
10164 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
10167 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
10168 GLenum target, const GLbyte* data) {
10169 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10170 "context", logger_.GetLogPrefix(),
10171 "mailbox[0]", static_cast<unsigned char>(data[0]));
10173 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
10174 target, data);
10177 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
10178 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
10179 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10180 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
10181 "mailbox that was not generated by "
10182 "GenMailboxCHROMIUM.";
10184 if (!texture_ref) {
10185 LOCAL_SET_GL_ERROR(
10186 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
10187 return;
10190 Texture* produced = texture_manager()->Produce(texture_ref);
10191 if (!produced) {
10192 LOCAL_SET_GL_ERROR(
10193 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
10194 return;
10197 if (produced->target() != target) {
10198 LOCAL_SET_GL_ERROR(
10199 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
10200 return;
10203 group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
10206 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10207 const GLbyte* data) {
10208 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10209 "context", logger_.GetLogPrefix(),
10210 "mailbox[0]", static_cast<unsigned char>(data[0]));
10211 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10212 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10213 "mailbox that was not generated by "
10214 "GenMailboxCHROMIUM.";
10216 scoped_refptr<TextureRef> texture_ref =
10217 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10218 if (!texture_ref.get()) {
10219 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10220 "glConsumeTextureCHROMIUM",
10221 "unknown texture for target");
10222 return;
10224 GLuint client_id = texture_ref->client_id();
10225 if (!client_id) {
10226 LOCAL_SET_GL_ERROR(
10227 GL_INVALID_OPERATION,
10228 "glConsumeTextureCHROMIUM", "unknown texture for target");
10229 return;
10231 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10232 if (!texture) {
10233 LOCAL_SET_GL_ERROR(
10234 GL_INVALID_OPERATION,
10235 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10236 return;
10238 if (texture->target() != target) {
10239 LOCAL_SET_GL_ERROR(
10240 GL_INVALID_OPERATION,
10241 "glConsumeTextureCHROMIUM", "invalid target");
10242 return;
10245 DeleteTexturesHelper(1, &client_id);
10246 texture_ref = texture_manager()->Consume(client_id, texture);
10247 glBindTexture(target, texture_ref->service_id());
10249 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10250 unit.bind_target = target;
10251 switch (target) {
10252 case GL_TEXTURE_2D:
10253 unit.bound_texture_2d = texture_ref;
10254 break;
10255 case GL_TEXTURE_CUBE_MAP:
10256 unit.bound_texture_cube_map = texture_ref;
10257 break;
10258 case GL_TEXTURE_EXTERNAL_OES:
10259 unit.bound_texture_external_oes = texture_ref;
10260 break;
10261 case GL_TEXTURE_RECTANGLE_ARB:
10262 unit.bound_texture_rectangle_arb = texture_ref;
10263 break;
10264 default:
10265 NOTREACHED(); // Validation should prevent us getting here.
10266 break;
10270 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10271 uint32_t immediate_data_size,
10272 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c) {
10273 GLenum target = static_cast<GLenum>(c.target);
10274 uint32_t data_size;
10275 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
10276 return error::kOutOfBounds;
10278 if (data_size > immediate_data_size) {
10279 return error::kOutOfBounds;
10281 const GLbyte* mailbox =
10282 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
10283 if (!validators_->texture_bind_target.IsValid(target)) {
10284 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10285 "glCreateAndConsumeTextureCHROMIUM", target, "target");
10286 return error::kNoError;
10288 if (mailbox == NULL) {
10289 return error::kOutOfBounds;
10291 uint32_t client_id = c.client_id;
10292 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
10293 return error::kNoError;
10296 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
10297 const GLbyte* data, GLuint client_id) {
10298 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
10299 "context", logger_.GetLogPrefix(),
10300 "mailbox[0]", static_cast<unsigned char>(data[0]));
10301 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10302 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
10303 "passed a mailbox that was not "
10304 "generated by GenMailboxCHROMIUM.";
10306 TextureRef* texture_ref = GetTexture(client_id);
10307 if (texture_ref) {
10308 LOCAL_SET_GL_ERROR(
10309 GL_INVALID_OPERATION,
10310 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
10311 return;
10313 Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
10314 if (!texture) {
10315 LOCAL_SET_GL_ERROR(
10316 GL_INVALID_OPERATION,
10317 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
10318 return;
10320 if (texture->target() != target) {
10321 LOCAL_SET_GL_ERROR(
10322 GL_INVALID_OPERATION,
10323 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
10324 return;
10327 IdAllocatorInterface* id_allocator =
10328 group_->GetIdAllocator(id_namespaces::kTextures);
10329 id_allocator->MarkAsUsed(client_id);
10331 texture_ref = texture_manager()->Consume(client_id, texture);
10334 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10335 GLsizei length, const GLchar* marker) {
10336 if (!marker) {
10337 marker = "";
10339 debug_marker_manager_.SetMarker(
10340 length ? std::string(marker, length) : std::string(marker));
10343 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10344 GLsizei length, const GLchar* marker) {
10345 if (!marker) {
10346 marker = "";
10348 std::string name = length ? std::string(marker, length) : std::string(marker);
10349 debug_marker_manager_.PushGroup(name);
10350 gpu_tracer_->Begin(name, kTraceGroupMarker);
10353 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10354 debug_marker_manager_.PopGroup();
10355 gpu_tracer_->End(kTraceGroupMarker);
10358 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10359 GLenum target, GLint image_id) {
10360 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10362 if (target == GL_TEXTURE_CUBE_MAP) {
10363 LOCAL_SET_GL_ERROR(
10364 GL_INVALID_ENUM,
10365 "glBindTexImage2DCHROMIUM", "invalid target");
10366 return;
10369 // Default target might be conceptually valid, but disallow it to avoid
10370 // accidents.
10371 TextureRef* texture_ref =
10372 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10373 if (!texture_ref) {
10374 LOCAL_SET_GL_ERROR(
10375 GL_INVALID_OPERATION,
10376 "glBindTexImage2DCHROMIUM", "no texture bound");
10377 return;
10380 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10381 if (!gl_image) {
10382 LOCAL_SET_GL_ERROR(
10383 GL_INVALID_OPERATION,
10384 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
10385 return;
10389 ScopedGLErrorSuppressor suppressor(
10390 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
10391 if (!gl_image->BindTexImage(target)) {
10392 LOCAL_SET_GL_ERROR(
10393 GL_INVALID_OPERATION,
10394 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10395 return;
10399 gfx::Size size = gl_image->GetSize();
10400 texture_manager()->SetLevelInfo(
10401 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
10402 GL_RGBA, GL_UNSIGNED_BYTE, true);
10403 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
10406 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10407 GLenum target, GLint image_id) {
10408 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10410 // Default target might be conceptually valid, but disallow it to avoid
10411 // accidents.
10412 TextureRef* texture_ref =
10413 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10414 if (!texture_ref) {
10415 LOCAL_SET_GL_ERROR(
10416 GL_INVALID_OPERATION,
10417 "glReleaseTexImage2DCHROMIUM", "no texture bound");
10418 return;
10421 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10422 if (!gl_image) {
10423 LOCAL_SET_GL_ERROR(
10424 GL_INVALID_OPERATION,
10425 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
10426 return;
10429 // Do nothing when image is not currently bound.
10430 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
10431 return;
10434 ScopedGLErrorSuppressor suppressor(
10435 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
10436 gl_image->ReleaseTexImage(target);
10439 texture_manager()->SetLevelInfo(
10440 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
10441 GL_RGBA, GL_UNSIGNED_BYTE, false);
10444 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10445 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10446 Bucket* bucket = GetBucket(c.bucket_id);
10447 if (!bucket || bucket->size() == 0) {
10448 return error::kInvalidArguments;
10450 std::string command_name;
10451 if (!bucket->GetAsString(&command_name)) {
10452 return error::kInvalidArguments;
10454 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10455 if (!gpu_tracer_->Begin(command_name, kTraceCHROMIUM)) {
10456 LOCAL_SET_GL_ERROR(
10457 GL_INVALID_OPERATION,
10458 "glTraceBeginCHROMIUM", "unable to create begin trace");
10459 return error::kNoError;
10461 return error::kNoError;
10464 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10465 if (gpu_tracer_->CurrentName().empty()) {
10466 LOCAL_SET_GL_ERROR(
10467 GL_INVALID_OPERATION,
10468 "glTraceEndCHROMIUM", "no trace begin found");
10469 return;
10471 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10472 gpu_tracer_->End(kTraceCHROMIUM);
10475 void GLES2DecoderImpl::DoDrawBuffersEXT(
10476 GLsizei count, const GLenum* bufs) {
10477 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10478 LOCAL_SET_GL_ERROR(
10479 GL_INVALID_VALUE,
10480 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10481 return;
10484 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10485 if (framebuffer) {
10486 for (GLsizei i = 0; i < count; ++i) {
10487 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10488 bufs[i] != GL_NONE) {
10489 LOCAL_SET_GL_ERROR(
10490 GL_INVALID_OPERATION,
10491 "glDrawBuffersEXT",
10492 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10493 return;
10496 glDrawBuffersARB(count, bufs);
10497 framebuffer->SetDrawBuffers(count, bufs);
10498 } else { // backbuffer
10499 if (count > 1 ||
10500 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10501 LOCAL_SET_GL_ERROR(
10502 GL_INVALID_OPERATION,
10503 "glDrawBuffersEXT",
10504 "more than one buffer or bufs not GL_NONE or GL_BACK");
10505 return;
10507 GLenum mapped_buf = bufs[0];
10508 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10509 bufs[0] == GL_BACK) {
10510 mapped_buf = GL_COLOR_ATTACHMENT0;
10512 glDrawBuffersARB(count, &mapped_buf);
10513 group_->set_draw_buffer(bufs[0]);
10517 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
10518 group_->LoseContexts(other);
10519 reset_status_ = current;
10520 current_decoder_error_ = error::kLostContext;
10523 bool GLES2DecoderImpl::ValidateAsyncTransfer(
10524 const char* function_name,
10525 TextureRef* texture_ref,
10526 GLenum target,
10527 GLint level,
10528 const void * data) {
10529 // We only support async uploads to 2D textures for now.
10530 if (GL_TEXTURE_2D != target) {
10531 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10532 return false;
10534 // We only support uploads to level zero for now.
10535 if (level != 0) {
10536 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10537 return false;
10539 // A transfer buffer must be bound, even for asyncTexImage2D.
10540 if (data == NULL) {
10541 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10542 return false;
10544 // We only support one async transfer in progress.
10545 if (!texture_ref ||
10546 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10547 LOCAL_SET_GL_ERROR(
10548 GL_INVALID_OPERATION,
10549 function_name, "transfer already in progress");
10550 return false;
10552 return true;
10555 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
10556 uint32 async_upload_token,
10557 uint32 sync_data_shm_id,
10558 uint32 sync_data_shm_offset) {
10559 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
10560 if (!buffer || !buffer->GetDataAddress(sync_data_shm_offset,
10561 sizeof(AsyncUploadSync)))
10562 return base::Closure();
10564 AsyncMemoryParams mem_params(buffer,
10565 sync_data_shm_offset,
10566 sizeof(AsyncUploadSync));
10568 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
10569 new AsyncUploadTokenCompletionObserver(async_upload_token));
10571 return base::Bind(
10572 &AsyncPixelTransferManager::AsyncNotifyCompletion,
10573 base::Unretained(GetAsyncPixelTransferManager()),
10574 mem_params,
10575 observer);
10578 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10579 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10580 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10581 GLenum target = static_cast<GLenum>(c.target);
10582 GLint level = static_cast<GLint>(c.level);
10583 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10584 GLsizei width = static_cast<GLsizei>(c.width);
10585 GLsizei height = static_cast<GLsizei>(c.height);
10586 GLint border = static_cast<GLint>(c.border);
10587 GLenum format = static_cast<GLenum>(c.format);
10588 GLenum type = static_cast<GLenum>(c.type);
10589 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10590 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10591 uint32 pixels_size;
10592 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
10593 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
10594 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10596 base::ScopedClosureRunner scoped_completion_callback;
10597 if (async_upload_token) {
10598 base::Closure completion_closure =
10599 AsyncUploadTokenCompletionClosure(async_upload_token,
10600 sync_data_shm_id,
10601 sync_data_shm_offset);
10602 if (completion_closure.is_null())
10603 return error::kInvalidArguments;
10605 scoped_completion_callback.Reset(completion_closure);
10608 // TODO(epenner): Move this and copies of this memory validation
10609 // into ValidateTexImage2D step.
10610 if (!GLES2Util::ComputeImageDataSizes(
10611 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10612 NULL)) {
10613 return error::kOutOfBounds;
10615 const void* pixels = NULL;
10616 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10617 pixels = GetSharedMemoryAs<const void*>(
10618 pixels_shm_id, pixels_shm_offset, pixels_size);
10619 if (!pixels) {
10620 return error::kOutOfBounds;
10624 TextureManager::DoTextImage2DArguments args = {
10625 target, level, internal_format, width, height, border, format, type,
10626 pixels, pixels_size};
10627 TextureRef* texture_ref;
10628 // All the normal glTexSubImage2D validation.
10629 if (!texture_manager()->ValidateTexImage2D(
10630 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
10631 return error::kNoError;
10634 // Extra async validation.
10635 Texture* texture = texture_ref->texture();
10636 if (!ValidateAsyncTransfer(
10637 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
10638 return error::kNoError;
10640 // Don't allow async redefinition of a textures.
10641 if (texture->IsDefined()) {
10642 LOCAL_SET_GL_ERROR(
10643 GL_INVALID_OPERATION,
10644 "glAsyncTexImage2DCHROMIUM", "already defined");
10645 return error::kNoError;
10648 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10649 LOCAL_SET_GL_ERROR(
10650 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10651 return error::kNoError;
10654 // Setup the parameters.
10655 AsyncTexImage2DParams tex_params = {
10656 target, level, static_cast<GLenum>(internal_format),
10657 width, height, border, format, type};
10658 AsyncMemoryParams mem_params(
10659 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
10661 // Set up the async state if needed, and make the texture
10662 // immutable so the async state stays valid. The level info
10663 // is set up lazily when the transfer completes.
10664 AsyncPixelTransferDelegate* delegate =
10665 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10666 tex_params);
10667 texture->SetImmutable(true);
10669 delegate->AsyncTexImage2D(
10670 tex_params,
10671 mem_params,
10672 base::Bind(&TextureManager::SetLevelInfoFromParams,
10673 // The callback is only invoked if the transfer delegate still
10674 // exists, which implies through manager->texture_ref->state
10675 // ownership that both of these pointers are valid.
10676 base::Unretained(texture_manager()),
10677 base::Unretained(texture_ref),
10678 tex_params));
10679 return error::kNoError;
10682 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10683 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10684 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10685 GLenum target = static_cast<GLenum>(c.target);
10686 GLint level = static_cast<GLint>(c.level);
10687 GLint xoffset = static_cast<GLint>(c.xoffset);
10688 GLint yoffset = static_cast<GLint>(c.yoffset);
10689 GLsizei width = static_cast<GLsizei>(c.width);
10690 GLsizei height = static_cast<GLsizei>(c.height);
10691 GLenum format = static_cast<GLenum>(c.format);
10692 GLenum type = static_cast<GLenum>(c.type);
10693 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
10694 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
10695 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10697 base::ScopedClosureRunner scoped_completion_callback;
10698 if (async_upload_token) {
10699 base::Closure completion_closure =
10700 AsyncUploadTokenCompletionClosure(async_upload_token,
10701 sync_data_shm_id,
10702 sync_data_shm_offset);
10703 if (completion_closure.is_null())
10704 return error::kInvalidArguments;
10706 scoped_completion_callback.Reset(completion_closure);
10709 // TODO(epenner): Move this and copies of this memory validation
10710 // into ValidateTexSubImage2D step.
10711 uint32 data_size;
10712 if (!GLES2Util::ComputeImageDataSizes(
10713 width, height, format, type, state_.unpack_alignment, &data_size,
10714 NULL, NULL)) {
10715 return error::kOutOfBounds;
10717 const void* pixels = GetSharedMemoryAs<const void*>(
10718 c.data_shm_id, c.data_shm_offset, data_size);
10720 // All the normal glTexSubImage2D validation.
10721 error::Error error = error::kNoError;
10722 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10723 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10724 return error;
10727 // Extra async validation.
10728 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10729 &state_, target);
10730 Texture* texture = texture_ref->texture();
10731 if (!ValidateAsyncTransfer(
10732 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
10733 return error::kNoError;
10735 // Guarantee async textures are always 'cleared' as follows:
10736 // - AsyncTexImage2D can not redefine an existing texture
10737 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10738 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10739 // - Textures become immutable after an async call.
10740 // This way we know in all cases that an async texture is always clear.
10741 if (!texture->SafeToRenderFrom()) {
10742 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10743 target, level)) {
10744 LOCAL_SET_GL_ERROR(
10745 GL_OUT_OF_MEMORY,
10746 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10747 return error::kNoError;
10751 // Setup the parameters.
10752 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
10753 width, height, format, type};
10754 AsyncMemoryParams mem_params(
10755 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
10756 AsyncPixelTransferDelegate* delegate =
10757 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10758 if (!delegate) {
10759 // TODO(epenner): We may want to enforce exclusive use
10760 // of async APIs in which case this should become an error,
10761 // (the texture should have been async defined).
10762 AsyncTexImage2DParams define_params = {target, level,
10763 0, 0, 0, 0, 0, 0};
10764 texture->GetLevelSize(target, level, &define_params.width,
10765 &define_params.height);
10766 texture->GetLevelType(target, level, &define_params.type,
10767 &define_params.internal_format);
10768 // Set up the async state if needed, and make the texture
10769 // immutable so the async state stays valid.
10770 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
10771 texture_ref, define_params);
10772 texture->SetImmutable(true);
10775 delegate->AsyncTexSubImage2D(tex_params, mem_params);
10776 return error::kNoError;
10779 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10780 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10781 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10782 GLenum target = static_cast<GLenum>(c.target);
10784 if (GL_TEXTURE_2D != target) {
10785 LOCAL_SET_GL_ERROR(
10786 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10787 return error::kNoError;
10789 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10790 &state_, target);
10791 if (!texture_ref) {
10792 LOCAL_SET_GL_ERROR(
10793 GL_INVALID_OPERATION,
10794 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10795 return error::kNoError;
10797 AsyncPixelTransferDelegate* delegate =
10798 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10799 if (!delegate) {
10800 LOCAL_SET_GL_ERROR(
10801 GL_INVALID_OPERATION,
10802 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10803 return error::kNoError;
10805 delegate->WaitForTransferCompletion();
10806 ProcessFinishedAsyncTransfers();
10807 return error::kNoError;
10810 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
10811 uint32 immediate_data_size, const cmds::WaitAllAsyncTexImage2DCHROMIUM& c) {
10812 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10814 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
10815 ProcessFinishedAsyncTransfers();
10816 return error::kNoError;
10819 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
10820 TextureRef* texture_ref) {
10821 Texture* texture = texture_ref->texture();
10822 DoDidUseTexImageIfNeeded(texture, texture->target());
10825 void GLES2DecoderImpl::OnOutOfMemoryError() {
10826 if (lose_context_when_out_of_memory_) {
10827 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
10828 LoseContext(GL_GUILTY_CONTEXT_RESET_ARB);
10832 // Include the auto-generated part of this file. We split this because it means
10833 // we can easily edit the non-auto generated parts right here in this file
10834 // instead of having to edit some template or the code generator.
10835 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10837 } // namespace gles2
10838 } // namespace gpu