JSONStringValueSerializer takes a StringPiece instead of std::string&.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob9df13b86ae72fc882276197f3733a77a829d5c3e
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/float_util.h"
21 #include "base/memory/scoped_ptr.h"
22 #include "base/numerics/safe_math.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/strings/string_split.h"
25 #include "base/trace_event/trace_event.h"
26 #include "base/trace_event/trace_event_synthetic_delay.h"
27 #include "build/build_config.h"
28 #define GLES2_GPU_SERVICE 1
29 #include "gpu/command_buffer/common/debug_marker_manager.h"
30 #include "gpu/command_buffer/common/gles2_cmd_format.h"
31 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
32 #include "gpu/command_buffer/common/id_allocator.h"
33 #include "gpu/command_buffer/common/mailbox.h"
34 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
35 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
36 #include "gpu/command_buffer/service/buffer_manager.h"
37 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
38 #include "gpu/command_buffer/service/context_group.h"
39 #include "gpu/command_buffer/service/context_state.h"
40 #include "gpu/command_buffer/service/error_state.h"
41 #include "gpu/command_buffer/service/feature_info.h"
42 #include "gpu/command_buffer/service/framebuffer_manager.h"
43 #include "gpu/command_buffer/service/gl_utils.h"
44 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
45 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
46 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
47 #include "gpu/command_buffer/service/gpu_state_tracer.h"
48 #include "gpu/command_buffer/service/gpu_switches.h"
49 #include "gpu/command_buffer/service/gpu_tracer.h"
50 #include "gpu/command_buffer/service/image_manager.h"
51 #include "gpu/command_buffer/service/mailbox_manager.h"
52 #include "gpu/command_buffer/service/memory_tracking.h"
53 #include "gpu/command_buffer/service/program_manager.h"
54 #include "gpu/command_buffer/service/query_manager.h"
55 #include "gpu/command_buffer/service/renderbuffer_manager.h"
56 #include "gpu/command_buffer/service/shader_manager.h"
57 #include "gpu/command_buffer/service/shader_translator.h"
58 #include "gpu/command_buffer/service/shader_translator_cache.h"
59 #include "gpu/command_buffer/service/texture_manager.h"
60 #include "gpu/command_buffer/service/valuebuffer_manager.h"
61 #include "gpu/command_buffer/service/vertex_array_manager.h"
62 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
63 #include "third_party/smhasher/src/City.h"
64 #include "ui/gl/gl_fence.h"
65 #include "ui/gl/gl_image.h"
66 #include "ui/gl/gl_implementation.h"
67 #include "ui/gl/gl_surface.h"
69 #if defined(OS_MACOSX)
70 #include <IOSurface/IOSurfaceAPI.h>
71 // Note that this must be included after gl_bindings.h to avoid conflicts.
72 #include <OpenGL/CGLIOSurface.h>
73 #endif
75 #if defined(OS_WIN)
76 #include "base/win/win_util.h"
77 #endif
79 namespace gpu {
80 namespace gles2 {
82 namespace {
84 static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
85 static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
86 static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
87 static const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
89 static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
90 GLint rangeMax,
91 GLint precision) {
92 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
95 static void GetShaderPrecisionFormatImpl(GLenum shader_type,
96 GLenum precision_type,
97 GLint *range, GLint *precision) {
98 switch (precision_type) {
99 case GL_LOW_INT:
100 case GL_MEDIUM_INT:
101 case GL_HIGH_INT:
102 // These values are for a 32-bit twos-complement integer format.
103 range[0] = 31;
104 range[1] = 30;
105 *precision = 0;
106 break;
107 case GL_LOW_FLOAT:
108 case GL_MEDIUM_FLOAT:
109 case GL_HIGH_FLOAT:
110 // These values are for an IEEE single-precision floating-point format.
111 range[0] = 127;
112 range[1] = 127;
113 *precision = 23;
114 break;
115 default:
116 NOTREACHED();
117 break;
120 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
121 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
122 // This function is sometimes defined even though it's really just
123 // a stub, so we need to set range and precision as if it weren't
124 // defined before calling it.
125 // On Mac OS with some GPUs, calling this generates a
126 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
127 // platforms.
128 glGetShaderPrecisionFormat(shader_type, precision_type,
129 range, precision);
131 // TODO(brianderson): Make the following official workarounds.
133 // Some drivers have bugs where they report the ranges as a negative number.
134 // Taking the absolute value here shouldn't hurt because negative numbers
135 // aren't expected anyway.
136 range[0] = abs(range[0]);
137 range[1] = abs(range[1]);
139 // If the driver reports a precision for highp float that isn't actually
140 // highp, don't pretend like it's supported because shader compilation will
141 // fail anyway.
142 if (precision_type == GL_HIGH_FLOAT &&
143 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
144 range[0] = 0;
145 range[1] = 0;
146 *precision = 0;
151 static gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
152 switch (plane_transform) {
153 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
154 return gfx::OVERLAY_TRANSFORM_NONE;
155 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
156 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
157 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
158 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
159 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
160 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
161 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
162 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
163 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
164 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
165 default:
166 return gfx::OVERLAY_TRANSFORM_INVALID;
170 } // namespace
172 class GLES2DecoderImpl;
174 // Local versions of the SET_GL_ERROR macros
175 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
176 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
177 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
178 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
179 function_name, value, label)
180 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
181 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
182 function_name, pname)
183 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
184 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
185 function_name)
186 #define LOCAL_PEEK_GL_ERROR(function_name) \
187 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
188 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
189 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
190 #define LOCAL_PERFORMANCE_WARNING(msg) \
191 PerformanceWarning(__FILE__, __LINE__, msg)
192 #define LOCAL_RENDER_WARNING(msg) \
193 RenderWarning(__FILE__, __LINE__, msg)
195 // Check that certain assumptions the code makes are true. There are places in
196 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
197 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
198 // a few others) are 32bits. If they are not 32bits the code will have to change
199 // to call those GL functions with service side memory and then copy the results
200 // to shared memory, converting the sizes.
201 static_assert(sizeof(GLint) == sizeof(uint32), // NOLINT
202 "GLint should be the same size as uint32");
203 static_assert(sizeof(GLsizei) == sizeof(uint32), // NOLINT
204 "GLsizei should be the same size as uint32");
205 static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
206 "GLfloat should be the same size as float");
208 // TODO(kbr): the use of this anonymous namespace core dumps the
209 // linker on Mac OS X 10.6 when the symbol ordering file is used
210 // namespace {
212 // Returns the address of the first byte after a struct.
213 template <typename T>
214 const void* AddressAfterStruct(const T& pod) {
215 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
218 // Returns the address of the frst byte after the struct or NULL if size >
219 // immediate_data_size.
220 template <typename RETURN_TYPE, typename COMMAND_TYPE>
221 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
222 uint32 size,
223 uint32 immediate_data_size) {
224 return (size <= immediate_data_size) ?
225 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
226 NULL;
229 // Computes the data size for certain gl commands like glUniform.
230 bool ComputeDataSize(
231 GLuint count,
232 size_t size,
233 unsigned int elements_per_unit,
234 uint32* dst) {
235 uint32 value;
236 if (!SafeMultiplyUint32(count, size, &value)) {
237 return false;
239 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
240 return false;
242 *dst = value;
243 return true;
246 // Return true if a character belongs to the ASCII subset as defined in
247 // GLSL ES 1.0 spec section 3.1.
248 static bool CharacterIsValidForGLES(unsigned char c) {
249 // Printing characters are valid except " $ ` @ \ ' DEL.
250 if (c >= 32 && c <= 126 &&
251 c != '"' &&
252 c != '$' &&
253 c != '`' &&
254 c != '@' &&
255 c != '\\' &&
256 c != '\'') {
257 return true;
259 // Horizontal tab, line feed, vertical tab, form feed, carriage return
260 // are also valid.
261 if (c >= 9 && c <= 13) {
262 return true;
265 return false;
268 static bool StringIsValidForGLES(const char* str) {
269 for (; *str; ++str) {
270 if (!CharacterIsValidForGLES(*str)) {
271 return false;
274 return true;
277 // This class prevents any GL errors that occur when it is in scope from
278 // being reported to the client.
279 class ScopedGLErrorSuppressor {
280 public:
281 explicit ScopedGLErrorSuppressor(
282 const char* function_name, ErrorState* error_state);
283 ~ScopedGLErrorSuppressor();
284 private:
285 const char* function_name_;
286 ErrorState* error_state_;
287 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
290 // Temporarily changes a decoder's bound texture and restore it when this
291 // object goes out of scope. Also temporarily switches to using active texture
292 // unit zero in case the client has changed that to something invalid.
293 class ScopedTextureBinder {
294 public:
295 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
296 ~ScopedTextureBinder();
298 private:
299 ContextState* state_;
300 GLenum target_;
301 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
304 // Temporarily changes a decoder's bound render buffer and restore it when this
305 // object goes out of scope.
306 class ScopedRenderBufferBinder {
307 public:
308 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
309 ~ScopedRenderBufferBinder();
311 private:
312 ContextState* state_;
313 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
316 // Temporarily changes a decoder's bound frame buffer and restore it when this
317 // object goes out of scope.
318 class ScopedFrameBufferBinder {
319 public:
320 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
321 ~ScopedFrameBufferBinder();
323 private:
324 GLES2DecoderImpl* decoder_;
325 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
328 // Temporarily changes a decoder's bound frame buffer to a resolved version of
329 // the multisampled offscreen render buffer if that buffer is multisampled, and,
330 // if it is bound or enforce_internal_framebuffer is true. If internal is
331 // true, the resolved framebuffer is not visible to the parent.
332 class ScopedResolvedFrameBufferBinder {
333 public:
334 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
335 bool enforce_internal_framebuffer,
336 bool internal);
337 ~ScopedResolvedFrameBufferBinder();
339 private:
340 GLES2DecoderImpl* decoder_;
341 bool resolve_and_bind_;
342 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
345 class ScopedModifyPixels {
346 public:
347 explicit ScopedModifyPixels(TextureRef* ref);
348 ~ScopedModifyPixels();
350 private:
351 TextureRef* ref_;
354 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
355 if (ref_)
356 ref_->texture()->OnWillModifyPixels();
359 ScopedModifyPixels::~ScopedModifyPixels() {
360 if (ref_)
361 ref_->texture()->OnDidModifyPixels();
364 class ScopedRenderTo {
365 public:
366 explicit ScopedRenderTo(Framebuffer* framebuffer);
367 ~ScopedRenderTo();
369 private:
370 const Framebuffer* framebuffer_;
373 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
374 : framebuffer_(framebuffer) {
375 if (framebuffer)
376 framebuffer_->OnWillRenderTo();
379 ScopedRenderTo::~ScopedRenderTo() {
380 if (framebuffer_)
381 framebuffer_->OnDidRenderTo();
384 // Encapsulates an OpenGL texture.
385 class BackTexture {
386 public:
387 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
388 ~BackTexture();
390 // Create a new render texture.
391 void Create();
393 // Set the initial size and format of a render texture or resize it.
394 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
396 // Copy the contents of the currently bound frame buffer.
397 void Copy(const gfx::Size& size, GLenum format);
399 // Destroy the render texture. This must be explicitly called before
400 // destroying this object.
401 void Destroy();
403 // Invalidate the texture. This can be used when a context is lost and it is
404 // not possible to make it current in order to free the resource.
405 void Invalidate();
407 GLuint id() const {
408 return id_;
411 gfx::Size size() const {
412 return size_;
415 private:
416 MemoryTypeTracker memory_tracker_;
417 ContextState* state_;
418 size_t bytes_allocated_;
419 GLuint id_;
420 gfx::Size size_;
421 DISALLOW_COPY_AND_ASSIGN(BackTexture);
424 // Encapsulates an OpenGL render buffer of any format.
425 class BackRenderbuffer {
426 public:
427 explicit BackRenderbuffer(
428 RenderbufferManager* renderbuffer_manager,
429 MemoryTracker* memory_tracker,
430 ContextState* state);
431 ~BackRenderbuffer();
433 // Create a new render buffer.
434 void Create();
436 // Set the initial size and format of a render buffer or resize it.
437 bool AllocateStorage(const FeatureInfo* feature_info,
438 const gfx::Size& size,
439 GLenum format,
440 GLsizei samples);
442 // Destroy the render buffer. This must be explicitly called before destroying
443 // this object.
444 void Destroy();
446 // Invalidate the render buffer. This can be used when a context is lost and
447 // it is not possible to make it current in order to free the resource.
448 void Invalidate();
450 GLuint id() const {
451 return id_;
454 private:
455 RenderbufferManager* renderbuffer_manager_;
456 MemoryTypeTracker memory_tracker_;
457 ContextState* state_;
458 size_t bytes_allocated_;
459 GLuint id_;
460 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
463 // Encapsulates an OpenGL frame buffer.
464 class BackFramebuffer {
465 public:
466 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
467 ~BackFramebuffer();
469 // Create a new frame buffer.
470 void Create();
472 // Attach a color render buffer to a frame buffer.
473 void AttachRenderTexture(BackTexture* texture);
475 // Attach a render buffer to a frame buffer. Note that this unbinds any
476 // currently bound frame buffer.
477 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
479 // Destroy the frame buffer. This must be explicitly called before destroying
480 // this object.
481 void Destroy();
483 // Invalidate the frame buffer. This can be used when a context is lost and it
484 // is not possible to make it current in order to free the resource.
485 void Invalidate();
487 // See glCheckFramebufferStatusEXT.
488 GLenum CheckStatus();
490 GLuint id() const {
491 return id_;
494 private:
495 GLES2DecoderImpl* decoder_;
496 GLuint id_;
497 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
500 struct FenceCallback {
501 explicit FenceCallback()
502 : fence(gfx::GLFence::Create()) {
503 DCHECK(fence);
505 std::vector<base::Closure> callbacks;
506 scoped_ptr<gfx::GLFence> fence;
509 class AsyncUploadTokenCompletionObserver
510 : public AsyncPixelTransferCompletionObserver {
511 public:
512 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
513 : async_upload_token_(async_upload_token) {
516 void DidComplete(const AsyncMemoryParams& mem_params) override {
517 DCHECK(mem_params.buffer().get());
518 void* data = mem_params.GetDataAddress();
519 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
520 sync->SetAsyncUploadToken(async_upload_token_);
523 private:
524 ~AsyncUploadTokenCompletionObserver() override {}
526 uint32 async_upload_token_;
528 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
531 // } // anonymous namespace.
533 // static
534 const unsigned int GLES2Decoder::kDefaultStencilMask =
535 static_cast<unsigned int>(-1);
537 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
538 uint32* service_texture_id) {
539 return false;
542 GLES2Decoder::GLES2Decoder()
543 : initialized_(false),
544 debug_(false),
545 log_commands_(false),
546 unsafe_es3_apis_enabled_(false) {
549 GLES2Decoder::~GLES2Decoder() {
552 void GLES2Decoder::BeginDecoding() {}
554 void GLES2Decoder::EndDecoding() {}
556 // This class implements GLES2Decoder so we don't have to expose all the GLES2
557 // cmd stuff to outside this class.
558 class GLES2DecoderImpl : public GLES2Decoder,
559 public FramebufferManager::TextureDetachObserver,
560 public ErrorStateClient {
561 public:
562 explicit GLES2DecoderImpl(ContextGroup* group);
563 ~GLES2DecoderImpl() override;
565 // Overridden from AsyncAPIInterface.
566 Error DoCommand(unsigned int command,
567 unsigned int arg_count,
568 const void* args) override;
570 error::Error DoCommands(unsigned int num_commands,
571 const void* buffer,
572 int num_entries,
573 int* entries_processed) override;
575 template <bool DebugImpl>
576 error::Error DoCommandsImpl(unsigned int num_commands,
577 const void* buffer,
578 int num_entries,
579 int* entries_processed);
581 // Overridden from AsyncAPIInterface.
582 const char* GetCommandName(unsigned int command_id) const override;
584 // Overridden from GLES2Decoder.
585 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
586 const scoped_refptr<gfx::GLContext>& context,
587 bool offscreen,
588 const gfx::Size& size,
589 const DisallowedFeatures& disallowed_features,
590 const std::vector<int32>& attribs) override;
591 void Destroy(bool have_context) override;
592 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
593 void ProduceFrontBuffer(const Mailbox& mailbox) override;
594 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
595 void UpdateParentTextureInfo();
596 bool MakeCurrent() override;
597 GLES2Util* GetGLES2Util() override { return &util_; }
598 gfx::GLContext* GetGLContext() override { return context_.get(); }
599 ContextGroup* GetContextGroup() override { return group_.get(); }
600 Capabilities GetCapabilities() override;
601 void RestoreState(const ContextState* prev_state) override;
603 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
604 void RestoreAllTextureUnitBindings(
605 const ContextState* prev_state) const override {
606 state_.RestoreAllTextureUnitBindings(prev_state);
608 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
609 state_.RestoreActiveTextureUnitBinding(target);
611 void RestoreBufferBindings() const override {
612 state_.RestoreBufferBindings();
614 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
615 void RestoreProgramBindings() const override {
616 state_.RestoreProgramBindings();
618 void RestoreTextureUnitBindings(unsigned unit) const override {
619 state_.RestoreTextureUnitBindings(unit, NULL);
621 void RestoreFramebufferBindings() const override;
622 void RestoreRenderbufferBindings() override;
623 void RestoreTextureState(unsigned service_id) const override;
625 void ClearAllAttributes() const override;
626 void RestoreAllAttributes() const override;
628 QueryManager* GetQueryManager() override { return query_manager_.get(); }
629 VertexArrayManager* GetVertexArrayManager() override {
630 return vertex_array_manager_.get();
632 ImageManager* GetImageManager() override { return image_manager_.get(); }
634 ValuebufferManager* GetValuebufferManager() override {
635 return valuebuffer_manager();
638 bool ProcessPendingQueries(bool did_finish) override;
640 bool HasMoreIdleWork() override;
641 void PerformIdleWork() override;
643 void WaitForReadPixels(base::Closure callback) override;
645 void SetResizeCallback(
646 const base::Callback<void(gfx::Size, float)>& callback) override;
648 Logger* GetLogger() override;
650 void BeginDecoding() override;
651 void EndDecoding() override;
653 ErrorState* GetErrorState() override;
654 const ContextState* GetContextState() override { return &state_; }
656 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
657 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
659 AsyncPixelTransferManager* GetAsyncPixelTransferManager() override;
660 void ResetAsyncPixelTransferManagerForTest() override;
661 void SetAsyncPixelTransferManagerForTest(
662 AsyncPixelTransferManager* manager) override;
663 void SetIgnoreCachedStateForTest(bool ignore) override;
664 void ProcessFinishedAsyncTransfers();
666 bool GetServiceTextureId(uint32 client_texture_id,
667 uint32* service_texture_id) override;
669 uint32 GetTextureUploadCount() override;
670 base::TimeDelta GetTotalTextureUploadTime() override;
671 base::TimeDelta GetTotalProcessingCommandsTime() override;
672 void AddProcessingCommandsTime(base::TimeDelta) override;
674 // Restores the current state to the user's settings.
675 void RestoreCurrentFramebufferBindings();
677 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
678 void ApplyDirtyState();
680 // These check the state of the currently bound framebuffer or the
681 // backbuffer if no framebuffer is bound.
682 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
683 // check with all attached and enabled color attachments.
684 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
685 bool BoundFramebufferHasDepthAttachment();
686 bool BoundFramebufferHasStencilAttachment();
688 error::ContextLostReason GetContextLostReason() override;
690 // Overridden from FramebufferManager::TextureDetachObserver:
691 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
693 // Overriden from ErrorStateClient.
694 void OnContextLostError() override;
695 void OnOutOfMemoryError() override;
697 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
698 void EnsureRenderbufferBound();
700 // Helpers to facilitate calling into compatible extensions.
701 static void RenderbufferStorageMultisampleHelper(
702 const FeatureInfo* feature_info,
703 GLenum target,
704 GLsizei samples,
705 GLenum internal_format,
706 GLsizei width,
707 GLsizei height);
709 void BlitFramebufferHelper(GLint srcX0,
710 GLint srcY0,
711 GLint srcX1,
712 GLint srcY1,
713 GLint dstX0,
714 GLint dstY0,
715 GLint dstX1,
716 GLint dstY1,
717 GLbitfield mask,
718 GLenum filter);
720 private:
721 friend class ScopedFrameBufferBinder;
722 friend class ScopedResolvedFrameBufferBinder;
723 friend class BackFramebuffer;
725 // Initialize or re-initialize the shader translator.
726 bool InitializeShaderTranslator();
728 void UpdateCapabilities();
730 // Helpers for the glGen and glDelete functions.
731 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
732 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
733 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
734 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
735 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
736 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
737 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
738 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
739 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
740 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
741 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
742 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
743 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
744 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
746 // Helper for async upload token completion notification callback.
747 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
748 uint32 sync_data_shm_id,
749 uint32 sync_data_shm_offset);
753 // Workarounds
754 void OnFboChanged() const;
755 void OnUseFramebuffer() const;
757 // TODO(gman): Cache these pointers?
758 BufferManager* buffer_manager() {
759 return group_->buffer_manager();
762 RenderbufferManager* renderbuffer_manager() {
763 return group_->renderbuffer_manager();
766 FramebufferManager* framebuffer_manager() {
767 return group_->framebuffer_manager();
770 ValuebufferManager* valuebuffer_manager() {
771 return group_->valuebuffer_manager();
774 ProgramManager* program_manager() {
775 return group_->program_manager();
778 ShaderManager* shader_manager() {
779 return group_->shader_manager();
782 ShaderTranslatorCache* shader_translator_cache() {
783 return group_->shader_translator_cache();
786 const TextureManager* texture_manager() const {
787 return group_->texture_manager();
790 TextureManager* texture_manager() {
791 return group_->texture_manager();
794 MailboxManager* mailbox_manager() {
795 return group_->mailbox_manager();
798 ImageManager* image_manager() { return image_manager_.get(); }
800 VertexArrayManager* vertex_array_manager() {
801 return vertex_array_manager_.get();
804 MemoryTracker* memory_tracker() {
805 return group_->memory_tracker();
808 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
809 MemoryTracker* tracker = memory_tracker();
810 if (tracker) {
811 return tracker->EnsureGPUMemoryAvailable(estimated_size);
813 return true;
816 bool IsOffscreenBufferMultisampled() const {
817 return offscreen_target_samples_ > 1;
820 // Creates a Texture for the given texture.
821 TextureRef* CreateTexture(
822 GLuint client_id, GLuint service_id) {
823 return texture_manager()->CreateTexture(client_id, service_id);
826 // Gets the texture info for the given texture. Returns NULL if none exists.
827 TextureRef* GetTexture(GLuint client_id) const {
828 return texture_manager()->GetTexture(client_id);
831 // Deletes the texture info for the given texture.
832 void RemoveTexture(GLuint client_id) {
833 texture_manager()->RemoveTexture(client_id);
836 // Get the size (in pixels) of the currently bound frame buffer (either FBO
837 // or regular back buffer).
838 gfx::Size GetBoundReadFrameBufferSize();
840 // Get the format of the currently bound frame buffer (either FBO or regular
841 // back buffer)
842 GLenum GetBoundReadFrameBufferTextureType();
843 GLenum GetBoundReadFrameBufferInternalFormat();
844 GLenum GetBoundDrawFrameBufferInternalFormat();
846 // Wrapper for CompressedTexImage2D commands.
847 error::Error DoCompressedTexImage2D(
848 GLenum target,
849 GLint level,
850 GLenum internal_format,
851 GLsizei width,
852 GLsizei height,
853 GLint border,
854 GLsizei image_size,
855 const void* data);
857 // Wrapper for CompressedTexSubImage2D.
858 void DoCompressedTexSubImage2D(
859 GLenum target,
860 GLint level,
861 GLint xoffset,
862 GLint yoffset,
863 GLsizei width,
864 GLsizei height,
865 GLenum format,
866 GLsizei imageSize,
867 const void * data);
869 // Wrapper for CopyTexImage2D.
870 void DoCopyTexImage2D(
871 GLenum target,
872 GLint level,
873 GLenum internal_format,
874 GLint x,
875 GLint y,
876 GLsizei width,
877 GLsizei height,
878 GLint border);
880 // Wrapper for SwapBuffers.
881 void DoSwapBuffers();
883 // Wrapper for SwapInterval.
884 void DoSwapInterval(int interval);
886 // Wrapper for CopyTexSubImage2D.
887 void DoCopyTexSubImage2D(
888 GLenum target,
889 GLint level,
890 GLint xoffset,
891 GLint yoffset,
892 GLint x,
893 GLint y,
894 GLsizei width,
895 GLsizei height);
897 // Validation for TexSubImage2D.
898 bool ValidateTexSubImage2D(
899 error::Error* error,
900 const char* function_name,
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 // Wrapper for TexSubImage2D.
912 error::Error DoTexSubImage2D(
913 GLenum target,
914 GLint level,
915 GLint xoffset,
916 GLint yoffset,
917 GLsizei width,
918 GLsizei height,
919 GLenum format,
920 GLenum type,
921 const void * data);
923 // Extra validation for async tex(Sub)Image2D.
924 bool ValidateAsyncTransfer(
925 const char* function_name,
926 TextureRef* texture_ref,
927 GLenum target,
928 GLint level,
929 const void * data);
931 // Wrapper for TexImageIOSurface2DCHROMIUM.
932 void DoTexImageIOSurface2DCHROMIUM(
933 GLenum target,
934 GLsizei width,
935 GLsizei height,
936 GLuint io_surface_id,
937 GLuint plane);
939 void DoCopyTextureCHROMIUM(
940 GLenum target,
941 GLuint source_id,
942 GLuint target_id,
943 GLint level,
944 GLenum internal_format,
945 GLenum dest_type);
947 // Wrapper for TexStorage2DEXT.
948 void DoTexStorage2DEXT(
949 GLenum target,
950 GLint levels,
951 GLenum internal_format,
952 GLsizei width,
953 GLsizei height);
955 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
956 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
957 const GLbyte* key);
958 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
959 GLenum target, const GLbyte* data);
961 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
962 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
963 GLuint client_id);
965 bool DoIsValuebufferCHROMIUM(GLuint client_id);
966 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
967 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
968 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
969 void DoUniformValueBufferCHROMIUM(GLint location,
970 GLenum target,
971 GLenum subscription);
973 void DoBindTexImage2DCHROMIUM(
974 GLenum target,
975 GLint image_id);
976 void DoReleaseTexImage2DCHROMIUM(
977 GLenum target,
978 GLint image_id);
980 void DoTraceEndCHROMIUM(void);
982 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
984 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
986 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
987 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
989 // Creates a Program for the given program.
990 Program* CreateProgram(
991 GLuint client_id, GLuint service_id) {
992 return program_manager()->CreateProgram(client_id, service_id);
995 // Gets the program info for the given program. Returns NULL if none exists.
996 Program* GetProgram(GLuint client_id) {
997 return program_manager()->GetProgram(client_id);
1000 #if defined(NDEBUG)
1001 void LogClientServiceMapping(
1002 const char* /* function_name */,
1003 GLuint /* client_id */,
1004 GLuint /* service_id */) {
1006 template<typename T>
1007 void LogClientServiceForInfo(
1008 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1010 #else
1011 void LogClientServiceMapping(
1012 const char* function_name, GLuint client_id, GLuint service_id) {
1013 if (service_logging_) {
1014 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1015 << ": client_id = " << client_id
1016 << ", service_id = " << service_id;
1019 template<typename T>
1020 void LogClientServiceForInfo(
1021 T* info, GLuint client_id, const char* function_name) {
1022 if (info) {
1023 LogClientServiceMapping(function_name, client_id, info->service_id());
1026 #endif
1028 // Gets the program info for the given program. If it's not a program
1029 // generates a GL error. Returns NULL if not program.
1030 Program* GetProgramInfoNotShader(
1031 GLuint client_id, const char* function_name) {
1032 Program* program = GetProgram(client_id);
1033 if (!program) {
1034 if (GetShader(client_id)) {
1035 LOCAL_SET_GL_ERROR(
1036 GL_INVALID_OPERATION, function_name, "shader passed for program");
1037 } else {
1038 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1041 LogClientServiceForInfo(program, client_id, function_name);
1042 return program;
1046 // Creates a Shader for the given shader.
1047 Shader* CreateShader(
1048 GLuint client_id,
1049 GLuint service_id,
1050 GLenum shader_type) {
1051 return shader_manager()->CreateShader(
1052 client_id, service_id, shader_type);
1055 // Gets the shader info for the given shader. Returns NULL if none exists.
1056 Shader* GetShader(GLuint client_id) {
1057 return shader_manager()->GetShader(client_id);
1060 // Gets the shader info for the given shader. If it's not a shader generates a
1061 // GL error. Returns NULL if not shader.
1062 Shader* GetShaderInfoNotProgram(
1063 GLuint client_id, const char* function_name) {
1064 Shader* shader = GetShader(client_id);
1065 if (!shader) {
1066 if (GetProgram(client_id)) {
1067 LOCAL_SET_GL_ERROR(
1068 GL_INVALID_OPERATION, function_name, "program passed for shader");
1069 } else {
1070 LOCAL_SET_GL_ERROR(
1071 GL_INVALID_VALUE, function_name, "unknown shader");
1074 LogClientServiceForInfo(shader, client_id, function_name);
1075 return shader;
1078 // Creates a buffer info for the given buffer.
1079 void CreateBuffer(GLuint client_id, GLuint service_id) {
1080 return buffer_manager()->CreateBuffer(client_id, service_id);
1083 // Gets the buffer info for the given buffer.
1084 Buffer* GetBuffer(GLuint client_id) {
1085 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1086 return buffer;
1089 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1090 // on glDeleteBuffers so we can make sure the user does not try to render
1091 // with deleted buffers.
1092 void RemoveBuffer(GLuint client_id);
1094 // Creates a framebuffer info for the given framebuffer.
1095 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1096 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1099 // Gets the framebuffer info for the given framebuffer.
1100 Framebuffer* GetFramebuffer(GLuint client_id) {
1101 return framebuffer_manager()->GetFramebuffer(client_id);
1104 // Removes the framebuffer info for the given framebuffer.
1105 void RemoveFramebuffer(GLuint client_id) {
1106 framebuffer_manager()->RemoveFramebuffer(client_id);
1109 // Creates a renderbuffer info for the given renderbuffer.
1110 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1111 return renderbuffer_manager()->CreateRenderbuffer(
1112 client_id, service_id);
1115 // Gets the renderbuffer info for the given renderbuffer.
1116 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1117 return renderbuffer_manager()->GetRenderbuffer(client_id);
1120 // Removes the renderbuffer info for the given renderbuffer.
1121 void RemoveRenderbuffer(GLuint client_id) {
1122 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1125 // Creates a valuebuffer info for the given valuebuffer.
1126 void CreateValuebuffer(GLuint client_id) {
1127 return valuebuffer_manager()->CreateValuebuffer(client_id);
1130 // Gets the valuebuffer info for a given valuebuffer.
1131 Valuebuffer* GetValuebuffer(GLuint client_id) {
1132 return valuebuffer_manager()->GetValuebuffer(client_id);
1135 // Removes the valuebuffer info for the given valuebuffer.
1136 void RemoveValuebuffer(GLuint client_id) {
1137 valuebuffer_manager()->RemoveValuebuffer(client_id);
1140 // Gets the vertex attrib manager for the given vertex array.
1141 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1142 VertexAttribManager* info =
1143 vertex_array_manager()->GetVertexAttribManager(client_id);
1144 return info;
1147 // Removes the vertex attrib manager for the given vertex array.
1148 void RemoveVertexAttribManager(GLuint client_id) {
1149 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1152 // Creates a vertex attrib manager for the given vertex array.
1153 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1154 GLuint client_id,
1155 GLuint service_id,
1156 bool client_visible) {
1157 return vertex_array_manager()->CreateVertexAttribManager(
1158 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1161 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1162 void DoBindUniformLocationCHROMIUM(
1163 GLuint client_id, GLint location, const char* name);
1165 error::Error GetAttribLocationHelper(
1166 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1167 const std::string& name_str);
1169 error::Error GetUniformLocationHelper(
1170 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1171 const std::string& name_str);
1173 error::Error GetFragDataLocationHelper(
1174 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1175 const std::string& name_str);
1177 // Wrapper for glShaderSource.
1178 void DoShaderSource(
1179 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1181 // Wrapper for glTransformFeedbackVaryings.
1182 void DoTransformFeedbackVaryings(
1183 GLuint client_program_id, GLsizei count, const char* const* varyings,
1184 GLenum buffer_mode);
1186 // Clear any textures used by the current program.
1187 bool ClearUnclearedTextures();
1189 // Clears any uncleared attachments attached to the given frame buffer.
1190 // Returns false if there was a generated GL error.
1191 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1193 // overridden from GLES2Decoder
1194 bool ClearLevel(unsigned service_id,
1195 unsigned bind_target,
1196 unsigned target,
1197 int level,
1198 unsigned internal_format,
1199 unsigned format,
1200 unsigned type,
1201 int width,
1202 int height,
1203 bool is_texture_immutable) override;
1205 // Restore all GL state that affects clearing.
1206 void RestoreClearState();
1208 // Remembers the state of some capabilities.
1209 // Returns: true if glEnable/glDisable should actually be called.
1210 bool SetCapabilityState(GLenum cap, bool enabled);
1212 // Check that the currently bound framebuffers are valid.
1213 // Generates GL error if not.
1214 bool CheckBoundFramebuffersValid(const char* func_name);
1216 // Check that the currently bound read framebuffer has a color image
1217 // attached. Generates GL error if not.
1218 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1220 // Check that the currently bound read framebuffer's color image
1221 // isn't the target texture of the glCopyTex{Sub}Image2D.
1222 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1224 // Check if a framebuffer meets our requirements.
1225 bool CheckFramebufferValid(
1226 Framebuffer* framebuffer,
1227 GLenum target,
1228 const char* func_name);
1230 // Check if the current valuebuffer exists and is valid. If not generates
1231 // the appropriate GL error. Returns true if the current valuebuffer is in
1232 // a usable state.
1233 bool CheckCurrentValuebuffer(const char* function_name);
1235 // Check if the current valuebuffer exists and is valiud and that the
1236 // value buffer is actually subscribed to the given subscription
1237 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1238 const char* function_name);
1240 // Check if the location can be used for the given subscription target. If not
1241 // generates the appropriate GL error. Returns true if the location is usable
1242 bool CheckSubscriptionTarget(GLint location,
1243 GLenum subscription,
1244 const char* function_name);
1246 // Checks if the current program exists and is valid. If not generates the
1247 // appropriate GL error. Returns true if the current program is in a usable
1248 // state.
1249 bool CheckCurrentProgram(const char* function_name);
1251 // Checks if the current program exists and is valid and that location is not
1252 // -1. If the current program is not valid generates the appropriate GL
1253 // error. Returns true if the current program is in a usable state and
1254 // location is not -1.
1255 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1257 // Checks if the current program samples a texture that is also the color
1258 // image of the current bound framebuffer, i.e., the source and destination
1259 // of the draw operation are the same.
1260 bool CheckDrawingFeedbackLoops();
1262 // Checks if |api_type| is valid for the given uniform
1263 // If the api type is not valid generates the appropriate GL
1264 // error. Returns true if |api_type| is valid for the uniform
1265 bool CheckUniformForApiType(const Program::UniformInfo* info,
1266 const char* function_name,
1267 Program::UniformApiType api_type);
1269 // Gets the type of a uniform for a location in the current program. Sets GL
1270 // errors if the current program is not valid. Returns true if the current
1271 // program is valid and the location exists. Adjusts count so it
1272 // does not overflow the uniform.
1273 bool PrepForSetUniformByLocation(GLint fake_location,
1274 const char* function_name,
1275 Program::UniformApiType api_type,
1276 GLint* real_location,
1277 GLenum* type,
1278 GLsizei* count);
1280 // Gets the service id for any simulated backbuffer fbo.
1281 GLuint GetBackbufferServiceId() const;
1283 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1284 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1286 // Helper for glGetVertexAttrib
1287 void GetVertexAttribHelper(
1288 const VertexAttrib* attrib, GLenum pname, GLint* param);
1290 // Wrapper for glActiveTexture
1291 void DoActiveTexture(GLenum texture_unit);
1293 // Wrapper for glAttachShader
1294 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1296 // Wrapper for glBindBuffer since we need to track the current targets.
1297 void DoBindBuffer(GLenum target, GLuint buffer);
1299 // Wrapper for glBindFramebuffer since we need to track the current targets.
1300 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1302 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1303 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1305 // Wrapper for glBindTexture since we need to track the current targets.
1306 void DoBindTexture(GLenum target, GLuint texture);
1308 // Wrapper for glBindVertexArrayOES
1309 void DoBindVertexArrayOES(GLuint array);
1310 void EmulateVertexArrayState();
1312 // Wrapper for glBlitFramebufferCHROMIUM.
1313 void DoBlitFramebufferCHROMIUM(
1314 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1315 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1316 GLbitfield mask, GLenum filter);
1318 // Wrapper for glBufferSubData.
1319 void DoBufferSubData(
1320 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1322 // Wrapper for glCheckFramebufferStatus
1323 GLenum DoCheckFramebufferStatus(GLenum target);
1325 // Wrapper for glClear
1326 error::Error DoClear(GLbitfield mask);
1328 // Wrappers for various state.
1329 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1330 void DoSampleCoverage(GLclampf value, GLboolean invert);
1332 // Wrapper for glCompileShader.
1333 void DoCompileShader(GLuint shader);
1335 // Wrapper for glDetachShader
1336 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1338 // Wrapper for glDisable
1339 void DoDisable(GLenum cap);
1341 // Wrapper for glDisableVertexAttribArray.
1342 void DoDisableVertexAttribArray(GLuint index);
1344 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1345 // attachments.
1346 void DoDiscardFramebufferEXT(GLenum target,
1347 GLsizei numAttachments,
1348 const GLenum* attachments);
1350 // Wrapper for glEnable
1351 void DoEnable(GLenum cap);
1353 // Wrapper for glEnableVertexAttribArray.
1354 void DoEnableVertexAttribArray(GLuint index);
1356 // Wrapper for glFinish.
1357 void DoFinish();
1359 // Wrapper for glFlush.
1360 void DoFlush();
1362 // Wrapper for glFramebufferRenderbufffer.
1363 void DoFramebufferRenderbuffer(
1364 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1365 GLuint renderbuffer);
1367 // Wrapper for glFramebufferTexture2D.
1368 void DoFramebufferTexture2D(
1369 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1370 GLint level);
1372 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1373 void DoFramebufferTexture2DMultisample(
1374 GLenum target, GLenum attachment, GLenum textarget,
1375 GLuint texture, GLint level, GLsizei samples);
1377 // Common implementation for both DoFramebufferTexture2D wrappers.
1378 void DoFramebufferTexture2DCommon(const char* name,
1379 GLenum target, GLenum attachment, GLenum textarget,
1380 GLuint texture, GLint level, GLsizei samples);
1382 // Wrapper for glFramebufferTextureLayer.
1383 void DoFramebufferTextureLayer(
1384 GLenum target, GLenum attachment, GLuint texture, GLint level,
1385 GLint layer);
1387 // Wrapper for glGenerateMipmap
1388 void DoGenerateMipmap(GLenum target);
1390 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1391 // to account for different pname values defined in different extension
1392 // variants.
1393 GLenum AdjustGetPname(GLenum pname);
1395 // Wrapper for DoGetBooleanv.
1396 void DoGetBooleanv(GLenum pname, GLboolean* params);
1398 // Wrapper for DoGetFloatv.
1399 void DoGetFloatv(GLenum pname, GLfloat* params);
1401 // Wrapper for glGetFramebufferAttachmentParameteriv.
1402 void DoGetFramebufferAttachmentParameteriv(
1403 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1405 // Wrapper for glGetIntegerv.
1406 void DoGetIntegerv(GLenum pname, GLint* params);
1408 // Gets the max value in a range in a buffer.
1409 GLuint DoGetMaxValueInBufferCHROMIUM(
1410 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1412 // Wrapper for glGetBufferParameteriv.
1413 void DoGetBufferParameteriv(
1414 GLenum target, GLenum pname, GLint* params);
1416 // Wrapper for glGetProgramiv.
1417 void DoGetProgramiv(
1418 GLuint program_id, GLenum pname, GLint* params);
1420 // Wrapper for glRenderbufferParameteriv.
1421 void DoGetRenderbufferParameteriv(
1422 GLenum target, GLenum pname, GLint* params);
1424 // Wrapper for glGetShaderiv
1425 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1427 // Wrappers for glGetTexParameter.
1428 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1429 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1430 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1432 // Wrappers for glGetVertexAttrib.
1433 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1434 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1436 // Wrappers for glIsXXX functions.
1437 bool DoIsEnabled(GLenum cap);
1438 bool DoIsBuffer(GLuint client_id);
1439 bool DoIsFramebuffer(GLuint client_id);
1440 bool DoIsProgram(GLuint client_id);
1441 bool DoIsRenderbuffer(GLuint client_id);
1442 bool DoIsShader(GLuint client_id);
1443 bool DoIsTexture(GLuint client_id);
1444 bool DoIsVertexArrayOES(GLuint client_id);
1446 // Wrapper for glLinkProgram
1447 void DoLinkProgram(GLuint program);
1449 // Wrapper for glRenderbufferStorage.
1450 void DoRenderbufferStorage(
1451 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1453 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1454 void DoRenderbufferStorageMultisampleCHROMIUM(
1455 GLenum target, GLsizei samples, GLenum internalformat,
1456 GLsizei width, GLsizei height);
1458 // Handler for glRenderbufferStorageMultisampleEXT
1459 // (multisampled_render_to_texture).
1460 void DoRenderbufferStorageMultisampleEXT(
1461 GLenum target, GLsizei samples, GLenum internalformat,
1462 GLsizei width, GLsizei height);
1464 // Common validation for multisample extensions.
1465 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1466 GLenum internalformat,
1467 GLsizei width,
1468 GLsizei height);
1470 // Verifies that the currently bound multisample renderbuffer is valid
1471 // Very slow! Only done on platforms with driver bugs that return invalid
1472 // buffers under memory pressure
1473 bool VerifyMultisampleRenderbufferIntegrity(
1474 GLuint renderbuffer, GLenum format);
1476 // Wrapper for glReleaseShaderCompiler.
1477 void DoReleaseShaderCompiler() { }
1479 // Wrappers for glSamplerParameter*v functions.
1480 void DoSamplerParameterfv(
1481 GLuint sampler, GLenum pname, const GLfloat* params);
1482 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1484 // Wrappers for glTexParameter functions.
1485 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1486 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1487 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1488 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1490 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1491 // spec only these 2 functions can be used to set sampler uniforms.
1492 void DoUniform1i(GLint fake_location, GLint v0);
1493 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1494 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1495 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1496 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1498 // Wrappers for glUniformfv because some drivers don't correctly accept
1499 // bool uniforms.
1500 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1501 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1502 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1503 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1505 void DoUniformMatrix2fv(
1506 GLint fake_location, GLsizei count, GLboolean transpose,
1507 const GLfloat* value);
1508 void DoUniformMatrix3fv(
1509 GLint fake_location, GLsizei count, GLboolean transpose,
1510 const GLfloat* value);
1511 void DoUniformMatrix4fv(
1512 GLint fake_location, GLsizei count, GLboolean transpose,
1513 const GLfloat* value);
1515 bool SetVertexAttribValue(
1516 const char* function_name, GLuint index, const GLfloat* value);
1518 // Wrappers for glVertexAttrib??
1519 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1520 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1521 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1522 void DoVertexAttrib4f(
1523 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1524 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1525 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1526 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1527 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1529 // Wrapper for glViewport
1530 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1532 // Wrapper for glUseProgram
1533 void DoUseProgram(GLuint program);
1535 // Wrapper for glValidateProgram.
1536 void DoValidateProgram(GLuint program_client_id);
1538 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1539 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1540 void DoPopGroupMarkerEXT(void);
1542 // Gets the number of values that will be returned by glGetXXX. Returns
1543 // false if pname is unknown.
1544 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1546 // Checks if the current program and vertex attributes are valid for drawing.
1547 bool IsDrawValid(
1548 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1549 GLsizei primcount);
1551 // Returns true if successful, simulated will be true if attrib0 was
1552 // simulated.
1553 bool SimulateAttrib0(
1554 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1555 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1557 // If an image is bound to texture, this will call Will/DidUseTexImage
1558 // if needed.
1559 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1560 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1562 // Returns false if textures were replaced.
1563 bool PrepareTexturesForRender();
1564 void RestoreStateForTextures();
1566 // Returns true if GL_FIXED attribs were simulated.
1567 bool SimulateFixedAttribs(
1568 const char* function_name,
1569 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1570 void RestoreStateForSimulatedFixedAttribs();
1572 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1573 // cases (primcount is always 1 for non-instanced).
1574 error::Error DoDrawArrays(
1575 const char* function_name,
1576 bool instanced, GLenum mode, GLint first, GLsizei count,
1577 GLsizei primcount);
1578 error::Error DoDrawElements(
1579 const char* function_name,
1580 bool instanced, GLenum mode, GLsizei count, GLenum type,
1581 int32 offset, GLsizei primcount);
1583 GLenum GetBindTargetForSamplerType(GLenum type) {
1584 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1585 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1586 switch (type) {
1587 case GL_SAMPLER_2D:
1588 return GL_TEXTURE_2D;
1589 case GL_SAMPLER_CUBE:
1590 return GL_TEXTURE_CUBE_MAP;
1591 case GL_SAMPLER_EXTERNAL_OES:
1592 return GL_TEXTURE_EXTERNAL_OES;
1593 case GL_SAMPLER_2D_RECT_ARB:
1594 return GL_TEXTURE_RECTANGLE_ARB;
1597 NOTREACHED();
1598 return 0;
1601 // Gets the framebuffer info for a particular target.
1602 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1603 Framebuffer* framebuffer = NULL;
1604 switch (target) {
1605 case GL_FRAMEBUFFER:
1606 case GL_DRAW_FRAMEBUFFER_EXT:
1607 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1608 break;
1609 case GL_READ_FRAMEBUFFER_EXT:
1610 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1611 break;
1612 default:
1613 NOTREACHED();
1614 break;
1616 return framebuffer;
1619 Renderbuffer* GetRenderbufferInfoForTarget(
1620 GLenum target) {
1621 Renderbuffer* renderbuffer = NULL;
1622 switch (target) {
1623 case GL_RENDERBUFFER:
1624 renderbuffer = state_.bound_renderbuffer.get();
1625 break;
1626 default:
1627 NOTREACHED();
1628 break;
1630 return renderbuffer;
1633 // Validates the program and location for a glGetUniform call and returns
1634 // a SizeResult setup to receive the result. Returns true if glGetUniform
1635 // should be called.
1636 bool GetUniformSetup(
1637 GLuint program, GLint fake_location,
1638 uint32 shm_id, uint32 shm_offset,
1639 error::Error* error, GLint* real_location, GLuint* service_id,
1640 void** result, GLenum* result_type);
1642 void MaybeExitOnContextLost();
1643 bool WasContextLost() override;
1644 bool WasContextLostByRobustnessExtension() override;
1645 void LoseContext(uint32 reset_status) override;
1647 #if defined(OS_MACOSX)
1648 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1649 #endif
1651 bool ValidateCompressedTexDimensions(
1652 const char* function_name,
1653 GLint level, GLsizei width, GLsizei height, GLenum format);
1654 bool ValidateCompressedTexFuncData(
1655 const char* function_name,
1656 GLsizei width, GLsizei height, GLenum format, size_t size);
1657 bool ValidateCompressedTexSubDimensions(
1658 const char* function_name,
1659 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1660 GLsizei width, GLsizei height, GLenum format,
1661 Texture* texture);
1663 void RenderWarning(const char* filename, int line, const std::string& msg);
1664 void PerformanceWarning(
1665 const char* filename, int line, const std::string& msg);
1667 const FeatureInfo::FeatureFlags& features() const {
1668 return feature_info_->feature_flags();
1671 const FeatureInfo::Workarounds& workarounds() const {
1672 return feature_info_->workarounds();
1675 bool ShouldDeferDraws() {
1676 return !offscreen_target_frame_buffer_.get() &&
1677 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1678 surface_->DeferDraws();
1681 bool ShouldDeferReads() {
1682 return !offscreen_target_frame_buffer_.get() &&
1683 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1684 surface_->DeferDraws();
1687 error::Error WillAccessBoundFramebufferForDraw() {
1688 if (ShouldDeferDraws())
1689 return error::kDeferCommandUntilLater;
1690 if (!offscreen_target_frame_buffer_.get() &&
1691 !framebuffer_state_.bound_draw_framebuffer.get() &&
1692 !surface_->SetBackbufferAllocation(true))
1693 return error::kLostContext;
1694 return error::kNoError;
1697 error::Error WillAccessBoundFramebufferForRead() {
1698 if (ShouldDeferReads())
1699 return error::kDeferCommandUntilLater;
1700 if (!offscreen_target_frame_buffer_.get() &&
1701 !framebuffer_state_.bound_read_framebuffer.get() &&
1702 !surface_->SetBackbufferAllocation(true))
1703 return error::kLostContext;
1704 return error::kNoError;
1707 // Set remaining commands to process to 0 to force DoCommands to return
1708 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1709 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1711 void ProcessPendingReadPixels();
1712 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1714 // Generate a member function prototype for each command in an automated and
1715 // typesafe way.
1716 #define GLES2_CMD_OP(name) \
1717 Error Handle##name(uint32 immediate_data_size, const void* data);
1719 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1721 #undef GLES2_CMD_OP
1723 // The GL context this decoder renders to on behalf of the client.
1724 scoped_refptr<gfx::GLSurface> surface_;
1725 scoped_refptr<gfx::GLContext> context_;
1727 // The ContextGroup for this decoder uses to track resources.
1728 scoped_refptr<ContextGroup> group_;
1730 DebugMarkerManager debug_marker_manager_;
1731 Logger logger_;
1733 // All the state for this context.
1734 ContextState state_;
1736 // Current width and height of the offscreen frame buffer.
1737 gfx::Size offscreen_size_;
1739 // Util to help with GL.
1740 GLES2Util util_;
1742 // unpack flip y as last set by glPixelStorei
1743 bool unpack_flip_y_;
1745 // unpack (un)premultiply alpha as last set by glPixelStorei
1746 bool unpack_premultiply_alpha_;
1747 bool unpack_unpremultiply_alpha_;
1749 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1750 GLuint attrib_0_buffer_id_;
1752 // The value currently in attrib_0.
1753 Vec4 attrib_0_value_;
1755 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1756 bool attrib_0_buffer_matches_value_;
1758 // The size of attrib 0.
1759 GLsizei attrib_0_size_;
1761 // The buffer used to simulate GL_FIXED attribs.
1762 GLuint fixed_attrib_buffer_id_;
1764 // The size of fiixed attrib buffer.
1765 GLsizei fixed_attrib_buffer_size_;
1767 // The offscreen frame buffer that the client renders to. With EGL, the
1768 // depth and stencil buffers are separate. With regular GL there is a single
1769 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1770 // offscreen_target_stencil_render_buffer_ is unused.
1771 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1772 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1773 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1774 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1775 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1776 GLenum offscreen_target_color_format_;
1777 GLenum offscreen_target_depth_format_;
1778 GLenum offscreen_target_stencil_format_;
1779 GLsizei offscreen_target_samples_;
1780 GLboolean offscreen_target_buffer_preserved_;
1782 // The copy that is saved when SwapBuffers is called.
1783 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1784 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1785 scoped_refptr<TextureRef>
1786 offscreen_saved_color_texture_info_;
1788 // The copy that is used as the destination for multi-sample resolves.
1789 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1790 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1791 GLenum offscreen_saved_color_format_;
1793 scoped_ptr<QueryManager> query_manager_;
1795 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1797 scoped_ptr<ImageManager> image_manager_;
1799 base::Callback<void(gfx::Size, float)> resize_callback_;
1801 WaitSyncPointCallback wait_sync_point_callback_;
1803 ShaderCacheCallback shader_cache_callback_;
1805 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1807 // The format of the back buffer_
1808 GLenum back_buffer_color_format_;
1809 bool back_buffer_has_depth_;
1810 bool back_buffer_has_stencil_;
1812 bool surfaceless_;
1814 // Backbuffer attachments that are currently undefined.
1815 uint32 backbuffer_needs_clear_bits_;
1817 // The current decoder error communicates the decoder error through command
1818 // processing functions that do not return the error value. Should be set only
1819 // if not returning an error.
1820 error::Error current_decoder_error_;
1822 bool use_shader_translator_;
1823 scoped_refptr<ShaderTranslator> vertex_translator_;
1824 scoped_refptr<ShaderTranslator> fragment_translator_;
1826 DisallowedFeatures disallowed_features_;
1828 // Cached from ContextGroup
1829 const Validators* validators_;
1830 scoped_refptr<FeatureInfo> feature_info_;
1832 int frame_number_;
1834 // Number of commands remaining to be processed in DoCommands().
1835 int commands_to_process_;
1837 bool has_robustness_extension_;
1838 GLenum reset_status_;
1839 bool reset_by_robustness_extension_;
1840 bool supports_post_sub_buffer_;
1842 // These flags are used to override the state of the shared feature_info_
1843 // member. Because the same FeatureInfo instance may be shared among many
1844 // contexts, the assumptions on the availablity of extensions in WebGL
1845 // contexts may be broken. These flags override the shared state to preserve
1846 // WebGL semantics.
1847 bool force_webgl_glsl_validation_;
1848 bool derivatives_explicitly_enabled_;
1849 bool frag_depth_explicitly_enabled_;
1850 bool draw_buffers_explicitly_enabled_;
1851 bool shader_texture_lod_explicitly_enabled_;
1853 bool compile_shader_always_succeeds_;
1855 // An optional behaviour to lose the context and group when OOM.
1856 bool lose_context_when_out_of_memory_;
1858 // Log extra info.
1859 bool service_logging_;
1861 #if defined(OS_MACOSX)
1862 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
1863 TextureToIOSurfaceMap texture_to_io_surface_map_;
1864 #endif
1866 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1867 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
1869 // Cached values of the currently assigned viewport dimensions.
1870 GLsizei viewport_max_width_;
1871 GLsizei viewport_max_height_;
1873 // Command buffer stats.
1874 base::TimeDelta total_processing_commands_time_;
1876 // States related to each manager.
1877 DecoderTextureState texture_state_;
1878 DecoderFramebufferState framebuffer_state_;
1880 scoped_ptr<GPUTracer> gpu_tracer_;
1881 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
1882 const unsigned char* cb_command_trace_category_;
1883 const unsigned char* gpu_decoder_category_;
1884 int gpu_trace_level_;
1885 bool gpu_trace_commands_;
1886 bool gpu_debug_commands_;
1888 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1890 // Used to validate multisample renderbuffers if needed
1891 GLuint validation_texture_;
1892 GLuint validation_fbo_multisample_;
1893 GLuint validation_fbo_;
1895 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
1896 uint32 immediate_data_size,
1897 const void* data);
1899 // A struct to hold info about each command.
1900 struct CommandInfo {
1901 CmdHandler cmd_handler;
1902 uint8 arg_flags; // How to handle the arguments for this command
1903 uint8 cmd_flags; // How to handle this command
1904 uint16 arg_count; // How many arguments are expected for this command.
1907 // A table of CommandInfo for all the commands.
1908 static const CommandInfo command_info[kNumCommands - kStartPoint];
1910 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1913 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
1914 #define GLES2_CMD_OP(name) \
1916 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
1917 cmds::name::cmd_flags, \
1918 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
1920 , /* NOLINT */
1921 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1922 #undef GLES2_CMD_OP
1925 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1926 const char* function_name, ErrorState* error_state)
1927 : function_name_(function_name),
1928 error_state_(error_state) {
1929 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
1932 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1933 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
1936 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
1937 TextureUnit& info = state->texture_units[0];
1938 GLuint last_id;
1939 scoped_refptr<TextureRef> texture_ref;
1940 switch (target) {
1941 case GL_TEXTURE_2D:
1942 texture_ref = info.bound_texture_2d;
1943 break;
1944 case GL_TEXTURE_CUBE_MAP:
1945 texture_ref = info.bound_texture_cube_map;
1946 break;
1947 case GL_TEXTURE_EXTERNAL_OES:
1948 texture_ref = info.bound_texture_external_oes;
1949 break;
1950 case GL_TEXTURE_RECTANGLE_ARB:
1951 texture_ref = info.bound_texture_rectangle_arb;
1952 break;
1953 default:
1954 NOTREACHED();
1955 break;
1957 if (texture_ref.get()) {
1958 last_id = texture_ref->service_id();
1959 } else {
1960 last_id = 0;
1963 glBindTexture(target, last_id);
1964 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
1967 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
1968 GLuint id,
1969 GLenum target)
1970 : state_(state),
1971 target_(target) {
1972 ScopedGLErrorSuppressor suppressor(
1973 "ScopedTextureBinder::ctor", state_->GetErrorState());
1975 // TODO(apatrick): Check if there are any other states that need to be reset
1976 // before binding a new texture.
1977 glActiveTexture(GL_TEXTURE0);
1978 glBindTexture(target, id);
1981 ScopedTextureBinder::~ScopedTextureBinder() {
1982 ScopedGLErrorSuppressor suppressor(
1983 "ScopedTextureBinder::dtor", state_->GetErrorState());
1984 RestoreCurrentTextureBindings(state_, target_);
1987 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
1988 GLuint id)
1989 : state_(state) {
1990 ScopedGLErrorSuppressor suppressor(
1991 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
1992 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1995 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1996 ScopedGLErrorSuppressor suppressor(
1997 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1998 state_->RestoreRenderbufferBindings();
2001 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2002 GLuint id)
2003 : decoder_(decoder) {
2004 ScopedGLErrorSuppressor suppressor(
2005 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2006 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2007 decoder->OnFboChanged();
2010 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2011 ScopedGLErrorSuppressor suppressor(
2012 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2013 decoder_->RestoreCurrentFramebufferBindings();
2016 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2017 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2018 : decoder_(decoder) {
2019 resolve_and_bind_ = (
2020 decoder_->offscreen_target_frame_buffer_.get() &&
2021 decoder_->IsOffscreenBufferMultisampled() &&
2022 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2023 enforce_internal_framebuffer));
2024 if (!resolve_and_bind_)
2025 return;
2027 ScopedGLErrorSuppressor suppressor(
2028 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2029 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2030 decoder_->offscreen_target_frame_buffer_->id());
2031 GLuint targetid;
2032 if (internal) {
2033 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2034 decoder_->offscreen_resolved_frame_buffer_.reset(
2035 new BackFramebuffer(decoder_));
2036 decoder_->offscreen_resolved_frame_buffer_->Create();
2037 decoder_->offscreen_resolved_color_texture_.reset(
2038 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2039 decoder_->offscreen_resolved_color_texture_->Create();
2041 DCHECK(decoder_->offscreen_saved_color_format_);
2042 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2043 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2044 false);
2045 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2046 decoder_->offscreen_resolved_color_texture_.get());
2047 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2048 GL_FRAMEBUFFER_COMPLETE) {
2049 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2050 << "because offscreen resolved FBO was incomplete.";
2051 return;
2054 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2055 } else {
2056 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2058 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2059 const int width = decoder_->offscreen_size_.width();
2060 const int height = decoder_->offscreen_size_.height();
2061 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2062 decoder->BlitFramebufferHelper(0,
2064 width,
2065 height,
2068 width,
2069 height,
2070 GL_COLOR_BUFFER_BIT,
2071 GL_NEAREST);
2072 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2075 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2076 if (!resolve_and_bind_)
2077 return;
2079 ScopedGLErrorSuppressor suppressor(
2080 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2081 decoder_->RestoreCurrentFramebufferBindings();
2082 if (decoder_->state_.enable_flags.scissor_test) {
2083 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2087 BackTexture::BackTexture(
2088 MemoryTracker* memory_tracker,
2089 ContextState* state)
2090 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2091 state_(state),
2092 bytes_allocated_(0),
2093 id_(0) {
2096 BackTexture::~BackTexture() {
2097 // This does not destroy the render texture because that would require that
2098 // the associated GL context was current. Just check that it was explicitly
2099 // destroyed.
2100 DCHECK_EQ(id_, 0u);
2103 void BackTexture::Create() {
2104 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2105 state_->GetErrorState());
2106 Destroy();
2107 glGenTextures(1, &id_);
2108 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2114 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2115 // never called on an offscreen context, no data will ever be uploaded to the
2116 // saved offscreen color texture (it is deferred until to when SwapBuffers
2117 // is called). My idea is that some nvidia drivers might have a bug where
2118 // deleting a texture that has never been populated might cause a
2119 // crash.
2120 glTexImage2D(
2121 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2123 bytes_allocated_ = 16u * 16u * 4u;
2124 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2127 bool BackTexture::AllocateStorage(
2128 const gfx::Size& size, GLenum format, bool zero) {
2129 DCHECK_NE(id_, 0u);
2130 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2131 state_->GetErrorState());
2132 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2133 uint32 image_size = 0;
2134 GLES2Util::ComputeImageDataSizes(
2135 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2136 NULL, NULL);
2138 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2139 return false;
2142 scoped_ptr<char[]> zero_data;
2143 if (zero) {
2144 zero_data.reset(new char[image_size]);
2145 memset(zero_data.get(), 0, image_size);
2148 glTexImage2D(GL_TEXTURE_2D,
2149 0, // mip level
2150 format,
2151 size.width(),
2152 size.height(),
2153 0, // border
2154 format,
2155 GL_UNSIGNED_BYTE,
2156 zero_data.get());
2158 size_ = size;
2160 bool success = glGetError() == GL_NO_ERROR;
2161 if (success) {
2162 memory_tracker_.TrackMemFree(bytes_allocated_);
2163 bytes_allocated_ = image_size;
2164 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2166 return success;
2169 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2170 DCHECK_NE(id_, 0u);
2171 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2172 state_->GetErrorState());
2173 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2174 glCopyTexImage2D(GL_TEXTURE_2D,
2175 0, // level
2176 format,
2177 0, 0,
2178 size.width(),
2179 size.height(),
2180 0); // border
2183 void BackTexture::Destroy() {
2184 if (id_ != 0) {
2185 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2186 state_->GetErrorState());
2187 glDeleteTextures(1, &id_);
2188 id_ = 0;
2190 memory_tracker_.TrackMemFree(bytes_allocated_);
2191 bytes_allocated_ = 0;
2194 void BackTexture::Invalidate() {
2195 id_ = 0;
2198 BackRenderbuffer::BackRenderbuffer(
2199 RenderbufferManager* renderbuffer_manager,
2200 MemoryTracker* memory_tracker,
2201 ContextState* state)
2202 : renderbuffer_manager_(renderbuffer_manager),
2203 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2204 state_(state),
2205 bytes_allocated_(0),
2206 id_(0) {
2209 BackRenderbuffer::~BackRenderbuffer() {
2210 // This does not destroy the render buffer because that would require that
2211 // the associated GL context was current. Just check that it was explicitly
2212 // destroyed.
2213 DCHECK_EQ(id_, 0u);
2216 void BackRenderbuffer::Create() {
2217 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2218 state_->GetErrorState());
2219 Destroy();
2220 glGenRenderbuffersEXT(1, &id_);
2223 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2224 const gfx::Size& size,
2225 GLenum format,
2226 GLsizei samples) {
2227 ScopedGLErrorSuppressor suppressor(
2228 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2229 ScopedRenderBufferBinder binder(state_, id_);
2231 uint32 estimated_size = 0;
2232 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2233 size.width(), size.height(), samples, format, &estimated_size)) {
2234 return false;
2237 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2238 return false;
2241 if (samples <= 1) {
2242 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2243 format,
2244 size.width(),
2245 size.height());
2246 } else {
2247 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2248 GL_RENDERBUFFER,
2249 samples,
2250 format,
2251 size.width(),
2252 size.height());
2254 bool success = glGetError() == GL_NO_ERROR;
2255 if (success) {
2256 // Mark the previously allocated bytes as free.
2257 memory_tracker_.TrackMemFree(bytes_allocated_);
2258 bytes_allocated_ = estimated_size;
2259 // Track the newly allocated bytes.
2260 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2262 return success;
2265 void BackRenderbuffer::Destroy() {
2266 if (id_ != 0) {
2267 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2268 state_->GetErrorState());
2269 glDeleteRenderbuffersEXT(1, &id_);
2270 id_ = 0;
2272 memory_tracker_.TrackMemFree(bytes_allocated_);
2273 bytes_allocated_ = 0;
2276 void BackRenderbuffer::Invalidate() {
2277 id_ = 0;
2280 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2281 : decoder_(decoder),
2282 id_(0) {
2285 BackFramebuffer::~BackFramebuffer() {
2286 // This does not destroy the frame buffer because that would require that
2287 // the associated GL context was current. Just check that it was explicitly
2288 // destroyed.
2289 DCHECK_EQ(id_, 0u);
2292 void BackFramebuffer::Create() {
2293 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2294 decoder_->GetErrorState());
2295 Destroy();
2296 glGenFramebuffersEXT(1, &id_);
2299 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2300 DCHECK_NE(id_, 0u);
2301 ScopedGLErrorSuppressor suppressor(
2302 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2303 ScopedFrameBufferBinder binder(decoder_, id_);
2304 GLuint attach_id = texture ? texture->id() : 0;
2305 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2306 GL_COLOR_ATTACHMENT0,
2307 GL_TEXTURE_2D,
2308 attach_id,
2312 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2313 BackRenderbuffer* render_buffer) {
2314 DCHECK_NE(id_, 0u);
2315 ScopedGLErrorSuppressor suppressor(
2316 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2317 ScopedFrameBufferBinder binder(decoder_, id_);
2318 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2319 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2320 target,
2321 GL_RENDERBUFFER,
2322 attach_id);
2325 void BackFramebuffer::Destroy() {
2326 if (id_ != 0) {
2327 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2328 decoder_->GetErrorState());
2329 glDeleteFramebuffersEXT(1, &id_);
2330 id_ = 0;
2334 void BackFramebuffer::Invalidate() {
2335 id_ = 0;
2338 GLenum BackFramebuffer::CheckStatus() {
2339 DCHECK_NE(id_, 0u);
2340 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2341 decoder_->GetErrorState());
2342 ScopedFrameBufferBinder binder(decoder_, id_);
2343 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2346 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2347 return new GLES2DecoderImpl(group);
2350 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2351 : GLES2Decoder(),
2352 group_(group),
2353 logger_(&debug_marker_manager_),
2354 state_(group_->feature_info(), this, &logger_),
2355 unpack_flip_y_(false),
2356 unpack_premultiply_alpha_(false),
2357 unpack_unpremultiply_alpha_(false),
2358 attrib_0_buffer_id_(0),
2359 attrib_0_buffer_matches_value_(true),
2360 attrib_0_size_(0),
2361 fixed_attrib_buffer_id_(0),
2362 fixed_attrib_buffer_size_(0),
2363 offscreen_target_color_format_(0),
2364 offscreen_target_depth_format_(0),
2365 offscreen_target_stencil_format_(0),
2366 offscreen_target_samples_(0),
2367 offscreen_target_buffer_preserved_(true),
2368 offscreen_saved_color_format_(0),
2369 back_buffer_color_format_(0),
2370 back_buffer_has_depth_(false),
2371 back_buffer_has_stencil_(false),
2372 surfaceless_(false),
2373 backbuffer_needs_clear_bits_(0),
2374 current_decoder_error_(error::kNoError),
2375 use_shader_translator_(true),
2376 validators_(group_->feature_info()->validators()),
2377 feature_info_(group_->feature_info()),
2378 frame_number_(0),
2379 has_robustness_extension_(false),
2380 reset_status_(GL_NO_ERROR),
2381 reset_by_robustness_extension_(false),
2382 supports_post_sub_buffer_(false),
2383 force_webgl_glsl_validation_(false),
2384 derivatives_explicitly_enabled_(false),
2385 frag_depth_explicitly_enabled_(false),
2386 draw_buffers_explicitly_enabled_(false),
2387 shader_texture_lod_explicitly_enabled_(false),
2388 compile_shader_always_succeeds_(false),
2389 lose_context_when_out_of_memory_(false),
2390 service_logging_(base::CommandLine::ForCurrentProcess()->HasSwitch(
2391 switches::kEnableGPUServiceLoggingGPU)),
2392 viewport_max_width_(0),
2393 viewport_max_height_(0),
2394 texture_state_(group_->feature_info()
2395 ->workarounds()
2396 .texsubimage2d_faster_than_teximage2d),
2397 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2398 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2399 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2400 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2401 gpu_trace_level_(2),
2402 gpu_trace_commands_(false),
2403 gpu_debug_commands_(false),
2404 validation_texture_(0),
2405 validation_fbo_multisample_(0),
2406 validation_fbo_(0) {
2407 DCHECK(group);
2409 attrib_0_value_.v[0] = 0.0f;
2410 attrib_0_value_.v[1] = 0.0f;
2411 attrib_0_value_.v[2] = 0.0f;
2412 attrib_0_value_.v[3] = 1.0f;
2414 // The shader translator is used for WebGL even when running on EGL
2415 // because additional restrictions are needed (like only enabling
2416 // GL_OES_standard_derivatives on demand). It is used for the unit
2417 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2418 // the empty string to CompileShader and this is not a valid shader.
2419 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2420 base::CommandLine::ForCurrentProcess()->HasSwitch(
2421 switches::kDisableGLSLTranslator)) {
2422 use_shader_translator_ = false;
2426 GLES2DecoderImpl::~GLES2DecoderImpl() {
2429 bool GLES2DecoderImpl::Initialize(
2430 const scoped_refptr<gfx::GLSurface>& surface,
2431 const scoped_refptr<gfx::GLContext>& context,
2432 bool offscreen,
2433 const gfx::Size& size,
2434 const DisallowedFeatures& disallowed_features,
2435 const std::vector<int32>& attribs) {
2436 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2437 DCHECK(context->IsCurrent(surface.get()));
2438 DCHECK(!context_.get());
2440 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2442 set_initialized();
2443 gpu_tracer_.reset(new GPUTracer(this));
2444 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2446 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2447 switches::kEnableGPUDebugging)) {
2448 set_debug(true);
2451 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2452 switches::kEnableGPUCommandLogging)) {
2453 set_log_commands(true);
2456 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2457 switches::kEnableUnsafeES3APIs)) {
2458 set_unsafe_es3_apis_enabled(true);
2461 compile_shader_always_succeeds_ =
2462 base::CommandLine::ForCurrentProcess()->HasSwitch(
2463 switches::kCompileShaderAlwaysSucceeds);
2465 // Take ownership of the context and surface. The surface can be replaced with
2466 // SetSurface.
2467 context_ = context;
2468 surface_ = surface;
2470 ContextCreationAttribHelper attrib_parser;
2471 if (!attrib_parser.Parse(attribs))
2472 return false;
2474 // Save the loseContextWhenOutOfMemory context creation attribute.
2475 lose_context_when_out_of_memory_ =
2476 attrib_parser.lose_context_when_out_of_memory;
2478 // If the failIfMajorPerformanceCaveat context creation attribute was true
2479 // and we are using a software renderer, fail.
2480 if (attrib_parser.fail_if_major_perf_caveat &&
2481 feature_info_->feature_flags().is_swiftshader) {
2482 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2483 Destroy(true);
2484 return false;
2487 if (!group_->Initialize(this, disallowed_features)) {
2488 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2489 << "failed to initialize.";
2490 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2491 Destroy(true);
2492 return false;
2494 CHECK_GL_ERROR();
2496 disallowed_features_ = disallowed_features;
2498 state_.attrib_values.resize(group_->max_vertex_attribs());
2499 vertex_array_manager_.reset(new VertexArrayManager());
2501 GLuint default_vertex_attrib_service_id = 0;
2502 if (features().native_vertex_array_object) {
2503 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2504 glBindVertexArrayOES(default_vertex_attrib_service_id);
2507 state_.default_vertex_attrib_manager =
2508 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2510 state_.default_vertex_attrib_manager->Initialize(
2511 group_->max_vertex_attribs(),
2512 feature_info_->workarounds().init_vertex_attributes);
2514 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2515 DoBindVertexArrayOES(0);
2517 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2519 image_manager_.reset(new ImageManager);
2521 util_.set_num_compressed_texture_formats(
2522 validators_->compressed_texture_format.GetValues().size());
2524 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2525 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2526 // OpenGL ES 2.0 does not have this issue.
2527 glEnableVertexAttribArray(0);
2529 glGenBuffersARB(1, &attrib_0_buffer_id_);
2530 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2531 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2532 glBindBuffer(GL_ARRAY_BUFFER, 0);
2533 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2535 state_.texture_units.resize(group_->max_texture_units());
2536 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2537 glActiveTexture(GL_TEXTURE0 + tt);
2538 // We want the last bind to be 2D.
2539 TextureRef* ref;
2540 if (features().oes_egl_image_external) {
2541 ref = texture_manager()->GetDefaultTextureInfo(
2542 GL_TEXTURE_EXTERNAL_OES);
2543 state_.texture_units[tt].bound_texture_external_oes = ref;
2544 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2546 if (features().arb_texture_rectangle) {
2547 ref = texture_manager()->GetDefaultTextureInfo(
2548 GL_TEXTURE_RECTANGLE_ARB);
2549 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2550 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2552 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2553 state_.texture_units[tt].bound_texture_cube_map = ref;
2554 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2555 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2556 state_.texture_units[tt].bound_texture_2d = ref;
2557 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2559 glActiveTexture(GL_TEXTURE0);
2560 CHECK_GL_ERROR();
2562 if (offscreen) {
2563 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2564 features().chromium_framebuffer_multisample) {
2565 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2566 // max_sample_count must be initialized to a sane value. If
2567 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2568 GLint max_sample_count = 1;
2569 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2570 offscreen_target_samples_ = std::min(attrib_parser.samples,
2571 max_sample_count);
2572 } else {
2573 offscreen_target_samples_ = 1;
2575 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2577 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2578 const bool rgb8_supported =
2579 context_->HasExtension("GL_OES_rgb8_rgba8");
2580 // The only available default render buffer formats in GLES2 have very
2581 // little precision. Don't enable multisampling unless 8-bit render
2582 // buffer formats are available--instead fall back to 8-bit textures.
2583 if (rgb8_supported && offscreen_target_samples_ > 1) {
2584 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2585 GL_RGBA8 : GL_RGB8;
2586 } else {
2587 offscreen_target_samples_ = 1;
2588 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2589 GL_RGBA : GL_RGB;
2592 // ANGLE only supports packed depth/stencil formats, so use it if it is
2593 // available.
2594 const bool depth24_stencil8_supported =
2595 feature_info_->feature_flags().packed_depth24_stencil8;
2596 VLOG(1) << "GL_OES_packed_depth_stencil "
2597 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2598 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2599 depth24_stencil8_supported) {
2600 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2601 offscreen_target_stencil_format_ = 0;
2602 } else {
2603 // It may be the case that this depth/stencil combination is not
2604 // supported, but this will be checked later by CheckFramebufferStatus.
2605 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2606 GL_DEPTH_COMPONENT16 : 0;
2607 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2608 GL_STENCIL_INDEX8 : 0;
2610 } else {
2611 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2612 GL_RGBA : GL_RGB;
2614 // If depth is requested at all, use the packed depth stencil format if
2615 // it's available, as some desktop GL drivers don't support any non-packed
2616 // formats for depth attachments.
2617 const bool depth24_stencil8_supported =
2618 feature_info_->feature_flags().packed_depth24_stencil8;
2619 VLOG(1) << "GL_EXT_packed_depth_stencil "
2620 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2622 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2623 depth24_stencil8_supported) {
2624 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2625 offscreen_target_stencil_format_ = 0;
2626 } else {
2627 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2628 GL_DEPTH_COMPONENT : 0;
2629 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2630 GL_STENCIL_INDEX : 0;
2634 offscreen_saved_color_format_ = attrib_parser.alpha_size > 0 ?
2635 GL_RGBA : GL_RGB;
2637 // Create the target frame buffer. This is the one that the client renders
2638 // directly to.
2639 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2640 offscreen_target_frame_buffer_->Create();
2641 // Due to GLES2 format limitations, either the color texture (for
2642 // non-multisampling) or the color render buffer (for multisampling) will be
2643 // attached to the offscreen frame buffer. The render buffer has more
2644 // limited formats available to it, but the texture can't do multisampling.
2645 if (IsOffscreenBufferMultisampled()) {
2646 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2647 renderbuffer_manager(), memory_tracker(), &state_));
2648 offscreen_target_color_render_buffer_->Create();
2649 } else {
2650 offscreen_target_color_texture_.reset(new BackTexture(
2651 memory_tracker(), &state_));
2652 offscreen_target_color_texture_->Create();
2654 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2655 renderbuffer_manager(), memory_tracker(), &state_));
2656 offscreen_target_depth_render_buffer_->Create();
2657 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2658 renderbuffer_manager(), memory_tracker(), &state_));
2659 offscreen_target_stencil_render_buffer_->Create();
2661 // Create the saved offscreen texture. The target frame buffer is copied
2662 // here when SwapBuffers is called.
2663 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2664 offscreen_saved_frame_buffer_->Create();
2666 offscreen_saved_color_texture_.reset(new BackTexture(
2667 memory_tracker(), &state_));
2668 offscreen_saved_color_texture_->Create();
2670 // Allocate the render buffers at their initial size and check the status
2671 // of the frame buffers is okay.
2672 if (!ResizeOffscreenFrameBuffer(size)) {
2673 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2674 Destroy(true);
2675 return false;
2678 // Allocate the offscreen saved color texture.
2679 DCHECK(offscreen_saved_color_format_);
2680 offscreen_saved_color_texture_->AllocateStorage(
2681 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2683 offscreen_saved_frame_buffer_->AttachRenderTexture(
2684 offscreen_saved_color_texture_.get());
2685 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2686 GL_FRAMEBUFFER_COMPLETE) {
2687 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2688 Destroy(true);
2689 return false;
2692 // Bind to the new default frame buffer (the offscreen target frame buffer).
2693 // This should now be associated with ID zero.
2694 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2695 } else {
2696 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2697 // These are NOT if the back buffer has these proprorties. They are
2698 // if we want the command buffer to enforce them regardless of what
2699 // the real backbuffer is assuming the real back buffer gives us more than
2700 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2701 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2702 // can't do anything about that.
2704 if (!surfaceless_) {
2705 GLint v = 0;
2706 glGetIntegerv(GL_ALPHA_BITS, &v);
2707 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2708 // the user requested RGB then RGB. If the user did not specify a
2709 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2710 back_buffer_color_format_ =
2711 (attrib_parser.alpha_size != 0 && v > 0) ? GL_RGBA : GL_RGB;
2712 glGetIntegerv(GL_DEPTH_BITS, &v);
2713 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && v > 0;
2714 glGetIntegerv(GL_STENCIL_BITS, &v);
2715 back_buffer_has_stencil_ = attrib_parser.stencil_size != 0 && v > 0;
2719 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2720 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2721 // isn't well documented; it was discovered in the Khronos OpenGL ES
2722 // mailing list archives. It also implicitly enables the desktop GL
2723 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2724 // variable in fragment shaders.
2725 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2726 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2727 glEnable(GL_POINT_SPRITE);
2730 has_robustness_extension_ =
2731 context->HasExtension("GL_ARB_robustness") ||
2732 context->HasExtension("GL_KHR_robustness") ||
2733 context->HasExtension("GL_EXT_robustness");
2735 if (!InitializeShaderTranslator()) {
2736 return false;
2739 state_.viewport_width = size.width();
2740 state_.viewport_height = size.height();
2742 GLint viewport_params[4] = { 0 };
2743 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2744 viewport_max_width_ = viewport_params[0];
2745 viewport_max_height_ = viewport_params[1];
2747 state_.scissor_width = state_.viewport_width;
2748 state_.scissor_height = state_.viewport_height;
2750 // Set all the default state because some GL drivers get it wrong.
2751 state_.InitCapabilities(NULL);
2752 state_.InitState(NULL);
2753 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2755 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2756 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2757 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2758 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2759 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
2761 bool call_gl_clear = !surfaceless_;
2762 #if defined(OS_ANDROID)
2763 // Temporary workaround for Android WebView because this clear ignores the
2764 // clip and corrupts that external UI of the App. Not calling glClear is ok
2765 // because the system already clears the buffer before each draw. Proper
2766 // fix might be setting the scissor clip properly before initialize. See
2767 // crbug.com/259023 for details.
2768 call_gl_clear = surface_->GetHandle();
2769 #endif
2770 if (call_gl_clear) {
2771 // Clear the backbuffer.
2772 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2775 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
2776 if (feature_info_->workarounds()
2777 .disable_post_sub_buffers_for_onscreen_surfaces &&
2778 !surface->IsOffscreen())
2779 supports_post_sub_buffer_ = false;
2781 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2782 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2785 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2786 context_->SetUnbindFboOnMakeCurrent();
2789 // Only compositor contexts are known to use only the subset of GL
2790 // that can be safely migrated between the iGPU and the dGPU. Mark
2791 // those contexts as safe to forcibly transition between the GPUs.
2792 // http://crbug.com/180876, http://crbug.com/227228
2793 if (!offscreen)
2794 context_->SetSafeToForceGpuSwitch();
2796 async_pixel_transfer_manager_.reset(
2797 AsyncPixelTransferManager::Create(context.get()));
2798 async_pixel_transfer_manager_->Initialize(texture_manager());
2800 if (workarounds().gl_clear_broken) {
2801 DCHECK(!clear_framebuffer_blit_.get());
2802 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
2803 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
2804 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
2805 return false;
2808 framebuffer_manager()->AddObserver(this);
2810 return true;
2813 Capabilities GLES2DecoderImpl::GetCapabilities() {
2814 DCHECK(initialized());
2816 Capabilities caps;
2817 caps.VisitPrecisions([](GLenum shader, GLenum type,
2818 Capabilities::ShaderPrecision* shader_precision) {
2819 GLint range[2] = {0, 0};
2820 GLint precision = 0;
2821 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
2822 shader_precision->min_range = range[0];
2823 shader_precision->max_range = range[1];
2824 shader_precision->precision = precision;
2826 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
2827 &caps.max_combined_texture_image_units);
2828 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
2829 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
2830 &caps.max_fragment_uniform_vectors);
2831 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
2832 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
2833 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
2834 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
2835 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
2836 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
2837 &caps.max_vertex_texture_image_units);
2838 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
2839 &caps.max_vertex_uniform_vectors);
2840 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
2841 &caps.num_compressed_texture_formats);
2842 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
2843 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
2844 &caps.bind_generates_resource_chromium);
2845 if (unsafe_es3_apis_enabled()) {
2846 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
2847 &caps.max_transform_feedback_separate_attribs);
2848 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
2849 &caps.max_uniform_buffer_bindings);
2850 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
2851 &caps.uniform_buffer_offset_alignment);
2854 caps.egl_image_external =
2855 feature_info_->feature_flags().oes_egl_image_external;
2856 caps.texture_format_bgra8888 =
2857 feature_info_->feature_flags().ext_texture_format_bgra8888;
2858 caps.texture_format_etc1 =
2859 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
2860 caps.texture_format_etc1_npot =
2861 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
2862 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
2863 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
2864 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
2865 caps.discard_framebuffer =
2866 feature_info_->feature_flags().ext_discard_framebuffer;
2867 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
2869 #if defined(OS_MACOSX)
2870 // This is unconditionally true on mac, no need to test for it at runtime.
2871 caps.iosurface = true;
2872 #endif
2874 caps.post_sub_buffer = supports_post_sub_buffer_;
2875 caps.image = true;
2877 caps.blend_equation_advanced =
2878 feature_info_->feature_flags().blend_equation_advanced;
2879 caps.blend_equation_advanced_coherent =
2880 feature_info_->feature_flags().blend_equation_advanced_coherent;
2881 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
2882 return caps;
2885 void GLES2DecoderImpl::UpdateCapabilities() {
2886 util_.set_num_compressed_texture_formats(
2887 validators_->compressed_texture_format.GetValues().size());
2888 util_.set_num_shader_binary_formats(
2889 validators_->shader_binary_format.GetValues().size());
2892 bool GLES2DecoderImpl::InitializeShaderTranslator() {
2893 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2895 if (!use_shader_translator_) {
2896 return true;
2898 ShBuiltInResources resources;
2899 ShInitBuiltInResources(&resources);
2900 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2901 resources.MaxVertexUniformVectors =
2902 group_->max_vertex_uniform_vectors();
2903 resources.MaxVaryingVectors = group_->max_varying_vectors();
2904 resources.MaxVertexTextureImageUnits =
2905 group_->max_vertex_texture_image_units();
2906 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2907 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2908 resources.MaxFragmentUniformVectors =
2909 group_->max_fragment_uniform_vectors();
2910 resources.MaxDrawBuffers = group_->max_draw_buffers();
2911 resources.MaxExpressionComplexity = 256;
2912 resources.MaxCallStackDepth = 256;
2914 GLint range[2] = { 0, 0 };
2915 GLint precision = 0;
2916 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2917 range, &precision);
2918 resources.FragmentPrecisionHigh =
2919 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
2921 if (force_webgl_glsl_validation_) {
2922 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2923 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2924 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
2925 if (!draw_buffers_explicitly_enabled_)
2926 resources.MaxDrawBuffers = 1;
2927 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
2928 resources.NV_draw_buffers =
2929 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
2930 } else {
2931 resources.OES_standard_derivatives =
2932 features().oes_standard_derivatives ? 1 : 0;
2933 resources.ARB_texture_rectangle =
2934 features().arb_texture_rectangle ? 1 : 0;
2935 resources.OES_EGL_image_external =
2936 features().oes_egl_image_external ? 1 : 0;
2937 resources.EXT_draw_buffers =
2938 features().ext_draw_buffers ? 1 : 0;
2939 resources.EXT_frag_depth =
2940 features().ext_frag_depth ? 1 : 0;
2941 resources.EXT_shader_texture_lod =
2942 features().ext_shader_texture_lod ? 1 : 0;
2943 resources.NV_draw_buffers =
2944 features().nv_draw_buffers ? 1 : 0;
2947 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2948 : SH_GLES2_SPEC;
2949 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2950 resources.HashFunction = &CityHash64;
2951 else
2952 resources.HashFunction = NULL;
2953 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2954 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2955 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2956 int driver_bug_workarounds = 0;
2957 if (workarounds().needs_glsl_built_in_function_emulation)
2958 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
2959 if (workarounds().init_gl_position_in_vertex_shader)
2960 driver_bug_workarounds |= SH_INIT_GL_POSITION;
2961 if (workarounds().unfold_short_circuit_as_ternary_operation)
2962 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
2963 if (workarounds().init_varyings_without_static_use)
2964 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
2965 if (workarounds().unroll_for_loop_with_sampler_array_index)
2966 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
2967 if (workarounds().scalarize_vec_and_mat_constructor_args)
2968 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
2969 if (workarounds().regenerate_struct_names)
2970 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
2972 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2973 switches::kEmulateShaderPrecision))
2974 resources.WEBGL_debug_shader_precision = true;
2976 vertex_translator_ = shader_translator_cache()->GetTranslator(
2977 GL_VERTEX_SHADER,
2978 shader_spec,
2979 &resources,
2980 implementation_type,
2981 static_cast<ShCompileOptions>(driver_bug_workarounds));
2982 if (!vertex_translator_.get()) {
2983 LOG(ERROR) << "Could not initialize vertex shader translator.";
2984 Destroy(true);
2985 return false;
2988 fragment_translator_ = shader_translator_cache()->GetTranslator(
2989 GL_FRAGMENT_SHADER,
2990 shader_spec,
2991 &resources,
2992 implementation_type,
2993 static_cast<ShCompileOptions>(driver_bug_workarounds));
2994 if (!fragment_translator_.get()) {
2995 LOG(ERROR) << "Could not initialize fragment shader translator.";
2996 Destroy(true);
2997 return false;
2999 return true;
3002 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3003 for (GLsizei ii = 0; ii < n; ++ii) {
3004 if (GetBuffer(client_ids[ii])) {
3005 return false;
3008 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3009 glGenBuffersARB(n, service_ids.get());
3010 for (GLsizei ii = 0; ii < n; ++ii) {
3011 CreateBuffer(client_ids[ii], service_ids[ii]);
3013 return true;
3016 bool GLES2DecoderImpl::GenFramebuffersHelper(
3017 GLsizei n, const GLuint* client_ids) {
3018 for (GLsizei ii = 0; ii < n; ++ii) {
3019 if (GetFramebuffer(client_ids[ii])) {
3020 return false;
3023 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3024 glGenFramebuffersEXT(n, service_ids.get());
3025 for (GLsizei ii = 0; ii < n; ++ii) {
3026 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3028 return true;
3031 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3032 GLsizei n, const GLuint* client_ids) {
3033 for (GLsizei ii = 0; ii < n; ++ii) {
3034 if (GetRenderbuffer(client_ids[ii])) {
3035 return false;
3038 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3039 glGenRenderbuffersEXT(n, service_ids.get());
3040 for (GLsizei ii = 0; ii < n; ++ii) {
3041 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3043 return true;
3046 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3047 const GLuint* client_ids) {
3048 for (GLsizei ii = 0; ii < n; ++ii) {
3049 if (GetValuebuffer(client_ids[ii])) {
3050 return false;
3053 for (GLsizei ii = 0; ii < n; ++ii) {
3054 CreateValuebuffer(client_ids[ii]);
3056 return true;
3059 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3060 for (GLsizei ii = 0; ii < n; ++ii) {
3061 if (GetTexture(client_ids[ii])) {
3062 return false;
3065 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3066 glGenTextures(n, service_ids.get());
3067 for (GLsizei ii = 0; ii < n; ++ii) {
3068 CreateTexture(client_ids[ii], service_ids[ii]);
3070 return true;
3073 void GLES2DecoderImpl::DeleteBuffersHelper(
3074 GLsizei n, const GLuint* client_ids) {
3075 for (GLsizei ii = 0; ii < n; ++ii) {
3076 Buffer* buffer = GetBuffer(client_ids[ii]);
3077 if (buffer && !buffer->IsDeleted()) {
3078 state_.vertex_attrib_manager->Unbind(buffer);
3079 if (state_.bound_array_buffer.get() == buffer) {
3080 state_.bound_array_buffer = NULL;
3082 RemoveBuffer(client_ids[ii]);
3087 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3088 GLsizei n, const GLuint* client_ids) {
3089 bool supports_separate_framebuffer_binds =
3090 features().chromium_framebuffer_multisample;
3092 for (GLsizei ii = 0; ii < n; ++ii) {
3093 Framebuffer* framebuffer =
3094 GetFramebuffer(client_ids[ii]);
3095 if (framebuffer && !framebuffer->IsDeleted()) {
3096 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3097 framebuffer_state_.bound_draw_framebuffer = NULL;
3098 framebuffer_state_.clear_state_dirty = true;
3099 GLenum target = supports_separate_framebuffer_binds ?
3100 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3101 glBindFramebufferEXT(target, GetBackbufferServiceId());
3103 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3104 framebuffer_state_.bound_read_framebuffer = NULL;
3105 GLenum target = supports_separate_framebuffer_binds ?
3106 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3107 glBindFramebufferEXT(target, GetBackbufferServiceId());
3109 OnFboChanged();
3110 RemoveFramebuffer(client_ids[ii]);
3115 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3116 GLsizei n, const GLuint* client_ids) {
3117 bool supports_separate_framebuffer_binds =
3118 features().chromium_framebuffer_multisample;
3119 for (GLsizei ii = 0; ii < n; ++ii) {
3120 Renderbuffer* renderbuffer =
3121 GetRenderbuffer(client_ids[ii]);
3122 if (renderbuffer && !renderbuffer->IsDeleted()) {
3123 if (state_.bound_renderbuffer.get() == renderbuffer) {
3124 state_.bound_renderbuffer = NULL;
3126 // Unbind from current framebuffers.
3127 if (supports_separate_framebuffer_binds) {
3128 if (framebuffer_state_.bound_read_framebuffer.get()) {
3129 framebuffer_state_.bound_read_framebuffer
3130 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3132 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3133 framebuffer_state_.bound_draw_framebuffer
3134 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3136 } else {
3137 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3138 framebuffer_state_.bound_draw_framebuffer
3139 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3142 framebuffer_state_.clear_state_dirty = true;
3143 RemoveRenderbuffer(client_ids[ii]);
3148 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3149 GLsizei n,
3150 const GLuint* client_ids) {
3151 for (GLsizei ii = 0; ii < n; ++ii) {
3152 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3153 if (valuebuffer) {
3154 if (state_.bound_valuebuffer.get() == valuebuffer) {
3155 state_.bound_valuebuffer = NULL;
3157 RemoveValuebuffer(client_ids[ii]);
3162 void GLES2DecoderImpl::DeleteTexturesHelper(
3163 GLsizei n, const GLuint* client_ids) {
3164 bool supports_separate_framebuffer_binds =
3165 features().chromium_framebuffer_multisample;
3166 for (GLsizei ii = 0; ii < n; ++ii) {
3167 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3168 if (texture_ref) {
3169 Texture* texture = texture_ref->texture();
3170 if (texture->IsAttachedToFramebuffer()) {
3171 framebuffer_state_.clear_state_dirty = true;
3173 // Unbind texture_ref from texture_ref units.
3174 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3175 state_.texture_units[jj].Unbind(texture_ref);
3177 // Unbind from current framebuffers.
3178 if (supports_separate_framebuffer_binds) {
3179 if (framebuffer_state_.bound_read_framebuffer.get()) {
3180 framebuffer_state_.bound_read_framebuffer
3181 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3183 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3184 framebuffer_state_.bound_draw_framebuffer
3185 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3187 } else {
3188 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3189 framebuffer_state_.bound_draw_framebuffer
3190 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3193 #if defined(OS_MACOSX)
3194 GLuint service_id = texture->service_id();
3195 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3196 ReleaseIOSurfaceForTexture(service_id);
3198 #endif
3199 RemoveTexture(client_ids[ii]);
3204 // } // anonymous namespace
3206 bool GLES2DecoderImpl::MakeCurrent() {
3207 if (!context_.get())
3208 return false;
3210 if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
3211 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3213 MaybeExitOnContextLost();
3215 return false;
3218 ProcessFinishedAsyncTransfers();
3220 // Rebind the FBO if it was unbound by the context.
3221 if (workarounds().unbind_fbo_on_context_switch)
3222 RestoreFramebufferBindings();
3224 framebuffer_state_.clear_state_dirty = true;
3226 return true;
3229 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3230 ProcessPendingReadPixels();
3231 if (engine() && query_manager_.get())
3232 query_manager_->ProcessPendingTransferQueries();
3234 // TODO(epenner): Is there a better place to do this?
3235 // This needs to occur before we execute any batch of commands
3236 // from the client, as the client may have recieved an async
3237 // completion while issuing those commands.
3238 // "DidFlushStart" would be ideal if we had such a callback.
3239 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3242 static void RebindCurrentFramebuffer(
3243 GLenum target,
3244 Framebuffer* framebuffer,
3245 GLuint back_buffer_service_id) {
3246 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3248 if (framebuffer_id == 0) {
3249 framebuffer_id = back_buffer_service_id;
3252 glBindFramebufferEXT(target, framebuffer_id);
3255 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3256 framebuffer_state_.clear_state_dirty = true;
3258 if (!features().chromium_framebuffer_multisample) {
3259 RebindCurrentFramebuffer(
3260 GL_FRAMEBUFFER,
3261 framebuffer_state_.bound_draw_framebuffer.get(),
3262 GetBackbufferServiceId());
3263 } else {
3264 RebindCurrentFramebuffer(
3265 GL_READ_FRAMEBUFFER_EXT,
3266 framebuffer_state_.bound_read_framebuffer.get(),
3267 GetBackbufferServiceId());
3268 RebindCurrentFramebuffer(
3269 GL_DRAW_FRAMEBUFFER_EXT,
3270 framebuffer_state_.bound_draw_framebuffer.get(),
3271 GetBackbufferServiceId());
3273 OnFboChanged();
3276 bool GLES2DecoderImpl::CheckFramebufferValid(
3277 Framebuffer* framebuffer,
3278 GLenum target, const char* func_name) {
3279 if (!framebuffer) {
3280 if (surfaceless_)
3281 return false;
3282 if (backbuffer_needs_clear_bits_) {
3283 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3284 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3285 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3286 glClearStencil(0);
3287 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3288 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3289 glClearDepth(1.0f);
3290 state_.SetDeviceDepthMask(GL_TRUE);
3291 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3292 bool reset_draw_buffer = false;
3293 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3294 group_->draw_buffer() == GL_NONE) {
3295 reset_draw_buffer = true;
3296 GLenum buf = GL_BACK;
3297 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3298 buf = GL_COLOR_ATTACHMENT0;
3299 glDrawBuffersARB(1, &buf);
3301 glClear(backbuffer_needs_clear_bits_);
3302 if (reset_draw_buffer) {
3303 GLenum buf = GL_NONE;
3304 glDrawBuffersARB(1, &buf);
3306 backbuffer_needs_clear_bits_ = 0;
3307 RestoreClearState();
3309 return true;
3312 if (framebuffer_manager()->IsComplete(framebuffer)) {
3313 return true;
3316 GLenum completeness = framebuffer->IsPossiblyComplete();
3317 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3318 LOCAL_SET_GL_ERROR(
3319 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3320 return false;
3323 // Are all the attachments cleared?
3324 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3325 texture_manager()->HaveUnclearedMips()) {
3326 if (!framebuffer->IsCleared()) {
3327 // Can we clear them?
3328 if (framebuffer->GetStatus(texture_manager(), target) !=
3329 GL_FRAMEBUFFER_COMPLETE) {
3330 LOCAL_SET_GL_ERROR(
3331 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3332 "framebuffer incomplete (clear)");
3333 return false;
3335 ClearUnclearedAttachments(target, framebuffer);
3339 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3340 if (framebuffer->GetStatus(texture_manager(), target) !=
3341 GL_FRAMEBUFFER_COMPLETE) {
3342 LOCAL_SET_GL_ERROR(
3343 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3344 "framebuffer incomplete (check)");
3345 return false;
3347 framebuffer_manager()->MarkAsComplete(framebuffer);
3350 // NOTE: At this point we don't know if the framebuffer is complete but
3351 // we DO know that everything that needs to be cleared has been cleared.
3352 return true;
3355 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3356 if (!features().chromium_framebuffer_multisample) {
3357 bool valid = CheckFramebufferValid(
3358 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3359 func_name);
3361 if (valid)
3362 OnUseFramebuffer();
3364 return valid;
3366 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3367 GL_DRAW_FRAMEBUFFER_EXT,
3368 func_name) &&
3369 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3370 GL_READ_FRAMEBUFFER_EXT,
3371 func_name);
3374 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3375 const char* func_name) {
3376 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3377 framebuffer_state_.bound_read_framebuffer.get() :
3378 framebuffer_state_.bound_draw_framebuffer.get();
3379 if (!framebuffer)
3380 return true;
3381 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3382 LOCAL_SET_GL_ERROR(
3383 GL_INVALID_OPERATION, func_name, "no color image attached");
3384 return false;
3386 return true;
3389 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3390 TextureRef* texture, GLint level) {
3391 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3392 framebuffer_state_.bound_read_framebuffer.get() :
3393 framebuffer_state_.bound_draw_framebuffer.get();
3394 if (!framebuffer)
3395 return false;
3396 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3397 GL_COLOR_ATTACHMENT0);
3398 if (!attachment)
3399 return false;
3400 return attachment->FormsFeedbackLoop(texture, level);
3403 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3404 Framebuffer* framebuffer =
3405 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3406 if (framebuffer != NULL) {
3407 const Framebuffer::Attachment* attachment =
3408 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3409 if (attachment) {
3410 return gfx::Size(attachment->width(), attachment->height());
3412 return gfx::Size(0, 0);
3413 } else if (offscreen_target_frame_buffer_.get()) {
3414 return offscreen_size_;
3415 } else {
3416 return surface_->GetSize();
3420 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3421 Framebuffer* framebuffer =
3422 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3423 if (framebuffer != NULL) {
3424 return framebuffer->GetColorAttachmentTextureType();
3425 } else {
3426 return GL_UNSIGNED_BYTE;
3430 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3431 Framebuffer* framebuffer =
3432 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3433 if (framebuffer != NULL) {
3434 return framebuffer->GetColorAttachmentFormat();
3435 } else if (offscreen_target_frame_buffer_.get()) {
3436 return offscreen_target_color_format_;
3437 } else {
3438 return back_buffer_color_format_;
3442 GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
3443 Framebuffer* framebuffer =
3444 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3445 if (framebuffer != NULL) {
3446 return framebuffer->GetColorAttachmentFormat();
3447 } else if (offscreen_target_frame_buffer_.get()) {
3448 return offscreen_target_color_format_;
3449 } else {
3450 return back_buffer_color_format_;
3454 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3455 if (!offscreen_saved_color_texture_info_.get())
3456 return;
3457 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3458 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3459 texture_manager()->SetLevelInfo(
3460 offscreen_saved_color_texture_info_.get(),
3461 GL_TEXTURE_2D,
3462 0, // level
3463 GL_RGBA,
3464 offscreen_size_.width(),
3465 offscreen_size_.height(),
3466 1, // depth
3467 0, // border
3468 GL_RGBA,
3469 GL_UNSIGNED_BYTE,
3470 true);
3471 texture_manager()->SetParameteri(
3472 "UpdateParentTextureInfo",
3473 GetErrorState(),
3474 offscreen_saved_color_texture_info_.get(),
3475 GL_TEXTURE_MAG_FILTER,
3476 GL_LINEAR);
3477 texture_manager()->SetParameteri(
3478 "UpdateParentTextureInfo",
3479 GetErrorState(),
3480 offscreen_saved_color_texture_info_.get(),
3481 GL_TEXTURE_MIN_FILTER,
3482 GL_LINEAR);
3483 texture_manager()->SetParameteri(
3484 "UpdateParentTextureInfo",
3485 GetErrorState(),
3486 offscreen_saved_color_texture_info_.get(),
3487 GL_TEXTURE_WRAP_S,
3488 GL_CLAMP_TO_EDGE);
3489 texture_manager()->SetParameteri(
3490 "UpdateParentTextureInfo",
3491 GetErrorState(),
3492 offscreen_saved_color_texture_info_.get(),
3493 GL_TEXTURE_WRAP_T,
3494 GL_CLAMP_TO_EDGE);
3495 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3496 &state_, target);
3497 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3500 void GLES2DecoderImpl::SetResizeCallback(
3501 const base::Callback<void(gfx::Size, float)>& callback) {
3502 resize_callback_ = callback;
3505 Logger* GLES2DecoderImpl::GetLogger() {
3506 return &logger_;
3509 void GLES2DecoderImpl::BeginDecoding() {
3510 gpu_tracer_->BeginDecoding();
3511 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3512 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3513 (*cb_command_trace_category_ != 0);
3516 void GLES2DecoderImpl::EndDecoding() {
3517 gpu_tracer_->EndDecoding();
3520 ErrorState* GLES2DecoderImpl::GetErrorState() {
3521 return state_.GetErrorState();
3524 void GLES2DecoderImpl::SetShaderCacheCallback(
3525 const ShaderCacheCallback& callback) {
3526 shader_cache_callback_ = callback;
3529 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3530 const WaitSyncPointCallback& callback) {
3531 wait_sync_point_callback_ = callback;
3534 AsyncPixelTransferManager*
3535 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3536 return async_pixel_transfer_manager_.get();
3539 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3540 async_pixel_transfer_manager_.reset();
3543 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3544 AsyncPixelTransferManager* manager) {
3545 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3548 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3549 uint32* service_texture_id) {
3550 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3551 if (texture_ref) {
3552 *service_texture_id = texture_ref->service_id();
3553 return true;
3555 return false;
3558 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3559 return texture_state_.texture_upload_count +
3560 async_pixel_transfer_manager_->GetTextureUploadCount();
3563 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3564 return texture_state_.total_texture_upload_time +
3565 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3568 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3569 return total_processing_commands_time_;
3572 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3573 total_processing_commands_time_ += time;
3576 void GLES2DecoderImpl::Destroy(bool have_context) {
3577 if (!initialized())
3578 return;
3580 DCHECK(!have_context || context_->IsCurrent(NULL));
3582 // Unbind everything.
3583 state_.vertex_attrib_manager = NULL;
3584 state_.default_vertex_attrib_manager = NULL;
3585 state_.texture_units.clear();
3586 state_.bound_array_buffer = NULL;
3587 state_.current_queries.clear();
3588 framebuffer_state_.bound_read_framebuffer = NULL;
3589 framebuffer_state_.bound_draw_framebuffer = NULL;
3590 state_.bound_renderbuffer = NULL;
3591 state_.bound_valuebuffer = NULL;
3593 if (offscreen_saved_color_texture_info_.get()) {
3594 DCHECK(offscreen_target_color_texture_);
3595 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3596 offscreen_saved_color_texture_->id());
3597 offscreen_saved_color_texture_->Invalidate();
3598 offscreen_saved_color_texture_info_ = NULL;
3600 if (have_context) {
3601 if (copy_texture_CHROMIUM_.get()) {
3602 copy_texture_CHROMIUM_->Destroy();
3603 copy_texture_CHROMIUM_.reset();
3606 clear_framebuffer_blit_.reset();
3608 if (state_.current_program.get()) {
3609 program_manager()->UnuseProgram(shader_manager(),
3610 state_.current_program.get());
3613 if (attrib_0_buffer_id_) {
3614 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3616 if (fixed_attrib_buffer_id_) {
3617 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3620 if (validation_texture_) {
3621 glDeleteTextures(1, &validation_texture_);
3622 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3623 glDeleteFramebuffersEXT(1, &validation_fbo_);
3626 if (offscreen_target_frame_buffer_.get())
3627 offscreen_target_frame_buffer_->Destroy();
3628 if (offscreen_target_color_texture_.get())
3629 offscreen_target_color_texture_->Destroy();
3630 if (offscreen_target_color_render_buffer_.get())
3631 offscreen_target_color_render_buffer_->Destroy();
3632 if (offscreen_target_depth_render_buffer_.get())
3633 offscreen_target_depth_render_buffer_->Destroy();
3634 if (offscreen_target_stencil_render_buffer_.get())
3635 offscreen_target_stencil_render_buffer_->Destroy();
3636 if (offscreen_saved_frame_buffer_.get())
3637 offscreen_saved_frame_buffer_->Destroy();
3638 if (offscreen_saved_color_texture_.get())
3639 offscreen_saved_color_texture_->Destroy();
3640 if (offscreen_resolved_frame_buffer_.get())
3641 offscreen_resolved_frame_buffer_->Destroy();
3642 if (offscreen_resolved_color_texture_.get())
3643 offscreen_resolved_color_texture_->Destroy();
3644 } else {
3645 if (offscreen_target_frame_buffer_.get())
3646 offscreen_target_frame_buffer_->Invalidate();
3647 if (offscreen_target_color_texture_.get())
3648 offscreen_target_color_texture_->Invalidate();
3649 if (offscreen_target_color_render_buffer_.get())
3650 offscreen_target_color_render_buffer_->Invalidate();
3651 if (offscreen_target_depth_render_buffer_.get())
3652 offscreen_target_depth_render_buffer_->Invalidate();
3653 if (offscreen_target_stencil_render_buffer_.get())
3654 offscreen_target_stencil_render_buffer_->Invalidate();
3655 if (offscreen_saved_frame_buffer_.get())
3656 offscreen_saved_frame_buffer_->Invalidate();
3657 if (offscreen_saved_color_texture_.get())
3658 offscreen_saved_color_texture_->Invalidate();
3659 if (offscreen_resolved_frame_buffer_.get())
3660 offscreen_resolved_frame_buffer_->Invalidate();
3661 if (offscreen_resolved_color_texture_.get())
3662 offscreen_resolved_color_texture_->Invalidate();
3665 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3666 // Otherwise, we can leak objects. http://crbug.com/258772.
3667 // state_.current_program must be reset before group_ is reset because
3668 // the later deletes the ProgramManager object that referred by
3669 // state_.current_program object.
3670 state_.current_program = NULL;
3672 copy_texture_CHROMIUM_.reset();
3673 clear_framebuffer_blit_.reset();
3675 if (query_manager_.get()) {
3676 query_manager_->Destroy(have_context);
3677 query_manager_.reset();
3680 if (vertex_array_manager_ .get()) {
3681 vertex_array_manager_->Destroy(have_context);
3682 vertex_array_manager_.reset();
3685 if (image_manager_.get()) {
3686 image_manager_->Destroy(have_context);
3687 image_manager_.reset();
3690 offscreen_target_frame_buffer_.reset();
3691 offscreen_target_color_texture_.reset();
3692 offscreen_target_color_render_buffer_.reset();
3693 offscreen_target_depth_render_buffer_.reset();
3694 offscreen_target_stencil_render_buffer_.reset();
3695 offscreen_saved_frame_buffer_.reset();
3696 offscreen_saved_color_texture_.reset();
3697 offscreen_resolved_frame_buffer_.reset();
3698 offscreen_resolved_color_texture_.reset();
3700 // Need to release these before releasing |group_| which may own the
3701 // ShaderTranslatorCache.
3702 fragment_translator_ = NULL;
3703 vertex_translator_ = NULL;
3705 // Should destroy the transfer manager before the texture manager held
3706 // by the context group.
3707 async_pixel_transfer_manager_.reset();
3709 if (group_.get()) {
3710 framebuffer_manager()->RemoveObserver(this);
3711 group_->Destroy(this, have_context);
3712 group_ = NULL;
3715 if (context_.get()) {
3716 context_->ReleaseCurrent(NULL);
3717 context_ = NULL;
3720 #if defined(OS_MACOSX)
3721 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3722 it != texture_to_io_surface_map_.end(); ++it) {
3723 CFRelease(it->second);
3725 texture_to_io_surface_map_.clear();
3726 #endif
3729 void GLES2DecoderImpl::SetSurface(
3730 const scoped_refptr<gfx::GLSurface>& surface) {
3731 DCHECK(context_->IsCurrent(NULL));
3732 DCHECK(surface_.get());
3733 surface_ = surface;
3734 RestoreCurrentFramebufferBindings();
3737 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
3738 if (!offscreen_saved_color_texture_.get()) {
3739 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
3740 return;
3742 if (!offscreen_saved_color_texture_info_.get()) {
3743 GLuint service_id = offscreen_saved_color_texture_->id();
3744 offscreen_saved_color_texture_info_ = TextureRef::Create(
3745 texture_manager(), 0, service_id);
3746 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3747 GL_TEXTURE_2D);
3748 UpdateParentTextureInfo();
3750 mailbox_manager()->ProduceTexture(
3751 mailbox, offscreen_saved_color_texture_info_->texture());
3754 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3755 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3756 if (!is_offscreen) {
3757 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3758 << " with an onscreen framebuffer.";
3759 return false;
3762 if (offscreen_size_ == size)
3763 return true;
3765 offscreen_size_ = size;
3766 int w = offscreen_size_.width();
3767 int h = offscreen_size_.height();
3768 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3769 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3770 << "to allocate storage due to excessive dimensions.";
3771 return false;
3774 // Reallocate the offscreen target buffers.
3775 DCHECK(offscreen_target_color_format_);
3776 if (IsOffscreenBufferMultisampled()) {
3777 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3778 feature_info_.get(),
3779 offscreen_size_,
3780 offscreen_target_color_format_,
3781 offscreen_target_samples_)) {
3782 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3783 << "to allocate storage for offscreen target color buffer.";
3784 return false;
3786 } else {
3787 if (!offscreen_target_color_texture_->AllocateStorage(
3788 offscreen_size_, offscreen_target_color_format_, false)) {
3789 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3790 << "to allocate storage for offscreen target color texture.";
3791 return false;
3794 if (offscreen_target_depth_format_ &&
3795 !offscreen_target_depth_render_buffer_->AllocateStorage(
3796 feature_info_.get(),
3797 offscreen_size_,
3798 offscreen_target_depth_format_,
3799 offscreen_target_samples_)) {
3800 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3801 << "to allocate storage for offscreen target depth buffer.";
3802 return false;
3804 if (offscreen_target_stencil_format_ &&
3805 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3806 feature_info_.get(),
3807 offscreen_size_,
3808 offscreen_target_stencil_format_,
3809 offscreen_target_samples_)) {
3810 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3811 << "to allocate storage for offscreen target stencil buffer.";
3812 return false;
3815 // Attach the offscreen target buffers to the target frame buffer.
3816 if (IsOffscreenBufferMultisampled()) {
3817 offscreen_target_frame_buffer_->AttachRenderBuffer(
3818 GL_COLOR_ATTACHMENT0,
3819 offscreen_target_color_render_buffer_.get());
3820 } else {
3821 offscreen_target_frame_buffer_->AttachRenderTexture(
3822 offscreen_target_color_texture_.get());
3824 if (offscreen_target_depth_format_) {
3825 offscreen_target_frame_buffer_->AttachRenderBuffer(
3826 GL_DEPTH_ATTACHMENT,
3827 offscreen_target_depth_render_buffer_.get());
3829 const bool packed_depth_stencil =
3830 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3831 if (packed_depth_stencil) {
3832 offscreen_target_frame_buffer_->AttachRenderBuffer(
3833 GL_STENCIL_ATTACHMENT,
3834 offscreen_target_depth_render_buffer_.get());
3835 } else if (offscreen_target_stencil_format_) {
3836 offscreen_target_frame_buffer_->AttachRenderBuffer(
3837 GL_STENCIL_ATTACHMENT,
3838 offscreen_target_stencil_render_buffer_.get());
3841 if (offscreen_target_frame_buffer_->CheckStatus() !=
3842 GL_FRAMEBUFFER_COMPLETE) {
3843 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3844 << "because offscreen FBO was incomplete.";
3845 return false;
3848 // Clear the target frame buffer.
3850 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3851 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3852 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3853 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3854 glClearStencil(0);
3855 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3856 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3857 glClearDepth(0);
3858 state_.SetDeviceDepthMask(GL_TRUE);
3859 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3860 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3861 RestoreClearState();
3864 // Destroy the offscreen resolved framebuffers.
3865 if (offscreen_resolved_frame_buffer_.get())
3866 offscreen_resolved_frame_buffer_->Destroy();
3867 if (offscreen_resolved_color_texture_.get())
3868 offscreen_resolved_color_texture_->Destroy();
3869 offscreen_resolved_color_texture_.reset();
3870 offscreen_resolved_frame_buffer_.reset();
3872 return true;
3875 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
3876 const void* cmd_data) {
3877 const gles2::cmds::ResizeCHROMIUM& c =
3878 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
3879 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
3880 return error::kDeferCommandUntilLater;
3882 GLuint width = static_cast<GLuint>(c.width);
3883 GLuint height = static_cast<GLuint>(c.height);
3884 GLfloat scale_factor = c.scale_factor;
3885 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
3887 width = std::max(1U, width);
3888 height = std::max(1U, height);
3890 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3891 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3892 // Make sure that we are done drawing to the back buffer before resizing.
3893 glFinish();
3894 #endif
3895 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3896 if (is_offscreen) {
3897 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3898 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3899 << "ResizeOffscreenFrameBuffer failed.";
3900 return error::kLostContext;
3904 if (!resize_callback_.is_null()) {
3905 resize_callback_.Run(gfx::Size(width, height), scale_factor);
3906 DCHECK(context_->IsCurrent(surface_.get()));
3907 if (!context_->IsCurrent(surface_.get())) {
3908 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3909 << "current after resize callback.";
3910 return error::kLostContext;
3914 return error::kNoError;
3917 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3918 if (command_id > kStartPoint && command_id < kNumCommands) {
3919 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3921 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3924 // Decode a command, and call the corresponding GL functions.
3925 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
3926 // of commands at once, and is now only used for tests that need to track
3927 // individual commands.
3928 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
3929 unsigned int arg_count,
3930 const void* cmd_data) {
3931 return DoCommands(1, cmd_data, arg_count + 1, 0);
3934 // Decode multiple commands, and call the corresponding GL functions.
3935 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
3936 // changed by a (malicious) client at any time, so if validation has to happen,
3937 // it should operate on a copy of them.
3938 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
3939 // interest of performance in this critical execution loop.
3940 template <bool DebugImpl>
3941 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
3942 const void* buffer,
3943 int num_entries,
3944 int* entries_processed) {
3945 commands_to_process_ = num_commands;
3946 error::Error result = error::kNoError;
3947 const CommandBufferEntry* cmd_data =
3948 static_cast<const CommandBufferEntry*>(buffer);
3949 int process_pos = 0;
3950 unsigned int command = 0;
3952 while (process_pos < num_entries && result == error::kNoError &&
3953 commands_to_process_--) {
3954 const unsigned int size = cmd_data->value_header.size;
3955 command = cmd_data->value_header.command;
3957 if (size == 0) {
3958 result = error::kInvalidSize;
3959 break;
3962 if (static_cast<int>(size) + process_pos > num_entries) {
3963 result = error::kOutOfBounds;
3964 break;
3967 if (DebugImpl) {
3968 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
3969 GetCommandName(command));
3971 if (log_commands()) {
3972 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
3973 << "cmd: " << GetCommandName(command);
3977 const unsigned int arg_count = size - 1;
3978 unsigned int command_index = command - kStartPoint - 1;
3979 if (command_index < arraysize(command_info)) {
3980 const CommandInfo& info = command_info[command_index];
3981 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3982 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3983 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3984 bool doing_gpu_trace = false;
3985 if (DebugImpl && gpu_trace_commands_) {
3986 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
3987 doing_gpu_trace = true;
3988 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
3989 GetCommandName(command),
3990 kTraceDecoder);
3994 uint32 immediate_data_size = (arg_count - info_arg_count) *
3995 sizeof(CommandBufferEntry); // NOLINT
3997 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
3999 if (DebugImpl && doing_gpu_trace)
4000 gpu_tracer_->End(kTraceDecoder);
4002 if (DebugImpl && debug()) {
4003 GLenum error;
4004 while ((error = glGetError()) != GL_NO_ERROR) {
4005 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4006 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4007 << " : " << GetCommandName(command);
4008 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4011 } else {
4012 result = error::kInvalidArguments;
4014 } else {
4015 result = DoCommonCommand(command, arg_count, cmd_data);
4018 if (DebugImpl) {
4019 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4020 GetCommandName(command));
4023 if (result == error::kNoError &&
4024 current_decoder_error_ != error::kNoError) {
4025 result = current_decoder_error_;
4026 current_decoder_error_ = error::kNoError;
4029 if (result != error::kDeferCommandUntilLater) {
4030 process_pos += size;
4031 cmd_data += size;
4035 if (entries_processed)
4036 *entries_processed = process_pos;
4038 if (error::IsError(result)) {
4039 LOG(ERROR) << "Error: " << result << " for Command "
4040 << GetCommandName(command);
4043 return result;
4046 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4047 const void* buffer,
4048 int num_entries,
4049 int* entries_processed) {
4050 if (gpu_debug_commands_) {
4051 return DoCommandsImpl<true>(
4052 num_commands, buffer, num_entries, entries_processed);
4053 } else {
4054 return DoCommandsImpl<false>(
4055 num_commands, buffer, num_entries, entries_processed);
4059 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4060 buffer_manager()->RemoveBuffer(client_id);
4063 void GLES2DecoderImpl::DoFinish() {
4064 glFinish();
4065 ProcessPendingReadPixels();
4066 ProcessPendingQueries(true);
4069 void GLES2DecoderImpl::DoFlush() {
4070 glFlush();
4071 ProcessPendingQueries(false);
4074 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4075 GLuint texture_index = texture_unit - GL_TEXTURE0;
4076 if (texture_index >= state_.texture_units.size()) {
4077 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4078 "glActiveTexture", texture_unit, "texture_unit");
4079 return;
4081 state_.active_texture_unit = texture_index;
4082 glActiveTexture(texture_unit);
4085 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4086 Buffer* buffer = NULL;
4087 GLuint service_id = 0;
4088 if (client_id != 0) {
4089 buffer = GetBuffer(client_id);
4090 if (!buffer) {
4091 if (!group_->bind_generates_resource()) {
4092 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4093 "glBindBuffer",
4094 "id not generated by glGenBuffers");
4095 return;
4098 // It's a new id so make a buffer buffer for it.
4099 glGenBuffersARB(1, &service_id);
4100 CreateBuffer(client_id, service_id);
4101 buffer = GetBuffer(client_id);
4104 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4105 if (buffer) {
4106 if (!buffer_manager()->SetTarget(buffer, target)) {
4107 LOCAL_SET_GL_ERROR(
4108 GL_INVALID_OPERATION,
4109 "glBindBuffer", "buffer bound to more than 1 target");
4110 return;
4112 service_id = buffer->service_id();
4114 switch (target) {
4115 case GL_ARRAY_BUFFER:
4116 state_.bound_array_buffer = buffer;
4117 break;
4118 case GL_ELEMENT_ARRAY_BUFFER:
4119 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
4120 break;
4121 default:
4122 NOTREACHED(); // Validation should prevent us getting here.
4123 break;
4125 glBindBuffer(target, service_id);
4128 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
4129 bool all_draw_buffers) {
4130 Framebuffer* framebuffer =
4131 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4132 if (!all_draw_buffers || !framebuffer) {
4133 return (GLES2Util::GetChannelsForFormat(
4134 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
4136 return framebuffer->HasAlphaMRT();
4139 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4140 Framebuffer* framebuffer =
4141 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4142 if (framebuffer) {
4143 return framebuffer->HasDepthAttachment();
4145 if (offscreen_target_frame_buffer_.get()) {
4146 return offscreen_target_depth_format_ != 0;
4148 return back_buffer_has_depth_;
4151 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4152 Framebuffer* framebuffer =
4153 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4154 if (framebuffer) {
4155 return framebuffer->HasStencilAttachment();
4157 if (offscreen_target_frame_buffer_.get()) {
4158 return offscreen_target_stencil_format_ != 0 ||
4159 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4161 return back_buffer_has_stencil_;
4164 void GLES2DecoderImpl::ApplyDirtyState() {
4165 if (framebuffer_state_.clear_state_dirty) {
4166 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
4167 state_.SetDeviceColorMask(state_.color_mask_red,
4168 state_.color_mask_green,
4169 state_.color_mask_blue,
4170 state_.color_mask_alpha && have_alpha);
4172 bool have_depth = BoundFramebufferHasDepthAttachment();
4173 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4175 bool have_stencil = BoundFramebufferHasStencilAttachment();
4176 state_.SetDeviceStencilMaskSeparate(
4177 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4178 state_.SetDeviceStencilMaskSeparate(
4179 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4181 state_.SetDeviceCapabilityState(
4182 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4183 state_.SetDeviceCapabilityState(
4184 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4185 framebuffer_state_.clear_state_dirty = false;
4189 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4190 return (offscreen_target_frame_buffer_.get())
4191 ? offscreen_target_frame_buffer_->id()
4192 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4195 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4196 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4197 "context", logger_.GetLogPrefix());
4198 // Restore the Framebuffer first because of bugs in Intel drivers.
4199 // Intel drivers incorrectly clip the viewport settings to
4200 // the size of the current framebuffer object.
4201 RestoreFramebufferBindings();
4202 state_.RestoreState(prev_state);
4205 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4206 GLuint service_id =
4207 framebuffer_state_.bound_draw_framebuffer.get()
4208 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4209 : GetBackbufferServiceId();
4210 if (!features().chromium_framebuffer_multisample) {
4211 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4212 } else {
4213 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4214 service_id = framebuffer_state_.bound_read_framebuffer.get()
4215 ? framebuffer_state_.bound_read_framebuffer->service_id()
4216 : GetBackbufferServiceId();
4217 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4219 OnFboChanged();
4222 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4223 state_.RestoreRenderbufferBindings();
4226 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4227 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4228 if (texture) {
4229 GLenum target = texture->target();
4230 glBindTexture(target, service_id);
4231 glTexParameteri(
4232 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4233 glTexParameteri(
4234 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4235 glTexParameteri(
4236 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4237 glTexParameteri(
4238 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4239 RestoreTextureUnitBindings(state_.active_texture_unit);
4243 void GLES2DecoderImpl::ClearAllAttributes() const {
4244 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4245 // other VAOs.
4246 if (feature_info_->feature_flags().native_vertex_array_object)
4247 glBindVertexArrayOES(0);
4249 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4250 if (i != 0) // Never disable attribute 0
4251 glDisableVertexAttribArray(i);
4252 if(features().angle_instanced_arrays)
4253 glVertexAttribDivisorANGLE(i, 0);
4257 void GLES2DecoderImpl::RestoreAllAttributes() const {
4258 state_.RestoreVertexAttribs();
4261 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4262 state_.SetIgnoreCachedStateForTest(ignore);
4265 void GLES2DecoderImpl::OnFboChanged() const {
4266 if (workarounds().restore_scissor_on_fbo_change)
4267 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
4269 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4270 GLint bound_fbo_unsigned = -1;
4271 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4272 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4273 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4274 surface_->NotifyWasBound();
4278 // Called after the FBO is checked for completeness.
4279 void GLES2DecoderImpl::OnUseFramebuffer() const {
4280 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
4281 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
4282 // The driver forgets the correct scissor when modifying the FBO binding.
4283 glScissor(state_.scissor_x,
4284 state_.scissor_y,
4285 state_.scissor_width,
4286 state_.scissor_height);
4288 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4289 // it's unclear how this bug works.
4290 glFlush();
4294 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4295 Framebuffer* framebuffer = NULL;
4296 GLuint service_id = 0;
4297 if (client_id != 0) {
4298 framebuffer = GetFramebuffer(client_id);
4299 if (!framebuffer) {
4300 if (!group_->bind_generates_resource()) {
4301 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4302 "glBindFramebuffer",
4303 "id not generated by glGenFramebuffers");
4304 return;
4307 // It's a new id so make a framebuffer framebuffer for it.
4308 glGenFramebuffersEXT(1, &service_id);
4309 CreateFramebuffer(client_id, service_id);
4310 framebuffer = GetFramebuffer(client_id);
4311 } else {
4312 service_id = framebuffer->service_id();
4314 framebuffer->MarkAsValid();
4316 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4318 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4319 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4322 // vmiura: This looks like dup code
4323 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4324 framebuffer_state_.bound_read_framebuffer = framebuffer;
4327 framebuffer_state_.clear_state_dirty = true;
4329 // If we are rendering to the backbuffer get the FBO id for any simulated
4330 // backbuffer.
4331 if (framebuffer == NULL) {
4332 service_id = GetBackbufferServiceId();
4335 glBindFramebufferEXT(target, service_id);
4336 OnFboChanged();
4339 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4340 Renderbuffer* renderbuffer = NULL;
4341 GLuint service_id = 0;
4342 if (client_id != 0) {
4343 renderbuffer = GetRenderbuffer(client_id);
4344 if (!renderbuffer) {
4345 if (!group_->bind_generates_resource()) {
4346 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4347 "glBindRenderbuffer",
4348 "id not generated by glGenRenderbuffers");
4349 return;
4352 // It's a new id so make a renderbuffer for it.
4353 glGenRenderbuffersEXT(1, &service_id);
4354 CreateRenderbuffer(client_id, service_id);
4355 renderbuffer = GetRenderbuffer(client_id);
4356 } else {
4357 service_id = renderbuffer->service_id();
4359 renderbuffer->MarkAsValid();
4361 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4362 state_.bound_renderbuffer = renderbuffer;
4363 state_.bound_renderbuffer_valid = true;
4364 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4367 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4368 TextureRef* texture_ref = NULL;
4369 GLuint service_id = 0;
4370 if (client_id != 0) {
4371 texture_ref = GetTexture(client_id);
4372 if (!texture_ref) {
4373 if (!group_->bind_generates_resource()) {
4374 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4375 "glBindTexture",
4376 "id not generated by glGenTextures");
4377 return;
4380 // It's a new id so make a texture texture for it.
4381 glGenTextures(1, &service_id);
4382 DCHECK_NE(0u, service_id);
4383 CreateTexture(client_id, service_id);
4384 texture_ref = GetTexture(client_id);
4386 } else {
4387 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4390 // Check the texture exists
4391 if (texture_ref) {
4392 Texture* texture = texture_ref->texture();
4393 // Check that we are not trying to bind it to a different target.
4394 if (texture->target() != 0 && texture->target() != target) {
4395 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4396 "glBindTexture",
4397 "texture bound to more than 1 target.");
4398 return;
4400 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4401 if (texture->target() == 0) {
4402 texture_manager()->SetTarget(texture_ref, target);
4404 glBindTexture(target, texture->service_id());
4405 } else {
4406 glBindTexture(target, 0);
4409 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4410 unit.bind_target = target;
4411 switch (target) {
4412 case GL_TEXTURE_2D:
4413 unit.bound_texture_2d = texture_ref;
4414 break;
4415 case GL_TEXTURE_CUBE_MAP:
4416 unit.bound_texture_cube_map = texture_ref;
4417 break;
4418 case GL_TEXTURE_EXTERNAL_OES:
4419 unit.bound_texture_external_oes = texture_ref;
4420 break;
4421 case GL_TEXTURE_RECTANGLE_ARB:
4422 unit.bound_texture_rectangle_arb = texture_ref;
4423 break;
4424 default:
4425 NOTREACHED(); // Validation should prevent us getting here.
4426 break;
4430 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4431 if (state_.vertex_attrib_manager->Enable(index, false)) {
4432 if (index != 0 ||
4433 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4434 glDisableVertexAttribArray(index);
4436 } else {
4437 LOCAL_SET_GL_ERROR(
4438 GL_INVALID_VALUE,
4439 "glDisableVertexAttribArray", "index out of range");
4443 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4444 GLsizei numAttachments,
4445 const GLenum* attachments) {
4446 Framebuffer* framebuffer =
4447 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4449 // Validates the attachments. If one of them fails
4450 // the whole command fails.
4451 for (GLsizei i = 0; i < numAttachments; ++i) {
4452 if ((framebuffer &&
4453 !validators_->attachment.IsValid(attachments[i])) ||
4454 (!framebuffer &&
4455 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4456 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4457 "glDiscardFramebufferEXT", attachments[i], "attachments");
4458 return;
4462 // Marks each one of them as not cleared
4463 for (GLsizei i = 0; i < numAttachments; ++i) {
4464 if (framebuffer) {
4465 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4466 texture_manager(),
4467 attachments[i],
4468 false);
4469 } else {
4470 switch (attachments[i]) {
4471 case GL_COLOR_EXT:
4472 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4473 break;
4474 case GL_DEPTH_EXT:
4475 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4476 case GL_STENCIL_EXT:
4477 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4478 break;
4479 default:
4480 NOTREACHED();
4481 break;
4486 // If the default framebuffer is bound but we are still rendering to an
4487 // FBO, translate attachment names that refer to default framebuffer
4488 // channels to corresponding framebuffer attachments.
4489 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4490 for (GLsizei i = 0; i < numAttachments; ++i) {
4491 GLenum attachment = attachments[i];
4492 if (!framebuffer && GetBackbufferServiceId()) {
4493 switch (attachment) {
4494 case GL_COLOR_EXT:
4495 attachment = GL_COLOR_ATTACHMENT0;
4496 break;
4497 case GL_DEPTH_EXT:
4498 attachment = GL_DEPTH_ATTACHMENT;
4499 break;
4500 case GL_STENCIL_EXT:
4501 attachment = GL_STENCIL_ATTACHMENT;
4502 break;
4503 default:
4504 NOTREACHED();
4505 return;
4508 translated_attachments[i] = attachment;
4511 ScopedRenderTo do_render(framebuffer);
4512 if (feature_info_->gl_version_info().is_es3) {
4513 glInvalidateFramebuffer(
4514 target, numAttachments, translated_attachments.get());
4515 } else {
4516 glDiscardFramebufferEXT(
4517 target, numAttachments, translated_attachments.get());
4521 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4522 if (state_.vertex_attrib_manager->Enable(index, true)) {
4523 glEnableVertexAttribArray(index);
4524 } else {
4525 LOCAL_SET_GL_ERROR(
4526 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4530 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4531 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4532 &state_, target);
4533 if (!texture_ref ||
4534 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4535 LOCAL_SET_GL_ERROR(
4536 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4537 return;
4540 if (target == GL_TEXTURE_CUBE_MAP) {
4541 for (int i = 0; i < 6; ++i) {
4542 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4543 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4544 LOCAL_SET_GL_ERROR(
4545 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4546 return;
4549 } else {
4550 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4551 LOCAL_SET_GL_ERROR(
4552 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4553 return;
4557 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4558 // Workaround for Mac driver bug. In the large scheme of things setting
4559 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4560 // hit so there's probably no need to make this conditional. The bug appears
4561 // to be that if the filtering mode is set to something that doesn't require
4562 // mipmaps for rendering, or is never set to something other than the default,
4563 // then glGenerateMipmap misbehaves.
4564 if (workarounds().set_texture_filter_before_generating_mipmap) {
4565 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4567 glGenerateMipmapEXT(target);
4568 if (workarounds().set_texture_filter_before_generating_mipmap) {
4569 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4570 texture_ref->texture()->min_filter());
4572 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4573 if (error == GL_NO_ERROR) {
4574 texture_manager()->MarkMipmapsGenerated(texture_ref);
4578 bool GLES2DecoderImpl::GetHelper(
4579 GLenum pname, GLint* params, GLsizei* num_written) {
4580 DCHECK(num_written);
4581 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4582 switch (pname) {
4583 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4584 *num_written = 1;
4585 // Return the GL implementation's preferred format and (see below type)
4586 // if we have the GL extension that exposes this. This allows the GPU
4587 // client to use the implementation's preferred format for glReadPixels
4588 // for optimisation.
4590 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4591 // case when requested on integer/floating point buffers but which is
4592 // acceptable on GLES2 and with the GL_OES_read_format extension.
4594 // Therefore if an error occurs we swallow the error and use the
4595 // internal implementation.
4596 if (params) {
4597 if (context_->HasExtension("GL_OES_read_format")) {
4598 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4599 GetErrorState());
4600 glGetIntegerv(pname, params);
4601 if (glGetError() == GL_NO_ERROR)
4602 return true;
4604 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4605 GetBoundReadFrameBufferInternalFormat());
4607 return true;
4608 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4609 *num_written = 1;
4610 if (params) {
4611 if (context_->HasExtension("GL_OES_read_format")) {
4612 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4613 GetErrorState());
4614 glGetIntegerv(pname, params);
4615 if (glGetError() == GL_NO_ERROR)
4616 return true;
4618 *params = GLES2Util::GetPreferredGLReadPixelsType(
4619 GetBoundReadFrameBufferInternalFormat(),
4620 GetBoundReadFrameBufferTextureType());
4622 return true;
4623 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4624 *num_written = 1;
4625 if (params) {
4626 *params = group_->max_fragment_uniform_vectors();
4628 return true;
4629 case GL_MAX_VARYING_VECTORS:
4630 *num_written = 1;
4631 if (params) {
4632 *params = group_->max_varying_vectors();
4634 return true;
4635 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4636 *num_written = 1;
4637 if (params) {
4638 *params = group_->max_vertex_uniform_vectors();
4640 return true;
4643 switch (pname) {
4644 case GL_MAX_VIEWPORT_DIMS:
4645 if (offscreen_target_frame_buffer_.get()) {
4646 *num_written = 2;
4647 if (params) {
4648 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4649 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4651 return true;
4653 return false;
4654 case GL_MAX_SAMPLES:
4655 *num_written = 1;
4656 if (params) {
4657 params[0] = renderbuffer_manager()->max_samples();
4659 return true;
4660 case GL_MAX_RENDERBUFFER_SIZE:
4661 *num_written = 1;
4662 if (params) {
4663 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4665 return true;
4666 case GL_MAX_TEXTURE_SIZE:
4667 *num_written = 1;
4668 if (params) {
4669 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4671 return true;
4672 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4673 *num_written = 1;
4674 if (params) {
4675 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4677 return true;
4678 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4679 *num_written = 1;
4680 if (params) {
4681 params[0] = group_->max_color_attachments();
4683 return true;
4684 case GL_MAX_DRAW_BUFFERS_ARB:
4685 *num_written = 1;
4686 if (params) {
4687 params[0] = group_->max_draw_buffers();
4689 return true;
4690 case GL_ALPHA_BITS:
4691 *num_written = 1;
4692 if (params) {
4693 GLint v = 0;
4694 glGetIntegerv(GL_ALPHA_BITS, &v);
4695 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
4697 return true;
4698 case GL_DEPTH_BITS:
4699 *num_written = 1;
4700 if (params) {
4701 GLint v = 0;
4702 glGetIntegerv(GL_DEPTH_BITS, &v);
4703 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4705 return true;
4706 case GL_STENCIL_BITS:
4707 *num_written = 1;
4708 if (params) {
4709 GLint v = 0;
4710 glGetIntegerv(GL_STENCIL_BITS, &v);
4711 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4713 return true;
4714 case GL_COMPRESSED_TEXTURE_FORMATS:
4715 *num_written = validators_->compressed_texture_format.GetValues().size();
4716 if (params) {
4717 for (GLint ii = 0; ii < *num_written; ++ii) {
4718 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4721 return true;
4722 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4723 *num_written = 1;
4724 if (params) {
4725 *params = validators_->compressed_texture_format.GetValues().size();
4727 return true;
4728 case GL_NUM_SHADER_BINARY_FORMATS:
4729 *num_written = 1;
4730 if (params) {
4731 *params = validators_->shader_binary_format.GetValues().size();
4733 return true;
4734 case GL_SHADER_BINARY_FORMATS:
4735 *num_written = validators_->shader_binary_format.GetValues().size();
4736 if (params) {
4737 for (GLint ii = 0; ii < *num_written; ++ii) {
4738 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4741 return true;
4742 case GL_SHADER_COMPILER:
4743 *num_written = 1;
4744 if (params) {
4745 *params = GL_TRUE;
4747 return true;
4748 case GL_ARRAY_BUFFER_BINDING:
4749 *num_written = 1;
4750 if (params) {
4751 if (state_.bound_array_buffer.get()) {
4752 GLuint client_id = 0;
4753 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4754 &client_id);
4755 *params = client_id;
4756 } else {
4757 *params = 0;
4760 return true;
4761 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4762 *num_written = 1;
4763 if (params) {
4764 if (state_.vertex_attrib_manager->element_array_buffer()) {
4765 GLuint client_id = 0;
4766 buffer_manager()->GetClientId(
4767 state_.vertex_attrib_manager->element_array_buffer()->
4768 service_id(), &client_id);
4769 *params = client_id;
4770 } else {
4771 *params = 0;
4774 return true;
4775 case GL_FRAMEBUFFER_BINDING:
4776 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4777 *num_written = 1;
4778 if (params) {
4779 Framebuffer* framebuffer =
4780 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4781 if (framebuffer) {
4782 GLuint client_id = 0;
4783 framebuffer_manager()->GetClientId(
4784 framebuffer->service_id(), &client_id);
4785 *params = client_id;
4786 } else {
4787 *params = 0;
4790 return true;
4791 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4792 *num_written = 1;
4793 if (params) {
4794 Framebuffer* framebuffer =
4795 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4796 if (framebuffer) {
4797 GLuint client_id = 0;
4798 framebuffer_manager()->GetClientId(
4799 framebuffer->service_id(), &client_id);
4800 *params = client_id;
4801 } else {
4802 *params = 0;
4805 return true;
4806 case GL_RENDERBUFFER_BINDING:
4807 *num_written = 1;
4808 if (params) {
4809 Renderbuffer* renderbuffer =
4810 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4811 if (renderbuffer) {
4812 *params = renderbuffer->client_id();
4813 } else {
4814 *params = 0;
4817 return true;
4818 case GL_CURRENT_PROGRAM:
4819 *num_written = 1;
4820 if (params) {
4821 if (state_.current_program.get()) {
4822 GLuint client_id = 0;
4823 program_manager()->GetClientId(
4824 state_.current_program->service_id(), &client_id);
4825 *params = client_id;
4826 } else {
4827 *params = 0;
4830 return true;
4831 case GL_VERTEX_ARRAY_BINDING_OES:
4832 *num_written = 1;
4833 if (params) {
4834 if (state_.vertex_attrib_manager.get() !=
4835 state_.default_vertex_attrib_manager.get()) {
4836 GLuint client_id = 0;
4837 vertex_array_manager_->GetClientId(
4838 state_.vertex_attrib_manager->service_id(), &client_id);
4839 *params = client_id;
4840 } else {
4841 *params = 0;
4844 return true;
4845 case GL_TEXTURE_BINDING_2D:
4846 *num_written = 1;
4847 if (params) {
4848 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4849 if (unit.bound_texture_2d.get()) {
4850 *params = unit.bound_texture_2d->client_id();
4851 } else {
4852 *params = 0;
4855 return true;
4856 case GL_TEXTURE_BINDING_CUBE_MAP:
4857 *num_written = 1;
4858 if (params) {
4859 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4860 if (unit.bound_texture_cube_map.get()) {
4861 *params = unit.bound_texture_cube_map->client_id();
4862 } else {
4863 *params = 0;
4866 return true;
4867 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4868 *num_written = 1;
4869 if (params) {
4870 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4871 if (unit.bound_texture_external_oes.get()) {
4872 *params = unit.bound_texture_external_oes->client_id();
4873 } else {
4874 *params = 0;
4877 return true;
4878 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4879 *num_written = 1;
4880 if (params) {
4881 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4882 if (unit.bound_texture_rectangle_arb.get()) {
4883 *params = unit.bound_texture_rectangle_arb->client_id();
4884 } else {
4885 *params = 0;
4888 return true;
4889 case GL_UNPACK_FLIP_Y_CHROMIUM:
4890 *num_written = 1;
4891 if (params) {
4892 params[0] = unpack_flip_y_;
4894 return true;
4895 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4896 *num_written = 1;
4897 if (params) {
4898 params[0] = unpack_premultiply_alpha_;
4900 return true;
4901 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4902 *num_written = 1;
4903 if (params) {
4904 params[0] = unpack_unpremultiply_alpha_;
4906 return true;
4907 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
4908 *num_written = 1;
4909 if (params) {
4910 params[0] = group_->bind_generates_resource() ? 1 : 0;
4912 return true;
4913 default:
4914 if (pname >= GL_DRAW_BUFFER0_ARB &&
4915 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4916 *num_written = 1;
4917 if (params) {
4918 Framebuffer* framebuffer =
4919 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4920 if (framebuffer) {
4921 params[0] = framebuffer->GetDrawBuffer(pname);
4922 } else { // backbuffer
4923 if (pname == GL_DRAW_BUFFER0_ARB)
4924 params[0] = group_->draw_buffer();
4925 else
4926 params[0] = GL_NONE;
4929 return true;
4931 *num_written = util_.GLGetNumValuesReturned(pname);
4932 return false;
4936 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4937 GLenum pname, GLsizei* num_values) {
4938 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
4939 return true;
4941 return GetHelper(pname, NULL, num_values);
4944 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4945 if (GL_MAX_SAMPLES == pname &&
4946 features().use_img_for_multisampled_render_to_texture) {
4947 return GL_MAX_SAMPLES_IMG;
4949 return pname;
4952 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4953 DCHECK(params);
4954 GLsizei num_written = 0;
4955 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
4956 scoped_ptr<GLint[]> values(new GLint[num_written]);
4957 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
4958 GetHelper(pname, values.get(), &num_written);
4960 for (GLsizei ii = 0; ii < num_written; ++ii) {
4961 params[ii] = static_cast<GLboolean>(values[ii]);
4963 } else {
4964 pname = AdjustGetPname(pname);
4965 glGetBooleanv(pname, params);
4969 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4970 DCHECK(params);
4971 GLsizei num_written = 0;
4972 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
4973 if (GetHelper(pname, NULL, &num_written)) {
4974 scoped_ptr<GLint[]> values(new GLint[num_written]);
4975 GetHelper(pname, values.get(), &num_written);
4976 for (GLsizei ii = 0; ii < num_written; ++ii) {
4977 params[ii] = static_cast<GLfloat>(values[ii]);
4979 } else {
4980 pname = AdjustGetPname(pname);
4981 glGetFloatv(pname, params);
4986 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4987 DCHECK(params);
4988 GLsizei num_written;
4989 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
4990 !GetHelper(pname, params, &num_written)) {
4991 pname = AdjustGetPname(pname);
4992 glGetIntegerv(pname, params);
4996 void GLES2DecoderImpl::DoGetProgramiv(
4997 GLuint program_id, GLenum pname, GLint* params) {
4998 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4999 if (!program) {
5000 return;
5002 program->GetProgramiv(pname, params);
5005 void GLES2DecoderImpl::DoGetBufferParameteriv(
5006 GLenum target, GLenum pname, GLint* params) {
5007 // Just delegate it. Some validation is actually done before this.
5008 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5009 &state_, target, pname, params);
5012 void GLES2DecoderImpl::DoBindAttribLocation(
5013 GLuint program_id, GLuint index, const char* name) {
5014 if (!StringIsValidForGLES(name)) {
5015 LOCAL_SET_GL_ERROR(
5016 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5017 return;
5019 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5020 LOCAL_SET_GL_ERROR(
5021 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5022 return;
5024 if (index >= group_->max_vertex_attribs()) {
5025 LOCAL_SET_GL_ERROR(
5026 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5027 return;
5029 Program* program = GetProgramInfoNotShader(
5030 program_id, "glBindAttribLocation");
5031 if (!program) {
5032 return;
5034 // At this point, the program's shaders may not be translated yet,
5035 // therefore, we may not find the hashed attribute name.
5036 // glBindAttribLocation call with original name is useless.
5037 // So instead, we should simply cache the binding, and then call
5038 // Program::ExecuteBindAttribLocationCalls() right before link.
5039 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5040 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5041 glBindAttribLocation(program->service_id(), index, name);
5044 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5045 uint32 immediate_data_size,
5046 const void* cmd_data) {
5047 const gles2::cmds::BindAttribLocationBucket& c =
5048 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5049 GLuint program = static_cast<GLuint>(c.program);
5050 GLuint index = static_cast<GLuint>(c.index);
5051 Bucket* bucket = GetBucket(c.name_bucket_id);
5052 if (!bucket || bucket->size() == 0) {
5053 return error::kInvalidArguments;
5055 std::string name_str;
5056 if (!bucket->GetAsString(&name_str)) {
5057 return error::kInvalidArguments;
5059 DoBindAttribLocation(program, index, name_str.c_str());
5060 return error::kNoError;
5063 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5064 GLuint program_id, GLint location, const char* name) {
5065 if (!StringIsValidForGLES(name)) {
5066 LOCAL_SET_GL_ERROR(
5067 GL_INVALID_VALUE,
5068 "glBindUniformLocationCHROMIUM", "Invalid character");
5069 return;
5071 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5072 LOCAL_SET_GL_ERROR(
5073 GL_INVALID_OPERATION,
5074 "glBindUniformLocationCHROMIUM", "reserved prefix");
5075 return;
5077 if (location < 0 || static_cast<uint32>(location) >=
5078 (group_->max_fragment_uniform_vectors() +
5079 group_->max_vertex_uniform_vectors()) * 4) {
5080 LOCAL_SET_GL_ERROR(
5081 GL_INVALID_VALUE,
5082 "glBindUniformLocationCHROMIUM", "location out of range");
5083 return;
5085 Program* program = GetProgramInfoNotShader(
5086 program_id, "glBindUniformLocationCHROMIUM");
5087 if (!program) {
5088 return;
5090 if (!program->SetUniformLocationBinding(name, location)) {
5091 LOCAL_SET_GL_ERROR(
5092 GL_INVALID_VALUE,
5093 "glBindUniformLocationCHROMIUM", "location out of range");
5097 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5098 uint32 immediate_data_size,
5099 const void* cmd_data) {
5100 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5101 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5102 cmd_data);
5103 GLuint program = static_cast<GLuint>(c.program);
5104 GLint location = static_cast<GLint>(c.location);
5105 Bucket* bucket = GetBucket(c.name_bucket_id);
5106 if (!bucket || bucket->size() == 0) {
5107 return error::kInvalidArguments;
5109 std::string name_str;
5110 if (!bucket->GetAsString(&name_str)) {
5111 return error::kInvalidArguments;
5113 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5114 return error::kNoError;
5117 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5118 const void* cmd_data) {
5119 const gles2::cmds::DeleteShader& c =
5120 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5121 GLuint client_id = c.shader;
5122 if (client_id) {
5123 Shader* shader = GetShader(client_id);
5124 if (shader) {
5125 if (!shader->IsDeleted()) {
5126 glDeleteShader(shader->service_id());
5127 shader_manager()->MarkAsDeleted(shader);
5129 } else {
5130 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5133 return error::kNoError;
5136 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5137 const void* cmd_data) {
5138 const gles2::cmds::DeleteProgram& c =
5139 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5140 GLuint client_id = c.program;
5141 if (client_id) {
5142 Program* program = GetProgram(client_id);
5143 if (program) {
5144 if (!program->IsDeleted()) {
5145 program_manager()->MarkAsDeleted(shader_manager(), program);
5147 } else {
5148 LOCAL_SET_GL_ERROR(
5149 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5152 return error::kNoError;
5155 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5156 DCHECK(!ShouldDeferDraws());
5157 if (CheckBoundFramebuffersValid("glClear")) {
5158 ApplyDirtyState();
5159 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5160 if (workarounds().gl_clear_broken) {
5161 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5162 GetErrorState());
5163 if (!BoundFramebufferHasDepthAttachment())
5164 mask &= ~GL_DEPTH_BUFFER_BIT;
5165 if (!BoundFramebufferHasStencilAttachment())
5166 mask &= ~GL_STENCIL_BUFFER_BIT;
5167 clear_framebuffer_blit_->ClearFramebuffer(
5168 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5169 state_.color_clear_green, state_.color_clear_blue,
5170 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5171 return error::kNoError;
5173 glClear(mask);
5175 return error::kNoError;
5178 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5179 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5180 GLuint client_renderbuffer_id) {
5181 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5182 if (!framebuffer) {
5183 LOCAL_SET_GL_ERROR(
5184 GL_INVALID_OPERATION,
5185 "glFramebufferRenderbuffer", "no framebuffer bound");
5186 return;
5188 GLuint service_id = 0;
5189 Renderbuffer* renderbuffer = NULL;
5190 if (client_renderbuffer_id) {
5191 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5192 if (!renderbuffer) {
5193 LOCAL_SET_GL_ERROR(
5194 GL_INVALID_OPERATION,
5195 "glFramebufferRenderbuffer", "unknown renderbuffer");
5196 return;
5198 service_id = renderbuffer->service_id();
5200 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5201 glFramebufferRenderbufferEXT(
5202 target, attachment, renderbuffertarget, service_id);
5203 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5204 if (error == GL_NO_ERROR) {
5205 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5207 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5208 framebuffer_state_.clear_state_dirty = true;
5210 OnFboChanged();
5213 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5214 if (SetCapabilityState(cap, false)) {
5215 glDisable(cap);
5219 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5220 if (SetCapabilityState(cap, true)) {
5221 glEnable(cap);
5225 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5226 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5227 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5228 glDepthRange(znear, zfar);
5231 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5232 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5233 state_.sample_coverage_invert = (invert != 0);
5234 glSampleCoverage(state_.sample_coverage_value, invert);
5237 // Assumes framebuffer is complete.
5238 void GLES2DecoderImpl::ClearUnclearedAttachments(
5239 GLenum target, Framebuffer* framebuffer) {
5240 if (target == GL_READ_FRAMEBUFFER_EXT) {
5241 // bind this to the DRAW point, clear then bind back to READ
5242 // TODO(gman): I don't think there is any guarantee that an FBO that
5243 // is complete on the READ attachment will be complete as a DRAW
5244 // attachment.
5245 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5246 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5248 GLbitfield clear_bits = 0;
5249 if (framebuffer->HasUnclearedColorAttachments()) {
5250 glClearColor(
5251 0.0f, 0.0f, 0.0f,
5252 (GLES2Util::GetChannelsForFormat(
5253 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
5254 1.0f);
5255 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5256 clear_bits |= GL_COLOR_BUFFER_BIT;
5257 if (feature_info_->feature_flags().ext_draw_buffers)
5258 framebuffer->PrepareDrawBuffersForClear();
5261 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5262 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5263 glClearStencil(0);
5264 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5265 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5266 clear_bits |= GL_STENCIL_BUFFER_BIT;
5269 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5270 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5271 glClearDepth(1.0f);
5272 state_.SetDeviceDepthMask(GL_TRUE);
5273 clear_bits |= GL_DEPTH_BUFFER_BIT;
5276 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5277 glClear(clear_bits);
5279 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5280 feature_info_->feature_flags().ext_draw_buffers)
5281 framebuffer->RestoreDrawBuffersAfterClear();
5283 framebuffer_manager()->MarkAttachmentsAsCleared(
5284 framebuffer, renderbuffer_manager(), texture_manager());
5286 RestoreClearState();
5288 if (target == GL_READ_FRAMEBUFFER_EXT) {
5289 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5290 Framebuffer* draw_framebuffer =
5291 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5292 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5293 GetBackbufferServiceId();
5294 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5298 void GLES2DecoderImpl::RestoreClearState() {
5299 framebuffer_state_.clear_state_dirty = true;
5300 glClearColor(
5301 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5302 state_.color_clear_alpha);
5303 glClearStencil(state_.stencil_clear);
5304 glClearDepth(state_.depth_clear);
5305 if (state_.enable_flags.scissor_test) {
5306 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5310 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5311 Framebuffer* framebuffer =
5312 GetFramebufferInfoForTarget(target);
5313 if (!framebuffer) {
5314 return GL_FRAMEBUFFER_COMPLETE;
5316 GLenum completeness = framebuffer->IsPossiblyComplete();
5317 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5318 return completeness;
5320 return framebuffer->GetStatus(texture_manager(), target);
5323 void GLES2DecoderImpl::DoFramebufferTexture2D(
5324 GLenum target, GLenum attachment, GLenum textarget,
5325 GLuint client_texture_id, GLint level) {
5326 DoFramebufferTexture2DCommon(
5327 "glFramebufferTexture2D", target, attachment,
5328 textarget, client_texture_id, level, 0);
5331 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5332 GLenum target, GLenum attachment, GLenum textarget,
5333 GLuint client_texture_id, GLint level, GLsizei samples) {
5334 DoFramebufferTexture2DCommon(
5335 "glFramebufferTexture2DMultisample", target, attachment,
5336 textarget, client_texture_id, level, samples);
5339 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5340 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5341 GLuint client_texture_id, GLint level, GLsizei samples) {
5342 if (samples > renderbuffer_manager()->max_samples()) {
5343 LOCAL_SET_GL_ERROR(
5344 GL_INVALID_VALUE,
5345 "glFramebufferTexture2DMultisample", "samples too large");
5346 return;
5348 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5349 if (!framebuffer) {
5350 LOCAL_SET_GL_ERROR(
5351 GL_INVALID_OPERATION,
5352 name, "no framebuffer bound.");
5353 return;
5355 GLuint service_id = 0;
5356 TextureRef* texture_ref = NULL;
5357 if (client_texture_id) {
5358 texture_ref = GetTexture(client_texture_id);
5359 if (!texture_ref) {
5360 LOCAL_SET_GL_ERROR(
5361 GL_INVALID_OPERATION,
5362 name, "unknown texture_ref");
5363 return;
5365 service_id = texture_ref->service_id();
5368 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5369 LOCAL_SET_GL_ERROR(
5370 GL_INVALID_VALUE,
5371 name, "level out of range");
5372 return;
5375 if (texture_ref)
5376 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5378 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5379 if (0 == samples) {
5380 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5381 } else {
5382 if (features().use_img_for_multisampled_render_to_texture) {
5383 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5384 service_id, level, samples);
5385 } else {
5386 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5387 service_id, level, samples);
5390 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5391 if (error == GL_NO_ERROR) {
5392 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5393 samples);
5395 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5396 framebuffer_state_.clear_state_dirty = true;
5399 if (texture_ref)
5400 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5402 OnFboChanged();
5405 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5406 GLenum target, GLenum attachment, GLuint client_texture_id,
5407 GLint level, GLint layer) {
5408 // TODO(zmo): Unsafe ES3 API, missing states update.
5409 GLuint service_id = 0;
5410 TextureRef* texture_ref = NULL;
5411 if (client_texture_id) {
5412 texture_ref = GetTexture(client_texture_id);
5413 if (!texture_ref) {
5414 LOCAL_SET_GL_ERROR(
5415 GL_INVALID_OPERATION,
5416 "glFramebufferTextureLayer", "unknown texture_ref");
5417 return;
5419 service_id = texture_ref->service_id();
5421 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5424 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5425 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5426 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5427 if (!framebuffer) {
5428 LOCAL_SET_GL_ERROR(
5429 GL_INVALID_OPERATION,
5430 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5431 return;
5433 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5434 const Framebuffer::Attachment* attachment_object =
5435 framebuffer->GetAttachment(attachment);
5436 *params = attachment_object ? attachment_object->object_name() : 0;
5437 } else {
5438 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5439 features().use_img_for_multisampled_render_to_texture) {
5440 pname = GL_TEXTURE_SAMPLES_IMG;
5442 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5446 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5447 GLenum target, GLenum pname, GLint* params) {
5448 Renderbuffer* renderbuffer =
5449 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5450 if (!renderbuffer) {
5451 LOCAL_SET_GL_ERROR(
5452 GL_INVALID_OPERATION,
5453 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5454 return;
5457 EnsureRenderbufferBound();
5458 switch (pname) {
5459 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5460 *params = renderbuffer->internal_format();
5461 break;
5462 case GL_RENDERBUFFER_WIDTH:
5463 *params = renderbuffer->width();
5464 break;
5465 case GL_RENDERBUFFER_HEIGHT:
5466 *params = renderbuffer->height();
5467 break;
5468 case GL_RENDERBUFFER_SAMPLES_EXT:
5469 if (features().use_img_for_multisampled_render_to_texture) {
5470 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5471 params);
5472 } else {
5473 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5474 params);
5476 default:
5477 glGetRenderbufferParameterivEXT(target, pname, params);
5478 break;
5482 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5483 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5484 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5485 GLbitfield mask, GLenum filter) {
5486 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5488 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5489 return;
5492 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5493 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5494 BlitFramebufferHelper(
5495 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5496 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5497 state_.enable_flags.scissor_test);
5500 void GLES2DecoderImpl::EnsureRenderbufferBound() {
5501 if (!state_.bound_renderbuffer_valid) {
5502 state_.bound_renderbuffer_valid = true;
5503 glBindRenderbufferEXT(GL_RENDERBUFFER,
5504 state_.bound_renderbuffer.get()
5505 ? state_.bound_renderbuffer->service_id()
5506 : 0);
5510 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
5511 const FeatureInfo* feature_info,
5512 GLenum target,
5513 GLsizei samples,
5514 GLenum internal_format,
5515 GLsizei width,
5516 GLsizei height) {
5517 // TODO(sievers): This could be resolved at the GL binding level, but the
5518 // binding process is currently a bit too 'brute force'.
5519 if (feature_info->gl_version_info().is_angle) {
5520 glRenderbufferStorageMultisampleANGLE(
5521 target, samples, internal_format, width, height);
5522 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
5523 glRenderbufferStorageMultisample(
5524 target, samples, internal_format, width, height);
5525 } else {
5526 glRenderbufferStorageMultisampleEXT(
5527 target, samples, internal_format, width, height);
5531 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
5532 GLint srcY0,
5533 GLint srcX1,
5534 GLint srcY1,
5535 GLint dstX0,
5536 GLint dstY0,
5537 GLint dstX1,
5538 GLint dstY1,
5539 GLbitfield mask,
5540 GLenum filter) {
5541 // TODO(sievers): This could be resolved at the GL binding level, but the
5542 // binding process is currently a bit too 'brute force'.
5543 if (feature_info_->gl_version_info().is_angle) {
5544 glBlitFramebufferANGLE(
5545 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5546 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
5547 glBlitFramebuffer(
5548 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5549 } else {
5550 glBlitFramebufferEXT(
5551 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5555 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
5556 GLsizei samples,
5557 GLenum internalformat,
5558 GLsizei width,
5559 GLsizei height) {
5560 if (samples > renderbuffer_manager()->max_samples()) {
5561 LOCAL_SET_GL_ERROR(
5562 GL_INVALID_VALUE,
5563 "glRenderbufferStorageMultisample", "samples too large");
5564 return false;
5567 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5568 height > renderbuffer_manager()->max_renderbuffer_size()) {
5569 LOCAL_SET_GL_ERROR(
5570 GL_INVALID_VALUE,
5571 "glRenderbufferStorageMultisample", "dimensions too large");
5572 return false;
5575 uint32 estimated_size = 0;
5576 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5577 width, height, samples, internalformat, &estimated_size)) {
5578 LOCAL_SET_GL_ERROR(
5579 GL_OUT_OF_MEMORY,
5580 "glRenderbufferStorageMultisample", "dimensions too large");
5581 return false;
5584 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5585 LOCAL_SET_GL_ERROR(
5586 GL_OUT_OF_MEMORY,
5587 "glRenderbufferStorageMultisample", "out of memory");
5588 return false;
5591 return true;
5594 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
5595 GLenum target, GLsizei samples, GLenum internalformat,
5596 GLsizei width, GLsizei height) {
5597 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5598 if (!renderbuffer) {
5599 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5600 "glRenderbufferStorageMultisampleCHROMIUM",
5601 "no renderbuffer bound");
5602 return;
5605 if (!ValidateRenderbufferStorageMultisample(
5606 samples, internalformat, width, height)) {
5607 return;
5610 EnsureRenderbufferBound();
5611 GLenum impl_format =
5612 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5613 internalformat);
5614 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
5615 "glRenderbufferStorageMultisampleCHROMIUM");
5616 RenderbufferStorageMultisampleHelper(
5617 feature_info_.get(), target, samples, impl_format, width, height);
5618 GLenum error =
5619 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
5620 if (error == GL_NO_ERROR) {
5622 if (workarounds().validate_multisample_buffer_allocation) {
5623 if (!VerifyMultisampleRenderbufferIntegrity(
5624 renderbuffer->service_id(), impl_format)) {
5625 LOCAL_SET_GL_ERROR(
5626 GL_OUT_OF_MEMORY,
5627 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
5628 return;
5632 // TODO(gman): If renderbuffers tracked which framebuffers they were
5633 // attached to we could just mark those framebuffers as not complete.
5634 framebuffer_manager()->IncFramebufferStateChangeCount();
5635 renderbuffer_manager()->SetInfo(
5636 renderbuffer, samples, internalformat, width, height);
5640 // This is the handler for multisampled_render_to_texture extensions.
5641 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
5642 GLenum target, GLsizei samples, GLenum internalformat,
5643 GLsizei width, GLsizei height) {
5644 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5645 if (!renderbuffer) {
5646 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
5647 "glRenderbufferStorageMultisampleEXT",
5648 "no renderbuffer bound");
5649 return;
5652 if (!ValidateRenderbufferStorageMultisample(
5653 samples, internalformat, width, height)) {
5654 return;
5657 EnsureRenderbufferBound();
5658 GLenum impl_format =
5659 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5660 internalformat);
5661 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
5662 if (features().use_img_for_multisampled_render_to_texture) {
5663 glRenderbufferStorageMultisampleIMG(
5664 target, samples, impl_format, width, height);
5665 } else {
5666 glRenderbufferStorageMultisampleEXT(
5667 target, samples, impl_format, width, height);
5669 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
5670 if (error == GL_NO_ERROR) {
5671 // TODO(gman): If renderbuffers tracked which framebuffers they were
5672 // attached to we could just mark those framebuffers as not complete.
5673 framebuffer_manager()->IncFramebufferStateChangeCount();
5674 renderbuffer_manager()->SetInfo(
5675 renderbuffer, samples, internalformat, width, height);
5679 // This function validates the allocation of a multisampled renderbuffer
5680 // by clearing it to a key color, blitting the contents to a texture, and
5681 // reading back the color to ensure it matches the key.
5682 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5683 GLuint renderbuffer, GLenum format) {
5685 // Only validate color buffers.
5686 // These formats have been selected because they are very common or are known
5687 // to be used by the WebGL backbuffer. If problems are observed with other
5688 // color formats they can be added here.
5689 switch(format) {
5690 case GL_RGB:
5691 case GL_RGB8:
5692 case GL_RGBA:
5693 case GL_RGBA8:
5694 break;
5695 default:
5696 return true;
5699 GLint draw_framebuffer, read_framebuffer;
5701 // Cache framebuffer and texture bindings.
5702 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5703 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5705 if (!validation_texture_) {
5706 GLint bound_texture;
5707 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5709 // Create additional resources needed for the verification.
5710 glGenTextures(1, &validation_texture_);
5711 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5712 glGenFramebuffersEXT(1, &validation_fbo_);
5714 // Texture only needs to be 1x1.
5715 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5716 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5717 GL_UNSIGNED_BYTE, NULL);
5719 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5720 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5721 GL_TEXTURE_2D, validation_texture_, 0);
5723 glBindTexture(GL_TEXTURE_2D, bound_texture);
5726 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5727 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5728 GL_RENDERBUFFER, renderbuffer);
5730 // Cache current state and reset it to the values we require.
5731 GLboolean scissor_enabled = false;
5732 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5733 if (scissor_enabled)
5734 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5736 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
5737 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5738 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5740 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5741 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5742 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5744 // Clear the buffer to the desired key color.
5745 glClear(GL_COLOR_BUFFER_BIT);
5747 // Blit from the multisample buffer to a standard texture.
5748 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5749 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5751 BlitFramebufferHelper(
5752 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5754 // Read a pixel from the buffer.
5755 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5757 unsigned char pixel[3] = {0, 0, 0};
5758 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5760 // Detach the renderbuffer.
5761 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5762 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5763 GL_RENDERBUFFER, 0);
5765 // Restore cached state.
5766 if (scissor_enabled)
5767 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
5769 state_.SetDeviceColorMask(
5770 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5771 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5772 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5773 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5775 // Return true if the pixel matched the desired key color.
5776 return (pixel[0] == 0xFF &&
5777 pixel[1] == 0x00 &&
5778 pixel[2] == 0xFF);
5781 void GLES2DecoderImpl::DoRenderbufferStorage(
5782 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
5783 Renderbuffer* renderbuffer =
5784 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5785 if (!renderbuffer) {
5786 LOCAL_SET_GL_ERROR(
5787 GL_INVALID_OPERATION,
5788 "glRenderbufferStorage", "no renderbuffer bound");
5789 return;
5792 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5793 height > renderbuffer_manager()->max_renderbuffer_size()) {
5794 LOCAL_SET_GL_ERROR(
5795 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
5796 return;
5799 uint32 estimated_size = 0;
5800 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5801 width, height, 1, internalformat, &estimated_size)) {
5802 LOCAL_SET_GL_ERROR(
5803 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5804 return;
5807 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5808 LOCAL_SET_GL_ERROR(
5809 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5810 return;
5813 EnsureRenderbufferBound();
5814 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5815 glRenderbufferStorageEXT(
5816 target,
5817 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5818 internalformat),
5819 width,
5820 height);
5821 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
5822 if (error == GL_NO_ERROR) {
5823 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5824 // we could just mark those framebuffers as not complete.
5825 framebuffer_manager()->IncFramebufferStateChangeCount();
5826 renderbuffer_manager()->SetInfo(
5827 renderbuffer, 1, internalformat, width, height);
5831 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
5832 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
5833 Program* program = GetProgramInfoNotShader(
5834 program_id, "glLinkProgram");
5835 if (!program) {
5836 return;
5839 LogClientServiceForInfo(program, program_id, "glLinkProgram");
5840 ShaderTranslator* vertex_translator = NULL;
5841 ShaderTranslator* fragment_translator = NULL;
5842 if (use_shader_translator_) {
5843 vertex_translator = vertex_translator_.get();
5844 fragment_translator = fragment_translator_.get();
5846 if (program->Link(shader_manager(),
5847 vertex_translator,
5848 fragment_translator,
5849 workarounds().count_all_in_varyings_packing ?
5850 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
5851 shader_cache_callback_)) {
5852 if (program == state_.current_program.get()) {
5853 if (workarounds().use_current_program_after_successful_link)
5854 glUseProgram(program->service_id());
5855 if (workarounds().clear_uniforms_before_first_program_use)
5856 program_manager()->ClearUniforms(program);
5860 // LinkProgram can be very slow. Exit command processing to allow for
5861 // context preemption and GPU watchdog checks.
5862 ExitCommandProcessingEarly();
5865 void GLES2DecoderImpl::DoSamplerParameterfv(
5866 GLuint sampler, GLenum pname, const GLfloat* params) {
5867 DCHECK(params);
5868 glSamplerParameterf(sampler, pname, params[0]);
5871 void GLES2DecoderImpl::DoSamplerParameteriv(
5872 GLuint sampler, GLenum pname, const GLint* params) {
5873 DCHECK(params);
5874 glSamplerParameteri(sampler, pname, params[0]);
5877 void GLES2DecoderImpl::DoTexParameterf(
5878 GLenum target, GLenum pname, GLfloat param) {
5879 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5880 &state_, target);
5881 if (!texture) {
5882 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
5883 return;
5886 texture_manager()->SetParameterf(
5887 "glTexParameterf", GetErrorState(), texture, pname, param);
5890 void GLES2DecoderImpl::DoTexParameteri(
5891 GLenum target, GLenum pname, GLint param) {
5892 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5893 &state_, target);
5894 if (!texture) {
5895 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
5896 return;
5899 texture_manager()->SetParameteri(
5900 "glTexParameteri", GetErrorState(), texture, pname, param);
5903 void GLES2DecoderImpl::DoTexParameterfv(
5904 GLenum target, GLenum pname, const GLfloat* params) {
5905 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5906 &state_, target);
5907 if (!texture) {
5908 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
5909 return;
5912 texture_manager()->SetParameterf(
5913 "glTexParameterfv", GetErrorState(), texture, pname, *params);
5916 void GLES2DecoderImpl::DoTexParameteriv(
5917 GLenum target, GLenum pname, const GLint* params) {
5918 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5919 &state_, target);
5920 if (!texture) {
5921 LOCAL_SET_GL_ERROR(
5922 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
5923 return;
5926 texture_manager()->SetParameteri(
5927 "glTexParameteriv", GetErrorState(), texture, pname, *params);
5930 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
5931 if (!state_.bound_valuebuffer.get()) {
5932 // There is no valuebuffer bound
5933 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
5934 "no valuebuffer in use");
5935 return false;
5937 return true;
5940 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
5941 GLenum subscription,
5942 const char* function_name) {
5943 if (!CheckCurrentValuebuffer(function_name)) {
5944 return false;
5946 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
5947 // The valuebuffer is not subscribed to the target
5948 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
5949 "valuebuffer is not subscribed");
5950 return false;
5952 return true;
5955 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
5956 GLenum subscription,
5957 const char* function_name) {
5958 if (!CheckCurrentProgramForUniform(location, function_name)) {
5959 return false;
5961 GLint real_location = -1;
5962 GLint array_index = -1;
5963 const Program::UniformInfo* info =
5964 state_.current_program->GetUniformInfoByFakeLocation(
5965 location, &real_location, &array_index);
5966 if (!info) {
5967 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
5968 return false;
5970 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
5971 info->accepts_api_type) == 0) {
5972 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
5973 "wrong type for subscription");
5974 return false;
5976 return true;
5979 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
5980 if (!state_.current_program.get()) {
5981 // The program does not exist.
5982 LOCAL_SET_GL_ERROR(
5983 GL_INVALID_OPERATION, function_name, "no program in use");
5984 return false;
5986 if (!state_.current_program->InUse()) {
5987 LOCAL_SET_GL_ERROR(
5988 GL_INVALID_OPERATION, function_name, "program not linked");
5989 return false;
5991 return true;
5994 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5995 GLint location, const char* function_name) {
5996 if (!CheckCurrentProgram(function_name)) {
5997 return false;
5999 return location != -1;
6002 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6003 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6004 if (!framebuffer)
6005 return false;
6006 const Framebuffer::Attachment* attachment =
6007 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6008 if (!attachment)
6009 return false;
6011 DCHECK(state_.current_program.get());
6012 const Program::SamplerIndices& sampler_indices =
6013 state_.current_program->sampler_indices();
6014 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6015 const Program::UniformInfo* uniform_info =
6016 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6017 DCHECK(uniform_info);
6018 if (uniform_info->type != GL_SAMPLER_2D)
6019 continue;
6020 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6021 GLuint texture_unit_index = uniform_info->texture_units[jj];
6022 if (texture_unit_index >= state_.texture_units.size())
6023 continue;
6024 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6025 TextureRef* texture_ref =
6026 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6027 if (attachment->IsTexture(texture_ref))
6028 return true;
6031 return false;
6034 bool GLES2DecoderImpl::CheckUniformForApiType(
6035 const Program::UniformInfo* info,
6036 const char* function_name,
6037 Program::UniformApiType api_type) {
6038 DCHECK(info);
6039 if ((api_type & info->accepts_api_type) == 0) {
6040 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6041 "wrong uniform function for type");
6042 return false;
6044 return true;
6047 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6048 GLint fake_location,
6049 const char* function_name,
6050 Program::UniformApiType api_type,
6051 GLint* real_location,
6052 GLenum* type,
6053 GLsizei* count) {
6054 DCHECK(type);
6055 DCHECK(count);
6056 DCHECK(real_location);
6058 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6059 return false;
6061 GLint array_index = -1;
6062 const Program::UniformInfo* info =
6063 state_.current_program->GetUniformInfoByFakeLocation(
6064 fake_location, real_location, &array_index);
6065 if (!info) {
6066 LOCAL_SET_GL_ERROR(
6067 GL_INVALID_OPERATION, function_name, "unknown location");
6068 return false;
6070 if (!CheckUniformForApiType(info, function_name, api_type)) {
6071 return false;
6073 if (*count > 1 && !info->is_array) {
6074 LOCAL_SET_GL_ERROR(
6075 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6076 return false;
6078 *count = std::min(info->size - array_index, *count);
6079 if (*count <= 0) {
6080 return false;
6082 *type = info->type;
6083 return true;
6086 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6087 GLenum type = 0;
6088 GLsizei count = 1;
6089 GLint real_location = -1;
6090 if (!PrepForSetUniformByLocation(fake_location,
6091 "glUniform1i",
6092 Program::kUniform1i,
6093 &real_location,
6094 &type,
6095 &count)) {
6096 return;
6098 if (!state_.current_program->SetSamplers(
6099 state_.texture_units.size(), fake_location, 1, &v0)) {
6100 LOCAL_SET_GL_ERROR(
6101 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6102 return;
6104 glUniform1i(real_location, v0);
6107 void GLES2DecoderImpl::DoUniform1iv(
6108 GLint fake_location, GLsizei count, const GLint *value) {
6109 GLenum type = 0;
6110 GLint real_location = -1;
6111 if (!PrepForSetUniformByLocation(fake_location,
6112 "glUniform1iv",
6113 Program::kUniform1i,
6114 &real_location,
6115 &type,
6116 &count)) {
6117 return;
6119 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6120 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6121 if (!state_.current_program->SetSamplers(
6122 state_.texture_units.size(), fake_location, count, value)) {
6123 LOCAL_SET_GL_ERROR(
6124 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6125 return;
6128 glUniform1iv(real_location, count, value);
6131 void GLES2DecoderImpl::DoUniform1fv(
6132 GLint fake_location, GLsizei count, const GLfloat* value) {
6133 GLenum type = 0;
6134 GLint real_location = -1;
6135 if (!PrepForSetUniformByLocation(fake_location,
6136 "glUniform1fv",
6137 Program::kUniform1f,
6138 &real_location,
6139 &type,
6140 &count)) {
6141 return;
6143 if (type == GL_BOOL) {
6144 scoped_ptr<GLint[]> temp(new GLint[count]);
6145 for (GLsizei ii = 0; ii < count; ++ii) {
6146 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6148 DoUniform1iv(real_location, count, temp.get());
6149 } else {
6150 glUniform1fv(real_location, count, value);
6154 void GLES2DecoderImpl::DoUniform2fv(
6155 GLint fake_location, GLsizei count, const GLfloat* value) {
6156 GLenum type = 0;
6157 GLint real_location = -1;
6158 if (!PrepForSetUniformByLocation(fake_location,
6159 "glUniform2fv",
6160 Program::kUniform2f,
6161 &real_location,
6162 &type,
6163 &count)) {
6164 return;
6166 if (type == GL_BOOL_VEC2) {
6167 GLsizei num_values = count * 2;
6168 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6169 for (GLsizei ii = 0; ii < num_values; ++ii) {
6170 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6172 glUniform2iv(real_location, count, temp.get());
6173 } else {
6174 glUniform2fv(real_location, count, value);
6178 void GLES2DecoderImpl::DoUniform3fv(
6179 GLint fake_location, GLsizei count, const GLfloat* value) {
6180 GLenum type = 0;
6181 GLint real_location = -1;
6182 if (!PrepForSetUniformByLocation(fake_location,
6183 "glUniform3fv",
6184 Program::kUniform3f,
6185 &real_location,
6186 &type,
6187 &count)) {
6188 return;
6190 if (type == GL_BOOL_VEC3) {
6191 GLsizei num_values = count * 3;
6192 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6193 for (GLsizei ii = 0; ii < num_values; ++ii) {
6194 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6196 glUniform3iv(real_location, count, temp.get());
6197 } else {
6198 glUniform3fv(real_location, count, value);
6202 void GLES2DecoderImpl::DoUniform4fv(
6203 GLint fake_location, GLsizei count, const GLfloat* value) {
6204 GLenum type = 0;
6205 GLint real_location = -1;
6206 if (!PrepForSetUniformByLocation(fake_location,
6207 "glUniform4fv",
6208 Program::kUniform4f,
6209 &real_location,
6210 &type,
6211 &count)) {
6212 return;
6214 if (type == GL_BOOL_VEC4) {
6215 GLsizei num_values = count * 4;
6216 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6217 for (GLsizei ii = 0; ii < num_values; ++ii) {
6218 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6220 glUniform4iv(real_location, count, temp.get());
6221 } else {
6222 glUniform4fv(real_location, count, value);
6226 void GLES2DecoderImpl::DoUniform2iv(
6227 GLint fake_location, GLsizei count, const GLint* value) {
6228 GLenum type = 0;
6229 GLint real_location = -1;
6230 if (!PrepForSetUniformByLocation(fake_location,
6231 "glUniform2iv",
6232 Program::kUniform2i,
6233 &real_location,
6234 &type,
6235 &count)) {
6236 return;
6238 glUniform2iv(real_location, count, value);
6241 void GLES2DecoderImpl::DoUniform3iv(
6242 GLint fake_location, GLsizei count, const GLint* value) {
6243 GLenum type = 0;
6244 GLint real_location = -1;
6245 if (!PrepForSetUniformByLocation(fake_location,
6246 "glUniform3iv",
6247 Program::kUniform3i,
6248 &real_location,
6249 &type,
6250 &count)) {
6251 return;
6253 glUniform3iv(real_location, count, value);
6256 void GLES2DecoderImpl::DoUniform4iv(
6257 GLint fake_location, GLsizei count, const GLint* value) {
6258 GLenum type = 0;
6259 GLint real_location = -1;
6260 if (!PrepForSetUniformByLocation(fake_location,
6261 "glUniform4iv",
6262 Program::kUniform4i,
6263 &real_location,
6264 &type,
6265 &count)) {
6266 return;
6268 glUniform4iv(real_location, count, value);
6271 void GLES2DecoderImpl::DoUniformMatrix2fv(
6272 GLint fake_location, GLsizei count, GLboolean transpose,
6273 const GLfloat* value) {
6274 GLenum type = 0;
6275 GLint real_location = -1;
6276 if (!PrepForSetUniformByLocation(fake_location,
6277 "glUniformMatrix2fv",
6278 Program::kUniformMatrix2f,
6279 &real_location,
6280 &type,
6281 &count)) {
6282 return;
6284 glUniformMatrix2fv(real_location, count, transpose, value);
6287 void GLES2DecoderImpl::DoUniformMatrix3fv(
6288 GLint fake_location, GLsizei count, GLboolean transpose,
6289 const GLfloat* value) {
6290 GLenum type = 0;
6291 GLint real_location = -1;
6292 if (!PrepForSetUniformByLocation(fake_location,
6293 "glUniformMatrix3fv",
6294 Program::kUniformMatrix3f,
6295 &real_location,
6296 &type,
6297 &count)) {
6298 return;
6300 glUniformMatrix3fv(real_location, count, transpose, value);
6303 void GLES2DecoderImpl::DoUniformMatrix4fv(
6304 GLint fake_location, GLsizei count, GLboolean transpose,
6305 const GLfloat* value) {
6306 GLenum type = 0;
6307 GLint real_location = -1;
6308 if (!PrepForSetUniformByLocation(fake_location,
6309 "glUniformMatrix4fv",
6310 Program::kUniformMatrix4f,
6311 &real_location,
6312 &type,
6313 &count)) {
6314 return;
6316 glUniformMatrix4fv(real_location, count, transpose, value);
6319 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6320 GLuint service_id = 0;
6321 Program* program = NULL;
6322 if (program_id) {
6323 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6324 if (!program) {
6325 return;
6327 if (!program->IsValid()) {
6328 // Program was not linked successfully. (ie, glLinkProgram)
6329 LOCAL_SET_GL_ERROR(
6330 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6331 return;
6333 service_id = program->service_id();
6335 if (state_.current_program.get()) {
6336 program_manager()->UnuseProgram(shader_manager(),
6337 state_.current_program.get());
6339 state_.current_program = program;
6340 LogClientServiceMapping("glUseProgram", program_id, service_id);
6341 glUseProgram(service_id);
6342 if (state_.current_program.get()) {
6343 program_manager()->UseProgram(state_.current_program.get());
6344 if (workarounds().clear_uniforms_before_first_program_use)
6345 program_manager()->ClearUniforms(program);
6349 void GLES2DecoderImpl::RenderWarning(
6350 const char* filename, int line, const std::string& msg) {
6351 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6354 void GLES2DecoderImpl::PerformanceWarning(
6355 const char* filename, int line, const std::string& msg) {
6356 logger_.LogMessage(filename, line,
6357 std::string("PERFORMANCE WARNING: ") + msg);
6360 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6361 Texture* texture, GLenum textarget) {
6362 // Image is already in use if texture is attached to a framebuffer.
6363 if (texture && !texture->IsAttachedToFramebuffer()) {
6364 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6365 if (image) {
6366 ScopedGLErrorSuppressor suppressor(
6367 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6368 GetErrorState());
6369 glBindTexture(textarget, texture->service_id());
6370 image->WillUseTexImage();
6371 RestoreCurrentTextureBindings(&state_, textarget);
6376 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6377 Texture* texture, GLenum textarget) {
6378 // Image is still in use if texture is attached to a framebuffer.
6379 if (texture && !texture->IsAttachedToFramebuffer()) {
6380 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6381 if (image) {
6382 ScopedGLErrorSuppressor suppressor(
6383 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6384 GetErrorState());
6385 glBindTexture(textarget, texture->service_id());
6386 image->DidUseTexImage();
6387 RestoreCurrentTextureBindings(&state_, textarget);
6392 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6393 DCHECK(state_.current_program.get());
6394 if (!texture_manager()->HaveUnrenderableTextures() &&
6395 !texture_manager()->HaveImages()) {
6396 return true;
6399 bool textures_set = false;
6400 const Program::SamplerIndices& sampler_indices =
6401 state_.current_program->sampler_indices();
6402 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6403 const Program::UniformInfo* uniform_info =
6404 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6405 DCHECK(uniform_info);
6406 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6407 GLuint texture_unit_index = uniform_info->texture_units[jj];
6408 if (texture_unit_index < state_.texture_units.size()) {
6409 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6410 TextureRef* texture_ref =
6411 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6412 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6413 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6414 textures_set = true;
6415 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6416 glBindTexture(
6417 textarget,
6418 texture_manager()->black_texture_id(uniform_info->type));
6419 if (!texture_ref) {
6420 LOCAL_RENDER_WARNING(
6421 std::string("there is no texture bound to the unit ") +
6422 base::IntToString(texture_unit_index));
6423 } else {
6424 LOCAL_RENDER_WARNING(
6425 std::string("texture bound to texture unit ") +
6426 base::IntToString(texture_unit_index) +
6427 " is not renderable. It maybe non-power-of-2 and have"
6428 " incompatible texture filtering.");
6430 continue;
6433 if (textarget != GL_TEXTURE_CUBE_MAP) {
6434 Texture* texture = texture_ref->texture();
6435 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6436 if (image && !texture->IsAttachedToFramebuffer()) {
6437 ScopedGLErrorSuppressor suppressor(
6438 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6439 textures_set = true;
6440 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6441 image->WillUseTexImage();
6442 continue;
6446 // else: should this be an error?
6449 return !textures_set;
6452 void GLES2DecoderImpl::RestoreStateForTextures() {
6453 DCHECK(state_.current_program.get());
6454 const Program::SamplerIndices& sampler_indices =
6455 state_.current_program->sampler_indices();
6456 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6457 const Program::UniformInfo* uniform_info =
6458 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6459 DCHECK(uniform_info);
6460 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6461 GLuint texture_unit_index = uniform_info->texture_units[jj];
6462 if (texture_unit_index < state_.texture_units.size()) {
6463 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6464 TextureRef* texture_ref =
6465 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6466 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6467 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6468 // Get the texture_ref info that was previously bound here.
6469 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
6470 ? texture_unit.bound_texture_2d.get()
6471 : texture_unit.bound_texture_cube_map.get();
6472 glBindTexture(texture_unit.bind_target,
6473 texture_ref ? texture_ref->service_id() : 0);
6474 continue;
6477 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
6478 Texture* texture = texture_ref->texture();
6479 gfx::GLImage* image =
6480 texture->GetLevelImage(texture_unit.bind_target, 0);
6481 if (image && !texture->IsAttachedToFramebuffer()) {
6482 ScopedGLErrorSuppressor suppressor(
6483 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
6484 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6485 image->DidUseTexImage();
6486 continue;
6492 // Set the active texture back to whatever the user had it as.
6493 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
6496 bool GLES2DecoderImpl::ClearUnclearedTextures() {
6497 // Only check if there are some uncleared textures.
6498 if (!texture_manager()->HaveUnsafeTextures()) {
6499 return true;
6502 // 1: Check all textures we are about to render with.
6503 if (state_.current_program.get()) {
6504 const Program::SamplerIndices& sampler_indices =
6505 state_.current_program->sampler_indices();
6506 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6507 const Program::UniformInfo* uniform_info =
6508 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6509 DCHECK(uniform_info);
6510 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6511 GLuint texture_unit_index = uniform_info->texture_units[jj];
6512 if (texture_unit_index < state_.texture_units.size()) {
6513 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6514 TextureRef* texture_ref =
6515 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6516 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
6517 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
6518 return false;
6525 return true;
6528 bool GLES2DecoderImpl::IsDrawValid(
6529 const char* function_name, GLuint max_vertex_accessed, bool instanced,
6530 GLsizei primcount) {
6531 DCHECK(instanced || primcount == 1);
6533 // NOTE: We specifically do not check current_program->IsValid() because
6534 // it could never be invalid since glUseProgram would have failed. While
6535 // glLinkProgram could later mark the program as invalid the previous
6536 // valid program will still function if it is still the current program.
6537 if (!state_.current_program.get()) {
6538 // The program does not exist.
6539 // But GL says no ERROR.
6540 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
6541 return false;
6544 if (CheckDrawingFeedbackLoops()) {
6545 LOCAL_SET_GL_ERROR(
6546 GL_INVALID_OPERATION, function_name,
6547 "Source and destination textures of the draw are the same.");
6548 return false;
6551 return state_.vertex_attrib_manager
6552 ->ValidateBindings(function_name,
6553 this,
6554 feature_info_.get(),
6555 state_.current_program.get(),
6556 max_vertex_accessed,
6557 instanced,
6558 primcount);
6561 bool GLES2DecoderImpl::SimulateAttrib0(
6562 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
6563 DCHECK(simulated);
6564 *simulated = false;
6566 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6567 return true;
6569 const VertexAttrib* attrib =
6570 state_.vertex_attrib_manager->GetVertexAttrib(0);
6571 // If it's enabled or it's not used then we don't need to do anything.
6572 bool attrib_0_used =
6573 state_.current_program->GetAttribInfoByLocation(0) != NULL;
6574 if (attrib->enabled() && attrib_0_used) {
6575 return true;
6578 // Make a buffer with a single repeated vec4 value enough to
6579 // simulate the constant value that is supposed to be here.
6580 // This is required to emulate GLES2 on GL.
6581 GLuint num_vertices = max_vertex_accessed + 1;
6582 uint32 size_needed = 0;
6584 if (num_vertices == 0 ||
6585 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
6586 size_needed > 0x7FFFFFFFU) {
6587 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6588 return false;
6591 LOCAL_PERFORMANCE_WARNING(
6592 "Attribute 0 is disabled. This has signficant performance penalty");
6594 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6595 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
6597 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
6598 if (new_buffer) {
6599 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6600 GLenum error = glGetError();
6601 if (error != GL_NO_ERROR) {
6602 LOCAL_SET_GL_ERROR(
6603 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6604 return false;
6608 const Vec4& value = state_.attrib_values[0];
6609 if (new_buffer ||
6610 (attrib_0_used &&
6611 (!attrib_0_buffer_matches_value_ ||
6612 (value.v[0] != attrib_0_value_.v[0] ||
6613 value.v[1] != attrib_0_value_.v[1] ||
6614 value.v[2] != attrib_0_value_.v[2] ||
6615 value.v[3] != attrib_0_value_.v[3])))) {
6616 std::vector<Vec4> temp(num_vertices, value);
6617 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
6618 attrib_0_buffer_matches_value_ = true;
6619 attrib_0_value_ = value;
6620 attrib_0_size_ = size_needed;
6623 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6625 if (attrib->divisor())
6626 glVertexAttribDivisorANGLE(0, 0);
6628 *simulated = true;
6629 return true;
6632 void GLES2DecoderImpl::RestoreStateForAttrib(
6633 GLuint attrib_index, bool restore_array_binding) {
6634 const VertexAttrib* attrib =
6635 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
6636 if (restore_array_binding) {
6637 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
6638 Buffer* buffer = attrib->buffer();
6639 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
6640 glVertexAttribPointer(
6641 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
6642 attrib->gl_stride(), ptr);
6644 if (attrib->divisor())
6645 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
6646 glBindBuffer(
6647 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
6648 state_.bound_array_buffer->service_id() : 0);
6650 // Never touch vertex attribute 0's state (in particular, never
6651 // disable it) when running on desktop GL because it will never be
6652 // re-enabled.
6653 if (attrib_index != 0 ||
6654 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
6655 if (attrib->enabled()) {
6656 glEnableVertexAttribArray(attrib_index);
6657 } else {
6658 glDisableVertexAttribArray(attrib_index);
6663 bool GLES2DecoderImpl::SimulateFixedAttribs(
6664 const char* function_name,
6665 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
6666 DCHECK(simulated);
6667 *simulated = false;
6668 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
6669 return true;
6671 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
6672 return true;
6675 LOCAL_PERFORMANCE_WARNING(
6676 "GL_FIXED attributes have a signficant performance penalty");
6678 // NOTE: we could be smart and try to check if a buffer is used
6679 // twice in 2 different attribs, find the overlapping parts and therefore
6680 // duplicate the minimum amount of data but this whole code path is not meant
6681 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6682 // tests so we just add to the buffer attrib used.
6684 GLuint elements_needed = 0;
6685 const VertexAttribManager::VertexAttribList& enabled_attribs =
6686 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6687 for (VertexAttribManager::VertexAttribList::const_iterator it =
6688 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6689 const VertexAttrib* attrib = *it;
6690 const Program::VertexAttrib* attrib_info =
6691 state_.current_program->GetAttribInfoByLocation(attrib->index());
6692 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6693 max_vertex_accessed);
6694 GLuint num_vertices = max_accessed + 1;
6695 if (num_vertices == 0) {
6696 LOCAL_SET_GL_ERROR(
6697 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6698 return false;
6700 if (attrib_info &&
6701 attrib->CanAccess(max_accessed) &&
6702 attrib->type() == GL_FIXED) {
6703 uint32 elements_used = 0;
6704 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
6705 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
6706 LOCAL_SET_GL_ERROR(
6707 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6708 return false;
6713 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6714 uint32 size_needed = 0;
6715 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
6716 size_needed > 0x7FFFFFFFU) {
6717 LOCAL_SET_GL_ERROR(
6718 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6719 return false;
6722 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
6724 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
6725 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
6726 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
6727 GLenum error = glGetError();
6728 if (error != GL_NO_ERROR) {
6729 LOCAL_SET_GL_ERROR(
6730 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
6731 return false;
6735 // Copy the elements and convert to float
6736 GLintptr offset = 0;
6737 for (VertexAttribManager::VertexAttribList::const_iterator it =
6738 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6739 const VertexAttrib* attrib = *it;
6740 const Program::VertexAttrib* attrib_info =
6741 state_.current_program->GetAttribInfoByLocation(attrib->index());
6742 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6743 max_vertex_accessed);
6744 GLuint num_vertices = max_accessed + 1;
6745 if (num_vertices == 0) {
6746 LOCAL_SET_GL_ERROR(
6747 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
6748 return false;
6750 if (attrib_info &&
6751 attrib->CanAccess(max_accessed) &&
6752 attrib->type() == GL_FIXED) {
6753 int num_elements = attrib->size() * num_vertices;
6754 const int src_size = num_elements * sizeof(int32);
6755 const int dst_size = num_elements * sizeof(float);
6756 scoped_ptr<float[]> data(new float[num_elements]);
6757 const int32* src = reinterpret_cast<const int32 *>(
6758 attrib->buffer()->GetRange(attrib->offset(), src_size));
6759 const int32* end = src + num_elements;
6760 float* dst = data.get();
6761 while (src != end) {
6762 *dst++ = static_cast<float>(*src++) / 65536.0f;
6764 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
6765 glVertexAttribPointer(
6766 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
6767 reinterpret_cast<GLvoid*>(offset));
6768 offset += dst_size;
6771 *simulated = true;
6772 return true;
6775 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6776 // There's no need to call glVertexAttribPointer because we shadow all the
6777 // settings and passing GL_FIXED to it will not work.
6778 glBindBuffer(
6779 GL_ARRAY_BUFFER,
6780 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6781 : 0);
6784 error::Error GLES2DecoderImpl::DoDrawArrays(
6785 const char* function_name,
6786 bool instanced,
6787 GLenum mode,
6788 GLint first,
6789 GLsizei count,
6790 GLsizei primcount) {
6791 error::Error error = WillAccessBoundFramebufferForDraw();
6792 if (error != error::kNoError)
6793 return error;
6794 if (!validators_->draw_mode.IsValid(mode)) {
6795 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6796 return error::kNoError;
6798 if (count < 0) {
6799 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6800 return error::kNoError;
6802 if (primcount < 0) {
6803 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6804 return error::kNoError;
6806 if (!CheckBoundFramebuffersValid(function_name)) {
6807 return error::kNoError;
6809 // We have to check this here because the prototype for glDrawArrays
6810 // is GLint not GLsizei.
6811 if (first < 0) {
6812 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
6813 return error::kNoError;
6816 if (count == 0 || primcount == 0) {
6817 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
6818 return error::kNoError;
6821 GLuint max_vertex_accessed = first + count - 1;
6822 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6823 if (!ClearUnclearedTextures()) {
6824 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6825 return error::kNoError;
6827 bool simulated_attrib_0 = false;
6828 if (!SimulateAttrib0(
6829 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6830 return error::kNoError;
6832 bool simulated_fixed_attribs = false;
6833 if (SimulateFixedAttribs(
6834 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6835 primcount)) {
6836 bool textures_set = !PrepareTexturesForRender();
6837 ApplyDirtyState();
6838 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6839 if (!instanced) {
6840 glDrawArrays(mode, first, count);
6841 } else {
6842 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6844 if (textures_set) {
6845 RestoreStateForTextures();
6847 if (simulated_fixed_attribs) {
6848 RestoreStateForSimulatedFixedAttribs();
6851 if (simulated_attrib_0) {
6852 // We don't have to restore attrib 0 generic data at the end of this
6853 // function even if it is simulated. This is because we will simulate
6854 // it in each draw call, and attrib 0 generic data queries use cached
6855 // values instead of passing down to the underlying driver.
6856 RestoreStateForAttrib(0, false);
6859 return error::kNoError;
6862 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
6863 const void* cmd_data) {
6864 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
6865 return DoDrawArrays("glDrawArrays",
6866 false,
6867 static_cast<GLenum>(c.mode),
6868 static_cast<GLint>(c.first),
6869 static_cast<GLsizei>(c.count),
6873 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
6874 uint32 immediate_data_size,
6875 const void* cmd_data) {
6876 const gles2::cmds::DrawArraysInstancedANGLE& c =
6877 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
6878 if (!features().angle_instanced_arrays) {
6879 LOCAL_SET_GL_ERROR(
6880 GL_INVALID_OPERATION,
6881 "glDrawArraysInstancedANGLE", "function not available");
6882 return error::kNoError;
6884 return DoDrawArrays("glDrawArraysIntancedANGLE",
6885 true,
6886 static_cast<GLenum>(c.mode),
6887 static_cast<GLint>(c.first),
6888 static_cast<GLsizei>(c.count),
6889 static_cast<GLsizei>(c.primcount));
6892 error::Error GLES2DecoderImpl::DoDrawElements(
6893 const char* function_name,
6894 bool instanced,
6895 GLenum mode,
6896 GLsizei count,
6897 GLenum type,
6898 int32 offset,
6899 GLsizei primcount) {
6900 error::Error error = WillAccessBoundFramebufferForDraw();
6901 if (error != error::kNoError)
6902 return error;
6903 if (!state_.vertex_attrib_manager->element_array_buffer()) {
6904 LOCAL_SET_GL_ERROR(
6905 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
6906 return error::kNoError;
6909 if (count < 0) {
6910 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
6911 return error::kNoError;
6913 if (offset < 0) {
6914 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
6915 return error::kNoError;
6917 if (!validators_->draw_mode.IsValid(mode)) {
6918 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
6919 return error::kNoError;
6921 if (!validators_->index_type.IsValid(type)) {
6922 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
6923 return error::kNoError;
6925 if (primcount < 0) {
6926 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
6927 return error::kNoError;
6930 if (!CheckBoundFramebuffersValid(function_name)) {
6931 return error::kNoError;
6934 if (count == 0 || primcount == 0) {
6935 return error::kNoError;
6938 GLuint max_vertex_accessed;
6939 Buffer* element_array_buffer =
6940 state_.vertex_attrib_manager->element_array_buffer();
6942 if (!element_array_buffer->GetMaxValueForRange(
6943 offset, count, type, &max_vertex_accessed)) {
6944 LOCAL_SET_GL_ERROR(
6945 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
6946 return error::kNoError;
6949 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
6950 if (!ClearUnclearedTextures()) {
6951 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
6952 return error::kNoError;
6954 bool simulated_attrib_0 = false;
6955 if (!SimulateAttrib0(
6956 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6957 return error::kNoError;
6959 bool simulated_fixed_attribs = false;
6960 if (SimulateFixedAttribs(
6961 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6962 primcount)) {
6963 bool textures_set = !PrepareTexturesForRender();
6964 ApplyDirtyState();
6965 // TODO(gman): Refactor to hide these details in BufferManager or
6966 // VertexAttribManager.
6967 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
6968 bool used_client_side_array = false;
6969 if (element_array_buffer->IsClientSideArray()) {
6970 used_client_side_array = true;
6971 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6972 indices = element_array_buffer->GetRange(offset, 0);
6975 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6976 if (!instanced) {
6977 glDrawElements(mode, count, type, indices);
6978 } else {
6979 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6982 if (used_client_side_array) {
6983 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6984 element_array_buffer->service_id());
6987 if (textures_set) {
6988 RestoreStateForTextures();
6990 if (simulated_fixed_attribs) {
6991 RestoreStateForSimulatedFixedAttribs();
6994 if (simulated_attrib_0) {
6995 // We don't have to restore attrib 0 generic data at the end of this
6996 // function even if it is simulated. This is because we will simulate
6997 // it in each draw call, and attrib 0 generic data queries use cached
6998 // values instead of passing down to the underlying driver.
6999 RestoreStateForAttrib(0, false);
7002 return error::kNoError;
7005 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7006 const void* cmd_data) {
7007 const gles2::cmds::DrawElements& c =
7008 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7009 return DoDrawElements("glDrawElements",
7010 false,
7011 static_cast<GLenum>(c.mode),
7012 static_cast<GLsizei>(c.count),
7013 static_cast<GLenum>(c.type),
7014 static_cast<int32>(c.index_offset),
7018 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7019 uint32 immediate_data_size,
7020 const void* cmd_data) {
7021 const gles2::cmds::DrawElementsInstancedANGLE& c =
7022 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7023 if (!features().angle_instanced_arrays) {
7024 LOCAL_SET_GL_ERROR(
7025 GL_INVALID_OPERATION,
7026 "glDrawElementsInstancedANGLE", "function not available");
7027 return error::kNoError;
7029 return DoDrawElements("glDrawElementsInstancedANGLE",
7030 true,
7031 static_cast<GLenum>(c.mode),
7032 static_cast<GLsizei>(c.count),
7033 static_cast<GLenum>(c.type),
7034 static_cast<int32>(c.index_offset),
7035 static_cast<GLsizei>(c.primcount));
7038 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7039 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7040 GLuint max_vertex_accessed = 0;
7041 Buffer* buffer = GetBuffer(buffer_id);
7042 if (!buffer) {
7043 // TODO(gman): Should this be a GL error or a command buffer error?
7044 LOCAL_SET_GL_ERROR(
7045 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7046 } else {
7047 if (!buffer->GetMaxValueForRange(
7048 offset, count, type, &max_vertex_accessed)) {
7049 // TODO(gman): Should this be a GL error or a command buffer error?
7050 LOCAL_SET_GL_ERROR(
7051 GL_INVALID_OPERATION,
7052 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7055 return max_vertex_accessed;
7058 void GLES2DecoderImpl::DoShaderSource(
7059 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7060 std::string str;
7061 for (GLsizei ii = 0; ii < count; ++ii) {
7062 if (length && length[ii] > 0)
7063 str.append(data[ii], length[ii]);
7064 else
7065 str.append(data[ii]);
7067 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7068 if (!shader) {
7069 return;
7071 // Note: We don't actually call glShaderSource here. We wait until
7072 // we actually compile the shader.
7073 shader->set_source(str);
7076 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7077 GLuint client_program_id, GLsizei count, const char* const* varyings,
7078 GLenum buffer_mode) {
7079 Program* program = GetProgramInfoNotShader(
7080 client_program_id, "glTransformFeedbackVaryings");
7081 if (!program) {
7082 return;
7084 glTransformFeedbackVaryings(
7085 program->service_id(), count, varyings, buffer_mode);
7088 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7089 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7090 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7091 if (!shader) {
7092 return;
7094 ShaderTranslator* translator = NULL;
7095 if (use_shader_translator_) {
7096 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7097 vertex_translator_.get() : fragment_translator_.get();
7100 shader->DoCompile(
7101 translator,
7102 feature_info_->feature_flags().angle_translated_shader_source ?
7103 Shader::kANGLE : Shader::kGL);
7105 // CompileShader can be very slow. Exit command processing to allow for
7106 // context preemption and GPU watchdog checks.
7107 ExitCommandProcessingEarly();
7110 void GLES2DecoderImpl::DoGetShaderiv(
7111 GLuint shader_id, GLenum pname, GLint* params) {
7112 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7113 if (!shader) {
7114 return;
7116 switch (pname) {
7117 case GL_SHADER_SOURCE_LENGTH:
7118 *params = shader->source().size();
7119 if (*params)
7120 ++(*params);
7121 return;
7122 case GL_COMPILE_STATUS:
7123 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7124 return;
7125 case GL_INFO_LOG_LENGTH:
7126 *params = shader->log_info().size();
7127 if (*params)
7128 ++(*params);
7129 return;
7130 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7131 *params = shader->translated_source().size();
7132 if (*params)
7133 ++(*params);
7134 return;
7135 default:
7136 break;
7138 glGetShaderiv(shader->service_id(), pname, params);
7141 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7142 const void* cmd_data) {
7143 const gles2::cmds::GetShaderSource& c =
7144 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7145 GLuint shader_id = c.shader;
7146 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7147 Bucket* bucket = CreateBucket(bucket_id);
7148 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7149 if (!shader || shader->source().empty()) {
7150 bucket->SetSize(0);
7151 return error::kNoError;
7153 bucket->SetFromString(shader->source().c_str());
7154 return error::kNoError;
7157 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7158 uint32 immediate_data_size,
7159 const void* cmd_data) {
7160 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7161 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7162 cmd_data);
7163 GLuint shader_id = c.shader;
7164 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7165 Bucket* bucket = CreateBucket(bucket_id);
7166 Shader* shader = GetShaderInfoNotProgram(
7167 shader_id, "glGetTranslatedShaderSourceANGLE");
7168 if (!shader) {
7169 bucket->SetSize(0);
7170 return error::kNoError;
7173 bucket->SetFromString(shader->translated_source().c_str());
7174 return error::kNoError;
7177 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7178 uint32 immediate_data_size,
7179 const void* cmd_data) {
7180 const gles2::cmds::GetProgramInfoLog& c =
7181 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7182 GLuint program_id = c.program;
7183 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7184 Bucket* bucket = CreateBucket(bucket_id);
7185 Program* program = GetProgramInfoNotShader(
7186 program_id, "glGetProgramInfoLog");
7187 if (!program || !program->log_info()) {
7188 bucket->SetFromString("");
7189 return error::kNoError;
7191 bucket->SetFromString(program->log_info()->c_str());
7192 return error::kNoError;
7195 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7196 uint32 immediate_data_size,
7197 const void* cmd_data) {
7198 const gles2::cmds::GetShaderInfoLog& c =
7199 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7200 GLuint shader_id = c.shader;
7201 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7202 Bucket* bucket = CreateBucket(bucket_id);
7203 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7204 if (!shader) {
7205 bucket->SetFromString("");
7206 return error::kNoError;
7208 bucket->SetFromString(shader->log_info().c_str());
7209 return error::kNoError;
7212 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7213 return state_.GetEnabled(cap);
7216 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7217 const Buffer* buffer = GetBuffer(client_id);
7218 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7221 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7222 const Framebuffer* framebuffer =
7223 GetFramebuffer(client_id);
7224 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7227 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7228 // IsProgram is true for programs as soon as they are created, until they are
7229 // deleted and no longer in use.
7230 const Program* program = GetProgram(client_id);
7231 return program != NULL && !program->IsDeleted();
7234 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7235 const Renderbuffer* renderbuffer =
7236 GetRenderbuffer(client_id);
7237 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7240 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7241 // IsShader is true for shaders as soon as they are created, until they
7242 // are deleted and not attached to any programs.
7243 const Shader* shader = GetShader(client_id);
7244 return shader != NULL && !shader->IsDeleted();
7247 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7248 const TextureRef* texture_ref = GetTexture(client_id);
7249 return texture_ref && texture_ref->texture()->IsValid();
7252 void GLES2DecoderImpl::DoAttachShader(
7253 GLuint program_client_id, GLint shader_client_id) {
7254 Program* program = GetProgramInfoNotShader(
7255 program_client_id, "glAttachShader");
7256 if (!program) {
7257 return;
7259 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7260 if (!shader) {
7261 return;
7263 if (!program->AttachShader(shader_manager(), shader)) {
7264 LOCAL_SET_GL_ERROR(
7265 GL_INVALID_OPERATION,
7266 "glAttachShader",
7267 "can not attach more than one shader of the same type.");
7268 return;
7270 glAttachShader(program->service_id(), shader->service_id());
7273 void GLES2DecoderImpl::DoDetachShader(
7274 GLuint program_client_id, GLint shader_client_id) {
7275 Program* program = GetProgramInfoNotShader(
7276 program_client_id, "glDetachShader");
7277 if (!program) {
7278 return;
7280 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7281 if (!shader) {
7282 return;
7284 if (!program->DetachShader(shader_manager(), shader)) {
7285 LOCAL_SET_GL_ERROR(
7286 GL_INVALID_OPERATION,
7287 "glDetachShader", "shader not attached to program");
7288 return;
7290 glDetachShader(program->service_id(), shader->service_id());
7293 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7294 Program* program = GetProgramInfoNotShader(
7295 program_client_id, "glValidateProgram");
7296 if (!program) {
7297 return;
7299 program->Validate();
7302 void GLES2DecoderImpl::GetVertexAttribHelper(
7303 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7304 switch (pname) {
7305 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
7306 Buffer* buffer = attrib->buffer();
7307 if (buffer && !buffer->IsDeleted()) {
7308 GLuint client_id;
7309 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7310 *params = client_id;
7312 break;
7314 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7315 *params = attrib->enabled();
7316 break;
7317 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7318 *params = attrib->size();
7319 break;
7320 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7321 *params = attrib->gl_stride();
7322 break;
7323 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7324 *params = attrib->type();
7325 break;
7326 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7327 *params = attrib->normalized();
7328 break;
7329 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
7330 *params = attrib->divisor();
7331 break;
7332 default:
7333 NOTREACHED();
7334 break;
7338 void GLES2DecoderImpl::DoGetTexParameterfv(
7339 GLenum target, GLenum pname, GLfloat* params) {
7340 InitTextureMaxAnisotropyIfNeeded(target, pname);
7341 glGetTexParameterfv(target, pname, params);
7344 void GLES2DecoderImpl::DoGetTexParameteriv(
7345 GLenum target, GLenum pname, GLint* params) {
7346 InitTextureMaxAnisotropyIfNeeded(target, pname);
7347 glGetTexParameteriv(target, pname, params);
7350 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7351 GLenum target, GLenum pname) {
7352 if (!workarounds().init_texture_max_anisotropy)
7353 return;
7354 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7355 !validators_->texture_parameter.IsValid(pname)) {
7356 return;
7359 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7360 &state_, target);
7361 if (!texture_ref) {
7362 LOCAL_SET_GL_ERROR(
7363 GL_INVALID_OPERATION,
7364 "glGetTexParamter{fi}v", "unknown texture for target");
7365 return;
7367 Texture* texture = texture_ref->texture();
7368 texture->InitTextureMaxAnisotropyIfNeeded(target);
7371 void GLES2DecoderImpl::DoGetVertexAttribfv(
7372 GLuint index, GLenum pname, GLfloat* params) {
7373 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7374 if (!attrib) {
7375 LOCAL_SET_GL_ERROR(
7376 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
7377 return;
7379 switch (pname) {
7380 case GL_CURRENT_VERTEX_ATTRIB: {
7381 const Vec4& value = state_.attrib_values[index];
7382 params[0] = value.v[0];
7383 params[1] = value.v[1];
7384 params[2] = value.v[2];
7385 params[3] = value.v[3];
7386 break;
7388 default: {
7389 GLint value = 0;
7390 GetVertexAttribHelper(attrib, pname, &value);
7391 *params = static_cast<GLfloat>(value);
7392 break;
7397 void GLES2DecoderImpl::DoGetVertexAttribiv(
7398 GLuint index, GLenum pname, GLint* params) {
7399 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7400 if (!attrib) {
7401 LOCAL_SET_GL_ERROR(
7402 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
7403 return;
7405 switch (pname) {
7406 case GL_CURRENT_VERTEX_ATTRIB: {
7407 const Vec4& value = state_.attrib_values[index];
7408 params[0] = static_cast<GLint>(value.v[0]);
7409 params[1] = static_cast<GLint>(value.v[1]);
7410 params[2] = static_cast<GLint>(value.v[2]);
7411 params[3] = static_cast<GLint>(value.v[3]);
7412 break;
7414 default:
7415 GetVertexAttribHelper(attrib, pname, params);
7416 break;
7420 bool GLES2DecoderImpl::SetVertexAttribValue(
7421 const char* function_name, GLuint index, const GLfloat* value) {
7422 if (index >= state_.attrib_values.size()) {
7423 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7424 return false;
7426 Vec4& v = state_.attrib_values[index];
7427 v.v[0] = value[0];
7428 v.v[1] = value[1];
7429 v.v[2] = value[2];
7430 v.v[3] = value[3];
7431 return true;
7434 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7435 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7436 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7437 glVertexAttrib1f(index, v0);
7441 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
7442 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
7443 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
7444 glVertexAttrib2f(index, v0, v1);
7448 void GLES2DecoderImpl::DoVertexAttrib3f(
7449 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
7450 GLfloat v[4] = { v0, v1, v2, 1.0f, };
7451 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
7452 glVertexAttrib3f(index, v0, v1, v2);
7456 void GLES2DecoderImpl::DoVertexAttrib4f(
7457 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
7458 GLfloat v[4] = { v0, v1, v2, v3, };
7459 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
7460 glVertexAttrib4f(index, v0, v1, v2, v3);
7464 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
7465 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
7466 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
7467 glVertexAttrib1fv(index, v);
7471 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
7472 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
7473 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
7474 glVertexAttrib2fv(index, v);
7478 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
7479 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
7480 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
7481 glVertexAttrib3fv(index, v);
7485 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
7486 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
7487 glVertexAttrib4fv(index, v);
7491 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
7492 uint32 immediate_data_size,
7493 const void* cmd_data) {
7494 // TODO(zmo): Unsafe ES3 API, missing states update.
7495 if (!unsafe_es3_apis_enabled())
7496 return error::kUnknownCommand;
7497 const gles2::cmds::VertexAttribIPointer& c =
7498 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
7499 GLuint indx = c.indx;
7500 GLint size = c.size;
7501 GLenum type = c.type;
7502 GLsizei stride = c.stride;
7503 GLsizei offset = c.offset;
7504 const void* ptr = reinterpret_cast<const void*>(offset);
7505 glVertexAttribIPointer(indx, size, type, stride, ptr);
7506 return error::kNoError;
7509 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
7510 uint32 immediate_data_size,
7511 const void* cmd_data) {
7512 const gles2::cmds::VertexAttribPointer& c =
7513 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
7515 if (!state_.bound_array_buffer.get() ||
7516 state_.bound_array_buffer->IsDeleted()) {
7517 if (state_.vertex_attrib_manager.get() ==
7518 state_.default_vertex_attrib_manager.get()) {
7519 LOCAL_SET_GL_ERROR(
7520 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
7521 return error::kNoError;
7522 } else if (c.offset != 0) {
7523 LOCAL_SET_GL_ERROR(
7524 GL_INVALID_VALUE,
7525 "glVertexAttribPointer", "client side arrays are not allowed");
7526 return error::kNoError;
7530 GLuint indx = c.indx;
7531 GLint size = c.size;
7532 GLenum type = c.type;
7533 GLboolean normalized = static_cast<GLboolean>(c.normalized);
7534 GLsizei stride = c.stride;
7535 GLsizei offset = c.offset;
7536 const void* ptr = reinterpret_cast<const void*>(offset);
7537 if (!validators_->vertex_attrib_type.IsValid(type)) {
7538 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
7539 return error::kNoError;
7541 if (!validators_->vertex_attrib_size.IsValid(size)) {
7542 LOCAL_SET_GL_ERROR(
7543 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
7544 return error::kNoError;
7546 if (indx >= group_->max_vertex_attribs()) {
7547 LOCAL_SET_GL_ERROR(
7548 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
7549 return error::kNoError;
7551 if (stride < 0) {
7552 LOCAL_SET_GL_ERROR(
7553 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
7554 return error::kNoError;
7556 if (stride > 255) {
7557 LOCAL_SET_GL_ERROR(
7558 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
7559 return error::kNoError;
7561 if (offset < 0) {
7562 LOCAL_SET_GL_ERROR(
7563 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
7564 return error::kNoError;
7566 GLsizei component_size =
7567 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
7568 // component_size must be a power of two to use & as optimized modulo.
7569 DCHECK(GLES2Util::IsPOT(component_size));
7570 if (offset & (component_size - 1)) {
7571 LOCAL_SET_GL_ERROR(
7572 GL_INVALID_OPERATION,
7573 "glVertexAttribPointer", "offset not valid for type");
7574 return error::kNoError;
7576 if (stride & (component_size - 1)) {
7577 LOCAL_SET_GL_ERROR(
7578 GL_INVALID_OPERATION,
7579 "glVertexAttribPointer", "stride not valid for type");
7580 return error::kNoError;
7582 state_.vertex_attrib_manager
7583 ->SetAttribInfo(indx,
7584 state_.bound_array_buffer.get(),
7585 size,
7586 type,
7587 normalized,
7588 stride,
7589 stride != 0 ? stride : component_size * size,
7590 offset);
7591 if (type != GL_FIXED) {
7592 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
7594 return error::kNoError;
7597 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
7598 GLsizei height) {
7599 state_.viewport_x = x;
7600 state_.viewport_y = y;
7601 state_.viewport_width = std::min(width, viewport_max_width_);
7602 state_.viewport_height = std::min(height, viewport_max_height_);
7603 glViewport(x, y, width, height);
7606 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
7607 uint32 immediate_data_size,
7608 const void* cmd_data) {
7609 const gles2::cmds::VertexAttribDivisorANGLE& c =
7610 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
7611 if (!features().angle_instanced_arrays) {
7612 LOCAL_SET_GL_ERROR(
7613 GL_INVALID_OPERATION,
7614 "glVertexAttribDivisorANGLE", "function not available");
7615 return error::kNoError;
7617 GLuint index = c.index;
7618 GLuint divisor = c.divisor;
7619 if (index >= group_->max_vertex_attribs()) {
7620 LOCAL_SET_GL_ERROR(
7621 GL_INVALID_VALUE,
7622 "glVertexAttribDivisorANGLE", "index out of range");
7623 return error::kNoError;
7626 state_.vertex_attrib_manager->SetDivisor(
7627 index,
7628 divisor);
7629 glVertexAttribDivisorANGLE(index, divisor);
7630 return error::kNoError;
7633 template <typename pixel_data_type>
7634 static void WriteAlphaData(
7635 void *pixels, uint32 row_count, uint32 channel_count,
7636 uint32 alpha_channel_index, uint32 unpadded_row_size,
7637 uint32 padded_row_size, pixel_data_type alpha_value) {
7638 DCHECK_GT(channel_count, 0U);
7639 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
7640 uint32 unpadded_row_size_in_elements =
7641 unpadded_row_size / sizeof(pixel_data_type);
7642 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
7643 uint32 padded_row_size_in_elements =
7644 padded_row_size / sizeof(pixel_data_type);
7645 pixel_data_type* dst =
7646 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
7647 for (uint32 yy = 0; yy < row_count; ++yy) {
7648 pixel_data_type* end = dst + unpadded_row_size_in_elements;
7649 for (pixel_data_type* d = dst; d < end; d += channel_count) {
7650 *d = alpha_value;
7652 dst += padded_row_size_in_elements;
7656 void GLES2DecoderImpl::FinishReadPixels(
7657 const cmds::ReadPixels& c,
7658 GLuint buffer) {
7659 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
7660 GLsizei width = c.width;
7661 GLsizei height = c.height;
7662 GLenum format = c.format;
7663 GLenum type = c.type;
7664 typedef cmds::ReadPixels::Result Result;
7665 uint32 pixels_size;
7666 Result* result = NULL;
7667 if (c.result_shm_id != 0) {
7668 result = GetSharedMemoryAs<Result*>(
7669 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7670 if (!result) {
7671 if (buffer != 0) {
7672 glDeleteBuffersARB(1, &buffer);
7674 return;
7677 GLES2Util::ComputeImageDataSizes(
7678 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
7679 NULL, NULL);
7680 void* pixels = GetSharedMemoryAs<void*>(
7681 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7682 if (!pixels) {
7683 if (buffer != 0) {
7684 glDeleteBuffersARB(1, &buffer);
7686 return;
7689 if (buffer != 0) {
7690 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7691 void* data;
7692 if (features().map_buffer_range) {
7693 data = glMapBufferRange(
7694 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
7695 } else {
7696 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
7698 if (!data) {
7699 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
7700 "Unable to map memory for readback.");
7701 return;
7703 memcpy(pixels, data, pixels_size);
7704 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
7705 // have to restore the state.
7706 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
7707 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7708 glDeleteBuffersARB(1, &buffer);
7711 if (result != NULL) {
7712 *result = true;
7715 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7716 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7717 if ((channels_exist & 0x0008) == 0 &&
7718 workarounds().clear_alpha_in_readpixels) {
7719 // Set the alpha to 255 because some drivers are buggy in this regard.
7720 uint32 temp_size;
7722 uint32 unpadded_row_size;
7723 uint32 padded_row_size;
7724 if (!GLES2Util::ComputeImageDataSizes(
7725 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
7726 &unpadded_row_size, &padded_row_size)) {
7727 return;
7730 uint32 channel_count = 0;
7731 uint32 alpha_channel = 0;
7732 switch (format) {
7733 case GL_RGBA:
7734 case GL_BGRA_EXT:
7735 channel_count = 4;
7736 alpha_channel = 3;
7737 break;
7738 case GL_ALPHA:
7739 channel_count = 1;
7740 alpha_channel = 0;
7741 break;
7744 if (channel_count > 0) {
7745 switch (type) {
7746 case GL_UNSIGNED_BYTE:
7747 WriteAlphaData<uint8>(
7748 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7749 padded_row_size, 0xFF);
7750 break;
7751 case GL_FLOAT:
7752 WriteAlphaData<float>(
7753 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7754 padded_row_size, 1.0f);
7755 break;
7756 case GL_HALF_FLOAT:
7757 WriteAlphaData<uint16>(
7758 pixels, height, channel_count, alpha_channel, unpadded_row_size,
7759 padded_row_size, 0x3C00);
7760 break;
7766 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
7767 const void* cmd_data) {
7768 const gles2::cmds::ReadPixels& c =
7769 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
7770 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
7771 error::Error fbo_error = WillAccessBoundFramebufferForRead();
7772 if (fbo_error != error::kNoError)
7773 return fbo_error;
7774 GLint x = c.x;
7775 GLint y = c.y;
7776 GLsizei width = c.width;
7777 GLsizei height = c.height;
7778 GLenum format = c.format;
7779 GLenum type = c.type;
7780 GLboolean async = static_cast<GLboolean>(c.async);
7781 if (width < 0 || height < 0) {
7782 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
7783 return error::kNoError;
7785 typedef cmds::ReadPixels::Result Result;
7786 uint32 pixels_size;
7787 if (!GLES2Util::ComputeImageDataSizes(
7788 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
7789 NULL, NULL)) {
7790 return error::kOutOfBounds;
7792 void* pixels = GetSharedMemoryAs<void*>(
7793 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
7794 if (!pixels) {
7795 return error::kOutOfBounds;
7797 Result* result = NULL;
7798 if (c.result_shm_id != 0) {
7799 result = GetSharedMemoryAs<Result*>(
7800 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7801 if (!result) {
7802 return error::kOutOfBounds;
7806 if (!validators_->read_pixel_format.IsValid(format)) {
7807 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
7808 return error::kNoError;
7810 if (!validators_->read_pixel_type.IsValid(type)) {
7811 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
7812 return error::kNoError;
7814 if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
7815 format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
7816 // format and type are acceptable enums but not guaranteed to be supported
7817 // for this framebuffer. Have to ask gl if they are valid.
7818 GLint preferred_format = 0;
7819 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
7820 GLint preferred_type = 0;
7821 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
7822 if (format != static_cast<GLenum>(preferred_format) ||
7823 type != static_cast<GLenum>(preferred_type)) {
7824 LOCAL_SET_GL_ERROR(
7825 GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
7826 "with the current read framebuffer");
7827 return error::kNoError;
7830 if (width == 0 || height == 0) {
7831 return error::kNoError;
7834 // Get the size of the current fbo or backbuffer.
7835 gfx::Size max_size = GetBoundReadFrameBufferSize();
7837 int32 max_x;
7838 int32 max_y;
7839 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
7840 LOCAL_SET_GL_ERROR(
7841 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7842 return error::kNoError;
7845 if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) {
7846 return error::kNoError;
7849 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7850 return error::kNoError;
7853 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
7855 ScopedResolvedFrameBufferBinder binder(this, false, true);
7857 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
7858 // The user requested an out of range area. Get the results 1 line
7859 // at a time.
7860 uint32 temp_size;
7861 uint32 unpadded_row_size;
7862 uint32 padded_row_size;
7863 if (!GLES2Util::ComputeImageDataSizes(
7864 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
7865 &unpadded_row_size, &padded_row_size)) {
7866 LOCAL_SET_GL_ERROR(
7867 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7868 return error::kNoError;
7871 GLint dest_x_offset = std::max(-x, 0);
7872 uint32 dest_row_offset;
7873 if (!GLES2Util::ComputeImageDataSizes(
7874 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
7875 &dest_row_offset, NULL, NULL)) {
7876 LOCAL_SET_GL_ERROR(
7877 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
7878 return error::kNoError;
7881 // Copy each row into the larger dest rect.
7882 int8* dst = static_cast<int8*>(pixels);
7883 GLint read_x = std::max(0, x);
7884 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
7885 GLint read_width = read_end_x - read_x;
7886 for (GLint yy = 0; yy < height; ++yy) {
7887 GLint ry = y + yy;
7889 // Clear the row.
7890 memset(dst, 0, unpadded_row_size);
7892 // If the row is in range, copy it.
7893 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
7894 glReadPixels(
7895 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7897 dst += padded_row_size;
7899 } else {
7900 if (async && features().use_async_readpixels) {
7901 GLuint buffer = 0;
7902 glGenBuffersARB(1, &buffer);
7903 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7904 // For ANGLE client version 2, GL_STREAM_READ is not available.
7905 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
7906 GL_STATIC_DRAW : GL_STREAM_READ;
7907 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
7908 GLenum error = glGetError();
7909 if (error == GL_NO_ERROR) {
7910 glReadPixels(x, y, width, height, format, type, 0);
7911 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7912 new FenceCallback()));
7913 WaitForReadPixels(base::Bind(
7914 &GLES2DecoderImpl::FinishReadPixels,
7915 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7916 <GLES2DecoderImpl>(this),
7917 c, buffer));
7918 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7919 return error::kNoError;
7920 } else {
7921 // On error, unbind pack buffer and fall through to sync readpixels
7922 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7923 glDeleteBuffersARB(1, &buffer);
7926 glReadPixels(x, y, width, height, format, type, pixels);
7928 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
7929 if (error == GL_NO_ERROR) {
7930 if (result != NULL) {
7931 *result = true;
7933 FinishReadPixels(c, 0);
7936 return error::kNoError;
7939 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
7940 const void* cmd_data) {
7941 const gles2::cmds::PixelStorei& c =
7942 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
7943 GLenum pname = c.pname;
7944 GLenum param = c.param;
7945 if (!validators_->pixel_store.IsValid(pname)) {
7946 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
7947 return error::kNoError;
7949 switch (pname) {
7950 case GL_PACK_ALIGNMENT:
7951 case GL_UNPACK_ALIGNMENT:
7952 if (!validators_->pixel_store_alignment.IsValid(param)) {
7953 LOCAL_SET_GL_ERROR(
7954 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
7955 return error::kNoError;
7957 break;
7958 case GL_UNPACK_FLIP_Y_CHROMIUM:
7959 unpack_flip_y_ = (param != 0);
7960 return error::kNoError;
7961 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7962 unpack_premultiply_alpha_ = (param != 0);
7963 return error::kNoError;
7964 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7965 unpack_unpremultiply_alpha_ = (param != 0);
7966 return error::kNoError;
7967 default:
7968 break;
7970 glPixelStorei(pname, param);
7971 switch (pname) {
7972 case GL_PACK_ALIGNMENT:
7973 state_.pack_alignment = param;
7974 break;
7975 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7976 state_.pack_reverse_row_order = (param != 0);
7977 break;
7978 case GL_UNPACK_ALIGNMENT:
7979 state_.unpack_alignment = param;
7980 break;
7981 default:
7982 // Validation should have prevented us from getting here.
7983 NOTREACHED();
7984 break;
7986 return error::kNoError;
7989 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
7990 uint32 immediate_data_size,
7991 const void* cmd_data) {
7992 const gles2::cmds::PostSubBufferCHROMIUM& c =
7993 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
7994 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7996 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
7998 if (!supports_post_sub_buffer_) {
7999 LOCAL_SET_GL_ERROR(
8000 GL_INVALID_OPERATION,
8001 "glPostSubBufferCHROMIUM", "command not supported by surface");
8002 return error::kNoError;
8004 bool is_tracing;
8005 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8006 &is_tracing);
8007 if (is_tracing) {
8008 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8009 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8010 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8011 is_offscreen ? offscreen_size_ : surface_->GetSize());
8013 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
8014 return error::kNoError;
8015 } else {
8016 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8017 return error::kLostContext;
8021 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8022 uint32 immediate_data_size,
8023 const void* cmd_data) {
8024 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8025 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8026 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8027 if (!ref) {
8028 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8029 "glScheduleOverlayPlaneCHROMIUM",
8030 "unknown texture");
8031 return error::kNoError;
8033 gfx::GLImage* image =
8034 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8035 if (!image) {
8036 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8037 "glScheduleOverlayPlaneCHROMIUM",
8038 "unsupported texture format");
8039 return error::kNoError;
8041 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8042 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8043 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8044 "glScheduleOverlayPlaneCHROMIUM",
8045 "invalid transform enum");
8046 return error::kNoError;
8048 if (!surface_->ScheduleOverlayPlane(
8049 c.plane_z_order,
8050 transform,
8051 image,
8052 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8053 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8054 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8055 "glScheduleOverlayPlaneCHROMIUM",
8056 "failed to schedule overlay");
8058 return error::kNoError;
8061 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8062 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8063 const std::string& name_str) {
8064 if (!StringIsValidForGLES(name_str.c_str())) {
8065 LOCAL_SET_GL_ERROR(
8066 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8067 return error::kNoError;
8069 Program* program = GetProgramInfoNotShader(
8070 client_id, "glGetAttribLocation");
8071 if (!program) {
8072 return error::kNoError;
8074 if (!program->IsValid()) {
8075 LOCAL_SET_GL_ERROR(
8076 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8077 return error::kNoError;
8079 GLint* location = GetSharedMemoryAs<GLint*>(
8080 location_shm_id, location_shm_offset, sizeof(GLint));
8081 if (!location) {
8082 return error::kOutOfBounds;
8084 // Require the client to init this incase the context is lost and we are no
8085 // longer executing commands.
8086 if (*location != -1) {
8087 return error::kGenericError;
8089 *location = program->GetAttribLocation(name_str);
8090 return error::kNoError;
8093 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8094 uint32 immediate_data_size,
8095 const void* cmd_data) {
8096 const gles2::cmds::GetAttribLocation& c =
8097 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8098 Bucket* bucket = GetBucket(c.name_bucket_id);
8099 if (!bucket) {
8100 return error::kInvalidArguments;
8102 std::string name_str;
8103 if (!bucket->GetAsString(&name_str)) {
8104 return error::kInvalidArguments;
8106 return GetAttribLocationHelper(
8107 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8110 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8111 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8112 const std::string& name_str) {
8113 if (!StringIsValidForGLES(name_str.c_str())) {
8114 LOCAL_SET_GL_ERROR(
8115 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8116 return error::kNoError;
8118 Program* program = GetProgramInfoNotShader(
8119 client_id, "glGetUniformLocation");
8120 if (!program) {
8121 return error::kNoError;
8123 if (!program->IsValid()) {
8124 LOCAL_SET_GL_ERROR(
8125 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8126 return error::kNoError;
8128 GLint* location = GetSharedMemoryAs<GLint*>(
8129 location_shm_id, location_shm_offset, sizeof(GLint));
8130 if (!location) {
8131 return error::kOutOfBounds;
8133 // Require the client to init this incase the context is lost an we are no
8134 // longer executing commands.
8135 if (*location != -1) {
8136 return error::kGenericError;
8138 *location = program->GetUniformFakeLocation(name_str);
8139 return error::kNoError;
8142 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8143 uint32 immediate_data_size,
8144 const void* cmd_data) {
8145 const gles2::cmds::GetUniformLocation& c =
8146 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8147 Bucket* bucket = GetBucket(c.name_bucket_id);
8148 if (!bucket) {
8149 return error::kInvalidArguments;
8151 std::string name_str;
8152 if (!bucket->GetAsString(&name_str)) {
8153 return error::kInvalidArguments;
8155 return GetUniformLocationHelper(
8156 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8159 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8160 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8161 const std::string& name_str) {
8162 GLint* location = GetSharedMemoryAs<GLint*>(
8163 location_shm_id, location_shm_offset, sizeof(GLint));
8164 if (!location) {
8165 return error::kOutOfBounds;
8167 // Require the client to init this incase the context is lost and we are no
8168 // longer executing commands.
8169 if (*location != -1) {
8170 return error::kGenericError;
8172 Program* program = GetProgramInfoNotShader(
8173 client_id, "glGetFragDataLocation");
8174 if (!program) {
8175 return error::kNoError;
8177 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8178 return error::kNoError;
8181 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8182 uint32 immediate_data_size,
8183 const void* cmd_data) {
8184 if (!unsafe_es3_apis_enabled())
8185 return error::kUnknownCommand;
8186 const gles2::cmds::GetFragDataLocation& c =
8187 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8188 Bucket* bucket = GetBucket(c.name_bucket_id);
8189 if (!bucket) {
8190 return error::kInvalidArguments;
8192 std::string name_str;
8193 if (!bucket->GetAsString(&name_str)) {
8194 return error::kInvalidArguments;
8196 return GetFragDataLocationHelper(
8197 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8200 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
8201 const void* cmd_data) {
8202 const gles2::cmds::GetString& c =
8203 *static_cast<const gles2::cmds::GetString*>(cmd_data);
8204 GLenum name = static_cast<GLenum>(c.name);
8205 if (!validators_->string_type.IsValid(name)) {
8206 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
8207 return error::kNoError;
8209 const char* str = reinterpret_cast<const char*>(glGetString(name));
8210 std::string extensions;
8211 switch (name) {
8212 case GL_VERSION:
8213 str = "OpenGL ES 2.0 Chromium";
8214 break;
8215 case GL_SHADING_LANGUAGE_VERSION:
8216 str = "OpenGL ES GLSL ES 1.0 Chromium";
8217 break;
8218 case GL_RENDERER:
8219 case GL_VENDOR:
8220 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
8221 // They are used by WEBGL_debug_renderer_info.
8222 if (!force_webgl_glsl_validation_)
8223 str = "Chromium";
8224 break;
8225 case GL_EXTENSIONS:
8227 // For WebGL contexts, strip out the OES derivatives and
8228 // EXT frag depth extensions if they have not been enabled.
8229 if (force_webgl_glsl_validation_) {
8230 extensions = feature_info_->extensions();
8231 if (!derivatives_explicitly_enabled_) {
8232 size_t offset = extensions.find(kOESDerivativeExtension);
8233 if (std::string::npos != offset) {
8234 extensions.replace(offset, arraysize(kOESDerivativeExtension),
8235 std::string());
8238 if (!frag_depth_explicitly_enabled_) {
8239 size_t offset = extensions.find(kEXTFragDepthExtension);
8240 if (std::string::npos != offset) {
8241 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
8242 std::string());
8245 if (!draw_buffers_explicitly_enabled_) {
8246 size_t offset = extensions.find(kEXTDrawBuffersExtension);
8247 if (std::string::npos != offset) {
8248 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
8249 std::string());
8252 if (!shader_texture_lod_explicitly_enabled_) {
8253 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
8254 if (std::string::npos != offset) {
8255 extensions.replace(offset,
8256 arraysize(kEXTShaderTextureLodExtension),
8257 std::string());
8260 } else {
8261 extensions = feature_info_->extensions().c_str();
8263 if (supports_post_sub_buffer_)
8264 extensions += " GL_CHROMIUM_post_sub_buffer";
8265 str = extensions.c_str();
8267 break;
8268 default:
8269 break;
8271 Bucket* bucket = CreateBucket(c.bucket_id);
8272 bucket->SetFromString(str);
8273 return error::kNoError;
8276 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
8277 const void* cmd_data) {
8278 const gles2::cmds::BufferData& c =
8279 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
8280 GLenum target = static_cast<GLenum>(c.target);
8281 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
8282 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8283 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8284 GLenum usage = static_cast<GLenum>(c.usage);
8285 const void* data = NULL;
8286 if (data_shm_id != 0 || data_shm_offset != 0) {
8287 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
8288 if (!data) {
8289 return error::kOutOfBounds;
8292 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
8293 return error::kNoError;
8296 void GLES2DecoderImpl::DoBufferSubData(
8297 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
8298 // Just delegate it. Some validation is actually done before this.
8299 buffer_manager()->ValidateAndDoBufferSubData(
8300 &state_, target, offset, size, data);
8303 bool GLES2DecoderImpl::ClearLevel(
8304 unsigned service_id,
8305 unsigned bind_target,
8306 unsigned target,
8307 int level,
8308 unsigned internal_format,
8309 unsigned format,
8310 unsigned type,
8311 int width,
8312 int height,
8313 bool is_texture_immutable) {
8314 uint32 channels = GLES2Util::GetChannelsForFormat(format);
8315 if (feature_info_->feature_flags().angle_depth_texture &&
8316 (channels & GLES2Util::kDepth) != 0) {
8317 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
8318 // on depth formats.
8319 GLuint fb = 0;
8320 glGenFramebuffersEXT(1, &fb);
8321 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
8323 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
8324 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
8325 GL_DEPTH_ATTACHMENT;
8327 glFramebufferTexture2DEXT(
8328 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
8329 // ANGLE promises a depth only attachment ok.
8330 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
8331 GL_FRAMEBUFFER_COMPLETE) {
8332 return false;
8334 glClearStencil(0);
8335 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
8336 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
8337 glClearDepth(1.0f);
8338 state_.SetDeviceDepthMask(GL_TRUE);
8339 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
8340 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
8342 RestoreClearState();
8344 glDeleteFramebuffersEXT(1, &fb);
8345 Framebuffer* framebuffer =
8346 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
8347 GLuint fb_service_id =
8348 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
8349 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
8350 return true;
8353 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
8355 uint32 size;
8356 uint32 padded_row_size;
8357 if (!GLES2Util::ComputeImageDataSizes(
8358 width, height, 1, format, type, state_.unpack_alignment, &size,
8359 NULL, &padded_row_size)) {
8360 return false;
8363 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
8365 int tile_height;
8367 if (size > kMaxZeroSize) {
8368 if (kMaxZeroSize < padded_row_size) {
8369 // That'd be an awfully large texture.
8370 return false;
8372 // We should never have a large total size with a zero row size.
8373 DCHECK_GT(padded_row_size, 0U);
8374 tile_height = kMaxZeroSize / padded_row_size;
8375 if (!GLES2Util::ComputeImageDataSizes(
8376 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
8377 NULL, NULL)) {
8378 return false;
8380 } else {
8381 tile_height = height;
8384 // Assumes the size has already been checked.
8385 scoped_ptr<char[]> zero(new char[size]);
8386 memset(zero.get(), 0, size);
8387 glBindTexture(bind_target, service_id);
8389 GLint y = 0;
8390 while (y < height) {
8391 GLint h = y + tile_height > height ? height - y : tile_height;
8392 if (is_texture_immutable || h != height) {
8393 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
8394 } else {
8395 glTexImage2D(
8396 target, level, internal_format, width, h, 0, format, type,
8397 zero.get());
8399 y += tile_height;
8401 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
8402 &state_, bind_target);
8403 glBindTexture(bind_target, texture ? texture->service_id() : 0);
8404 return true;
8407 namespace {
8409 const int kS3TCBlockWidth = 4;
8410 const int kS3TCBlockHeight = 4;
8411 const int kS3TCDXT1BlockSize = 8;
8412 const int kS3TCDXT3AndDXT5BlockSize = 16;
8414 bool IsValidDXTSize(GLint level, GLsizei size) {
8415 return (size == 1) ||
8416 (size == 2) || !(size % kS3TCBlockWidth);
8419 bool IsValidPVRTCSize(GLint level, GLsizei size) {
8420 return GLES2Util::IsPOT(size);
8423 } // anonymous namespace.
8425 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
8426 const char* function_name,
8427 GLsizei width, GLsizei height, GLenum format, size_t size) {
8428 unsigned int bytes_required = 0;
8430 switch (format) {
8431 case GL_ATC_RGB_AMD:
8432 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8433 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8434 case GL_ETC1_RGB8_OES: {
8435 int num_blocks_across =
8436 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8437 int num_blocks_down =
8438 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8439 int num_blocks = num_blocks_across * num_blocks_down;
8440 bytes_required = num_blocks * kS3TCDXT1BlockSize;
8441 break;
8443 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8444 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8445 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8446 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8447 int num_blocks_across =
8448 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
8449 int num_blocks_down =
8450 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
8451 int num_blocks = num_blocks_across * num_blocks_down;
8452 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
8453 break;
8455 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8456 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
8457 bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
8458 break;
8460 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8461 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8462 bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
8463 break;
8465 default:
8466 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8467 return false;
8470 if (size != bytes_required) {
8471 LOCAL_SET_GL_ERROR(
8472 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
8473 return false;
8476 return true;
8479 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
8480 const char* function_name,
8481 GLint level, GLsizei width, GLsizei height, GLenum format) {
8482 switch (format) {
8483 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8484 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8485 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8486 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8487 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
8488 LOCAL_SET_GL_ERROR(
8489 GL_INVALID_OPERATION, function_name,
8490 "width or height invalid for level");
8491 return false;
8493 return true;
8495 case GL_ATC_RGB_AMD:
8496 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8497 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
8498 case GL_ETC1_RGB8_OES: {
8499 if (width <= 0 || height <= 0) {
8500 LOCAL_SET_GL_ERROR(
8501 GL_INVALID_OPERATION, function_name,
8502 "width or height invalid for level");
8503 return false;
8505 return true;
8507 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8508 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8509 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8510 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8511 if (!IsValidPVRTCSize(level, width) ||
8512 !IsValidPVRTCSize(level, height)) {
8513 LOCAL_SET_GL_ERROR(
8514 GL_INVALID_OPERATION, function_name,
8515 "width or height invalid for level");
8516 return false;
8518 return true;
8520 default:
8521 return false;
8525 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
8526 const char* function_name,
8527 GLenum target, GLint level, GLint xoffset, GLint yoffset,
8528 GLsizei width, GLsizei height, GLenum format,
8529 Texture* texture) {
8530 if (xoffset < 0 || yoffset < 0) {
8531 LOCAL_SET_GL_ERROR(
8532 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
8533 return false;
8536 switch (format) {
8537 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
8538 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
8539 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
8540 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
8541 const int kBlockWidth = 4;
8542 const int kBlockHeight = 4;
8543 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
8544 LOCAL_SET_GL_ERROR(
8545 GL_INVALID_OPERATION, function_name,
8546 "xoffset or yoffset not multiple of 4");
8547 return false;
8549 GLsizei tex_width = 0;
8550 GLsizei tex_height = 0;
8551 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8552 width - xoffset > tex_width ||
8553 height - yoffset > tex_height) {
8554 LOCAL_SET_GL_ERROR(
8555 GL_INVALID_OPERATION, function_name, "dimensions out of range");
8556 return false;
8558 return ValidateCompressedTexDimensions(
8559 function_name, level, width, height, format);
8561 case GL_ATC_RGB_AMD:
8562 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
8563 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
8564 LOCAL_SET_GL_ERROR(
8565 GL_INVALID_OPERATION, function_name,
8566 "not supported for ATC textures");
8567 return false;
8569 case GL_ETC1_RGB8_OES: {
8570 LOCAL_SET_GL_ERROR(
8571 GL_INVALID_OPERATION, function_name,
8572 "not supported for ECT1_RGB8_OES textures");
8573 return false;
8575 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
8576 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
8577 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
8578 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
8579 if ((xoffset != 0) || (yoffset != 0)) {
8580 LOCAL_SET_GL_ERROR(
8581 GL_INVALID_OPERATION, function_name,
8582 "xoffset and yoffset must be zero");
8583 return false;
8585 GLsizei tex_width = 0;
8586 GLsizei tex_height = 0;
8587 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
8588 width != tex_width ||
8589 height != tex_height) {
8590 LOCAL_SET_GL_ERROR(
8591 GL_INVALID_OPERATION, function_name,
8592 "dimensions must match existing texture level dimensions");
8593 return false;
8595 return ValidateCompressedTexDimensions(
8596 function_name, level, width, height, format);
8598 default:
8599 return false;
8603 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
8604 GLenum target,
8605 GLint level,
8606 GLenum internal_format,
8607 GLsizei width,
8608 GLsizei height,
8609 GLint border,
8610 GLsizei image_size,
8611 const void* data) {
8612 // TODO(gman): Validate image_size is correct for width, height and format.
8613 if (!validators_->texture_target.IsValid(target)) {
8614 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8615 "glCompressedTexImage2D", target, "target");
8616 return error::kNoError;
8618 if (!validators_->compressed_texture_format.IsValid(
8619 internal_format)) {
8620 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8621 "glCompressedTexImage2D", internal_format, "internal_format");
8622 return error::kNoError;
8624 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8625 border != 0) {
8626 LOCAL_SET_GL_ERROR(
8627 GL_INVALID_VALUE,
8628 "glCompressedTexImage2D", "dimensions out of range");
8629 return error::kNoError;
8631 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8632 &state_, target);
8633 if (!texture_ref) {
8634 LOCAL_SET_GL_ERROR(
8635 GL_INVALID_VALUE,
8636 "glCompressedTexImage2D", "unknown texture target");
8637 return error::kNoError;
8639 Texture* texture = texture_ref->texture();
8640 if (texture->IsImmutable()) {
8641 LOCAL_SET_GL_ERROR(
8642 GL_INVALID_OPERATION,
8643 "glCompressedTexImage2D", "texture is immutable");
8644 return error::kNoError;
8647 if (!ValidateCompressedTexDimensions(
8648 "glCompressedTexImage2D", level, width, height, internal_format) ||
8649 !ValidateCompressedTexFuncData(
8650 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
8651 return error::kNoError;
8654 if (!EnsureGPUMemoryAvailable(image_size)) {
8655 LOCAL_SET_GL_ERROR(
8656 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
8657 return error::kNoError;
8660 if (texture->IsAttachedToFramebuffer()) {
8661 framebuffer_state_.clear_state_dirty = true;
8664 scoped_ptr<int8[]> zero;
8665 if (!data) {
8666 zero.reset(new int8[image_size]);
8667 memset(zero.get(), 0, image_size);
8668 data = zero.get();
8670 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
8671 glCompressedTexImage2D(
8672 target, level, internal_format, width, height, border, image_size, data);
8673 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
8674 if (error == GL_NO_ERROR) {
8675 texture_manager()->SetLevelInfo(
8676 texture_ref, target, level, internal_format,
8677 width, height, 1, border, 0, 0, true);
8680 // This may be a slow command. Exit command processing to allow for
8681 // context preemption and GPU watchdog checks.
8682 ExitCommandProcessingEarly();
8683 return error::kNoError;
8686 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
8687 uint32 immediate_data_size,
8688 const void* cmd_data) {
8689 const gles2::cmds::CompressedTexImage2D& c =
8690 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
8691 GLenum target = static_cast<GLenum>(c.target);
8692 GLint level = static_cast<GLint>(c.level);
8693 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8694 GLsizei width = static_cast<GLsizei>(c.width);
8695 GLsizei height = static_cast<GLsizei>(c.height);
8696 GLint border = static_cast<GLint>(c.border);
8697 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
8698 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
8699 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
8700 const void* data = NULL;
8701 if (data_shm_id != 0 || data_shm_offset != 0) {
8702 data = GetSharedMemoryAs<const void*>(
8703 data_shm_id, data_shm_offset, image_size);
8704 if (!data) {
8705 return error::kOutOfBounds;
8708 return DoCompressedTexImage2D(
8709 target, level, internal_format, width, height, border, image_size, data);
8712 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
8713 uint32 immediate_data_size,
8714 const void* cmd_data) {
8715 const gles2::cmds::CompressedTexImage2DBucket& c =
8716 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
8717 GLenum target = static_cast<GLenum>(c.target);
8718 GLint level = static_cast<GLint>(c.level);
8719 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8720 GLsizei width = static_cast<GLsizei>(c.width);
8721 GLsizei height = static_cast<GLsizei>(c.height);
8722 GLint border = static_cast<GLint>(c.border);
8723 Bucket* bucket = GetBucket(c.bucket_id);
8724 if (!bucket) {
8725 return error::kInvalidArguments;
8727 uint32 data_size = bucket->size();
8728 GLsizei imageSize = data_size;
8729 const void* data = bucket->GetData(0, data_size);
8730 if (!data) {
8731 return error::kInvalidArguments;
8733 return DoCompressedTexImage2D(
8734 target, level, internal_format, width, height, border,
8735 imageSize, data);
8738 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
8739 uint32 immediate_data_size,
8740 const void* cmd_data) {
8741 const gles2::cmds::CompressedTexSubImage2DBucket& c =
8742 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
8743 GLenum target = static_cast<GLenum>(c.target);
8744 GLint level = static_cast<GLint>(c.level);
8745 GLint xoffset = static_cast<GLint>(c.xoffset);
8746 GLint yoffset = static_cast<GLint>(c.yoffset);
8747 GLsizei width = static_cast<GLsizei>(c.width);
8748 GLsizei height = static_cast<GLsizei>(c.height);
8749 GLenum format = static_cast<GLenum>(c.format);
8750 Bucket* bucket = GetBucket(c.bucket_id);
8751 if (!bucket) {
8752 return error::kInvalidArguments;
8754 uint32 data_size = bucket->size();
8755 GLsizei imageSize = data_size;
8756 const void* data = bucket->GetData(0, data_size);
8757 if (!data) {
8758 return error::kInvalidArguments;
8760 if (!validators_->texture_target.IsValid(target)) {
8761 LOCAL_SET_GL_ERROR(
8762 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
8763 return error::kNoError;
8765 if (!validators_->compressed_texture_format.IsValid(format)) {
8766 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8767 "glCompressedTexSubImage2D", format, "format");
8768 return error::kNoError;
8770 if (width < 0) {
8771 LOCAL_SET_GL_ERROR(
8772 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
8773 return error::kNoError;
8775 if (height < 0) {
8776 LOCAL_SET_GL_ERROR(
8777 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
8778 return error::kNoError;
8780 if (imageSize < 0) {
8781 LOCAL_SET_GL_ERROR(
8782 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
8783 return error::kNoError;
8785 DoCompressedTexSubImage2D(
8786 target, level, xoffset, yoffset, width, height, format, imageSize, data);
8787 return error::kNoError;
8790 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
8791 const void* cmd_data) {
8792 const gles2::cmds::TexImage2D& c =
8793 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
8794 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
8795 "width", c.width, "height", c.height);
8796 // Set as failed for now, but if it successed, this will be set to not failed.
8797 texture_state_.tex_image_2d_failed = true;
8798 GLenum target = static_cast<GLenum>(c.target);
8799 GLint level = static_cast<GLint>(c.level);
8800 // TODO(kloveless): Change TexImage2D command to use unsigned integer
8801 // for internalformat.
8802 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8803 GLsizei width = static_cast<GLsizei>(c.width);
8804 GLsizei height = static_cast<GLsizei>(c.height);
8805 GLint border = static_cast<GLint>(c.border);
8806 GLenum format = static_cast<GLenum>(c.format);
8807 GLenum type = static_cast<GLenum>(c.type);
8808 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8809 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8810 uint32 pixels_size;
8811 if (!GLES2Util::ComputeImageDataSizes(
8812 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
8813 NULL, NULL)) {
8814 return error::kOutOfBounds;
8816 const void* pixels = NULL;
8817 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8818 pixels = GetSharedMemoryAs<const void*>(
8819 pixels_shm_id, pixels_shm_offset, pixels_size);
8820 if (!pixels) {
8821 return error::kOutOfBounds;
8825 TextureManager::DoTextImage2DArguments args = {
8826 target, level, internal_format, width, height, border, format, type,
8827 pixels, pixels_size};
8828 texture_manager()->ValidateAndDoTexImage2D(
8829 &texture_state_, &state_, &framebuffer_state_, args);
8831 // This may be a slow command. Exit command processing to allow for
8832 // context preemption and GPU watchdog checks.
8833 ExitCommandProcessingEarly();
8834 return error::kNoError;
8837 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
8838 const void* cmd_data) {
8839 // TODO(zmo): Unsafe ES3 API.
8840 if (!unsafe_es3_apis_enabled())
8841 return error::kUnknownCommand;
8843 const gles2::cmds::TexImage3D& c =
8844 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
8845 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
8846 "widthXheight", c.width * c.height, "depth", c.depth);
8847 GLenum target = static_cast<GLenum>(c.target);
8848 GLint level = static_cast<GLint>(c.level);
8849 GLenum internal_format = static_cast<GLenum>(c.internalformat);
8850 GLsizei width = static_cast<GLsizei>(c.width);
8851 GLsizei height = static_cast<GLsizei>(c.height);
8852 GLsizei depth = static_cast<GLsizei>(c.depth);
8853 GLint border = static_cast<GLint>(c.border);
8854 GLenum format = static_cast<GLenum>(c.format);
8855 GLenum type = static_cast<GLenum>(c.type);
8856 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
8857 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
8858 uint32 pixels_size;
8859 if (!GLES2Util::ComputeImageDataSizes(
8860 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
8861 NULL, NULL)) {
8862 return error::kOutOfBounds;
8864 const void* pixels = NULL;
8865 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
8866 pixels = GetSharedMemoryAs<const void*>(
8867 pixels_shm_id, pixels_shm_offset, pixels_size);
8868 if (!pixels) {
8869 return error::kOutOfBounds;
8873 glTexImage3D(target, level, internal_format, width, height, depth, border,
8874 format, type, pixels);
8876 // This may be a slow command. Exit command processing to allow for
8877 // context preemption and GPU watchdog checks.
8878 ExitCommandProcessingEarly();
8879 return error::kNoError;
8882 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
8883 GLenum target,
8884 GLint level,
8885 GLint xoffset,
8886 GLint yoffset,
8887 GLsizei width,
8888 GLsizei height,
8889 GLenum format,
8890 GLsizei image_size,
8891 const void * data) {
8892 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8893 &state_, target);
8894 if (!texture_ref) {
8895 LOCAL_SET_GL_ERROR(
8896 GL_INVALID_OPERATION,
8897 "glCompressedTexSubImage2D", "unknown texture for target");
8898 return;
8900 Texture* texture = texture_ref->texture();
8901 GLenum type = 0;
8902 GLenum internal_format = 0;
8903 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8904 LOCAL_SET_GL_ERROR(
8905 GL_INVALID_OPERATION,
8906 "glCompressedTexSubImage2D", "level does not exist.");
8907 return;
8909 if (internal_format != format) {
8910 LOCAL_SET_GL_ERROR(
8911 GL_INVALID_OPERATION,
8912 "glCompressedTexSubImage2D", "format does not match internal format.");
8913 return;
8915 if (!texture->ValidForTexture(
8916 target, level, xoffset, yoffset, width, height, type)) {
8917 LOCAL_SET_GL_ERROR(
8918 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
8919 return;
8922 if (!ValidateCompressedTexFuncData(
8923 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8924 !ValidateCompressedTexSubDimensions(
8925 "glCompressedTexSubImage2D",
8926 target, level, xoffset, yoffset, width, height, format, texture)) {
8927 return;
8931 // Note: There is no need to deal with texture cleared tracking here
8932 // because the validation above means you can only get here if the level
8933 // is already a matching compressed format and in that case
8934 // CompressedTexImage2D already cleared the texture.
8935 glCompressedTexSubImage2D(
8936 target, level, xoffset, yoffset, width, height, format, image_size, data);
8938 // This may be a slow command. Exit command processing to allow for
8939 // context preemption and GPU watchdog checks.
8940 ExitCommandProcessingEarly();
8943 static void Clip(
8944 GLint start, GLint range, GLint sourceRange,
8945 GLint* out_start, GLint* out_range) {
8946 DCHECK(out_start);
8947 DCHECK(out_range);
8948 if (start < 0) {
8949 range += start;
8950 start = 0;
8952 GLint end = start + range;
8953 if (end > sourceRange) {
8954 range -= end - sourceRange;
8956 *out_start = start;
8957 *out_range = range;
8960 void GLES2DecoderImpl::DoCopyTexImage2D(
8961 GLenum target,
8962 GLint level,
8963 GLenum internal_format,
8964 GLint x,
8965 GLint y,
8966 GLsizei width,
8967 GLsizei height,
8968 GLint border) {
8969 DCHECK(!ShouldDeferReads());
8970 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8971 &state_, target);
8972 if (!texture_ref) {
8973 LOCAL_SET_GL_ERROR(
8974 GL_INVALID_OPERATION,
8975 "glCopyTexImage2D", "unknown texture for target");
8976 return;
8978 Texture* texture = texture_ref->texture();
8979 if (texture->IsImmutable()) {
8980 LOCAL_SET_GL_ERROR(
8981 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
8982 return;
8984 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8985 border != 0) {
8986 LOCAL_SET_GL_ERROR(
8987 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
8988 return;
8990 if (!texture_manager()->ValidateFormatAndTypeCombination(
8991 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
8992 GL_UNSIGNED_BYTE)) {
8993 return;
8996 // Check we have compatible formats.
8997 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8998 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8999 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
9001 if ((channels_needed & channels_exist) != channels_needed) {
9002 LOCAL_SET_GL_ERROR(
9003 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
9004 return;
9007 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9008 LOCAL_SET_GL_ERROR(
9009 GL_INVALID_OPERATION,
9010 "glCopyTexImage2D", "can not be used with depth or stencil textures");
9011 return;
9014 uint32 estimated_size = 0;
9015 if (!GLES2Util::ComputeImageDataSizes(
9016 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
9017 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
9018 LOCAL_SET_GL_ERROR(
9019 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
9020 return;
9023 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9024 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
9025 return;
9028 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
9029 return;
9032 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9033 LOCAL_SET_GL_ERROR(
9034 GL_INVALID_OPERATION,
9035 "glCopyTexImage2D", "source and destination textures are the same");
9036 return;
9039 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
9040 return;
9043 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
9044 ScopedResolvedFrameBufferBinder binder(this, false, true);
9045 gfx::Size size = GetBoundReadFrameBufferSize();
9047 if (texture->IsAttachedToFramebuffer()) {
9048 framebuffer_state_.clear_state_dirty = true;
9051 // Clip to size to source dimensions
9052 GLint copyX = 0;
9053 GLint copyY = 0;
9054 GLint copyWidth = 0;
9055 GLint copyHeight = 0;
9056 Clip(x, width, size.width(), &copyX, &copyWidth);
9057 Clip(y, height, size.height(), &copyY, &copyHeight);
9059 if (copyX != x ||
9060 copyY != y ||
9061 copyWidth != width ||
9062 copyHeight != height) {
9063 // some part was clipped so clear the texture.
9064 if (!ClearLevel(
9065 texture->service_id(), texture->target(),
9066 target, level, internal_format, internal_format, GL_UNSIGNED_BYTE,
9067 width, height, texture->IsImmutable())) {
9068 LOCAL_SET_GL_ERROR(
9069 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
9070 return;
9072 if (copyHeight > 0 && copyWidth > 0) {
9073 GLint dx = copyX - x;
9074 GLint dy = copyY - y;
9075 GLint destX = dx;
9076 GLint destY = dy;
9077 ScopedModifyPixels modify(texture_ref);
9078 glCopyTexSubImage2D(target, level,
9079 destX, destY, copyX, copyY,
9080 copyWidth, copyHeight);
9082 } else {
9083 ScopedModifyPixels modify(texture_ref);
9084 glCopyTexImage2D(target, level, internal_format,
9085 copyX, copyY, copyWidth, copyHeight, border);
9087 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
9088 if (error == GL_NO_ERROR) {
9089 texture_manager()->SetLevelInfo(
9090 texture_ref, target, level, internal_format, width, height, 1,
9091 border, internal_format, GL_UNSIGNED_BYTE, true);
9094 // This may be a slow command. Exit command processing to allow for
9095 // context preemption and GPU watchdog checks.
9096 ExitCommandProcessingEarly();
9099 void GLES2DecoderImpl::DoCopyTexSubImage2D(
9100 GLenum target,
9101 GLint level,
9102 GLint xoffset,
9103 GLint yoffset,
9104 GLint x,
9105 GLint y,
9106 GLsizei width,
9107 GLsizei height) {
9108 DCHECK(!ShouldDeferReads());
9109 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9110 &state_, target);
9111 if (!texture_ref) {
9112 LOCAL_SET_GL_ERROR(
9113 GL_INVALID_OPERATION,
9114 "glCopyTexSubImage2D", "unknown texture for target");
9115 return;
9117 Texture* texture = texture_ref->texture();
9118 GLenum type = 0;
9119 GLenum format = 0;
9120 if (!texture->GetLevelType(target, level, &type, &format) ||
9121 !texture->ValidForTexture(
9122 target, level, xoffset, yoffset, width, height, type)) {
9123 LOCAL_SET_GL_ERROR(
9124 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
9125 return;
9127 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
9128 LOCAL_SET_GL_ERROR(
9129 GL_INVALID_OPERATION,
9130 "glCopyTexSubImage2D", "async upload pending for texture");
9131 return;
9134 // Check we have compatible formats.
9135 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
9136 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
9137 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
9139 if (!channels_needed ||
9140 (channels_needed & channels_exist) != channels_needed) {
9141 LOCAL_SET_GL_ERROR(
9142 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
9143 return;
9146 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9147 LOCAL_SET_GL_ERROR(
9148 GL_INVALID_OPERATION,
9149 "glCopySubImage2D", "can not be used with depth or stencil textures");
9150 return;
9153 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
9154 return;
9157 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
9158 LOCAL_SET_GL_ERROR(
9159 GL_INVALID_OPERATION,
9160 "glCopyTexSubImage2D", "source and destination textures are the same");
9161 return;
9164 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
9165 return;
9168 ScopedResolvedFrameBufferBinder binder(this, false, true);
9169 gfx::Size size = GetBoundReadFrameBufferSize();
9170 GLint copyX = 0;
9171 GLint copyY = 0;
9172 GLint copyWidth = 0;
9173 GLint copyHeight = 0;
9174 Clip(x, width, size.width(), &copyX, &copyWidth);
9175 Clip(y, height, size.height(), &copyY, &copyHeight);
9177 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
9178 height != size.height()) {
9179 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
9180 level)) {
9181 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
9182 "dimensions too big");
9183 return;
9185 } else {
9186 // Write all pixels in below.
9187 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9190 if (copyX != x ||
9191 copyY != y ||
9192 copyWidth != width ||
9193 copyHeight != height) {
9194 // some part was clipped so clear the sub rect.
9195 uint32 pixels_size = 0;
9196 if (!GLES2Util::ComputeImageDataSizes(
9197 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9198 NULL, NULL)) {
9199 LOCAL_SET_GL_ERROR(
9200 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
9201 return;
9203 scoped_ptr<char[]> zero(new char[pixels_size]);
9204 memset(zero.get(), 0, pixels_size);
9205 ScopedModifyPixels modify(texture_ref);
9206 glTexSubImage2D(
9207 target, level, xoffset, yoffset, width, height,
9208 format, type, zero.get());
9211 if (copyHeight > 0 && copyWidth > 0) {
9212 GLint dx = copyX - x;
9213 GLint dy = copyY - y;
9214 GLint destX = xoffset + dx;
9215 GLint destY = yoffset + dy;
9216 ScopedModifyPixels modify(texture_ref);
9217 glCopyTexSubImage2D(target, level,
9218 destX, destY, copyX, copyY,
9219 copyWidth, copyHeight);
9222 // This may be a slow command. Exit command processing to allow for
9223 // context preemption and GPU watchdog checks.
9224 ExitCommandProcessingEarly();
9227 bool GLES2DecoderImpl::ValidateTexSubImage2D(
9228 error::Error* error,
9229 const char* function_name,
9230 GLenum target,
9231 GLint level,
9232 GLint xoffset,
9233 GLint yoffset,
9234 GLsizei width,
9235 GLsizei height,
9236 GLenum format,
9237 GLenum type,
9238 const void * data) {
9239 (*error) = error::kNoError;
9240 if (!validators_->texture_target.IsValid(target)) {
9241 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
9242 return false;
9244 if (width < 0) {
9245 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
9246 return false;
9248 if (height < 0) {
9249 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
9250 return false;
9252 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9253 &state_, target);
9254 if (!texture_ref) {
9255 LOCAL_SET_GL_ERROR(
9256 GL_INVALID_OPERATION,
9257 function_name, "unknown texture for target");
9258 return false;
9260 Texture* texture = texture_ref->texture();
9261 GLenum current_type = 0;
9262 GLenum internal_format = 0;
9263 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
9264 LOCAL_SET_GL_ERROR(
9265 GL_INVALID_OPERATION, function_name, "level does not exist.");
9266 return false;
9268 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
9269 function_name, format, type, internal_format, level)) {
9270 return false;
9272 if (type != current_type) {
9273 LOCAL_SET_GL_ERROR(
9274 GL_INVALID_OPERATION,
9275 function_name, "type does not match type of texture.");
9276 return false;
9278 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
9279 LOCAL_SET_GL_ERROR(
9280 GL_INVALID_OPERATION,
9281 function_name, "async upload pending for texture");
9282 return false;
9284 if (!texture->ValidForTexture(
9285 target, level, xoffset, yoffset, width, height, type)) {
9286 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
9287 return false;
9289 if ((GLES2Util::GetChannelsForFormat(format) &
9290 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
9291 LOCAL_SET_GL_ERROR(
9292 GL_INVALID_OPERATION,
9293 function_name, "can not supply data for depth or stencil textures");
9294 return false;
9296 if (data == NULL) {
9297 (*error) = error::kOutOfBounds;
9298 return false;
9300 return true;
9303 error::Error GLES2DecoderImpl::DoTexSubImage2D(
9304 GLenum target,
9305 GLint level,
9306 GLint xoffset,
9307 GLint yoffset,
9308 GLsizei width,
9309 GLsizei height,
9310 GLenum format,
9311 GLenum type,
9312 const void * data) {
9313 error::Error error = error::kNoError;
9314 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
9315 xoffset, yoffset, width, height, format, type, data)) {
9316 return error;
9318 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9319 &state_, target);
9320 Texture* texture = texture_ref->texture();
9321 GLsizei tex_width = 0;
9322 GLsizei tex_height = 0;
9323 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
9324 DCHECK(ok);
9325 if (xoffset != 0 || yoffset != 0 ||
9326 width != tex_width || height != tex_height) {
9327 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
9328 target, level)) {
9329 LOCAL_SET_GL_ERROR(
9330 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
9331 return error::kNoError;
9333 ScopedTextureUploadTimer timer(&texture_state_);
9334 glTexSubImage2D(
9335 target, level, xoffset, yoffset, width, height, format, type, data);
9336 return error::kNoError;
9339 if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
9340 !texture->IsImmutable()) {
9341 ScopedTextureUploadTimer timer(&texture_state_);
9342 GLenum internal_format;
9343 GLenum tex_type;
9344 texture->GetLevelType(target, level, &tex_type, &internal_format);
9345 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
9346 // to look it up.
9347 glTexImage2D(
9348 target, level, internal_format, width, height, 0, format, type, data);
9349 } else {
9350 ScopedTextureUploadTimer timer(&texture_state_);
9351 glTexSubImage2D(
9352 target, level, xoffset, yoffset, width, height, format, type, data);
9354 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
9356 // This may be a slow command. Exit command processing to allow for
9357 // context preemption and GPU watchdog checks.
9358 ExitCommandProcessingEarly();
9359 return error::kNoError;
9362 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
9363 const void* cmd_data) {
9364 const gles2::cmds::TexSubImage2D& c =
9365 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
9366 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
9367 "width", c.width, "height", c.height);
9368 GLboolean internal = static_cast<GLboolean>(c.internal);
9369 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
9370 return error::kNoError;
9372 GLenum target = static_cast<GLenum>(c.target);
9373 GLint level = static_cast<GLint>(c.level);
9374 GLint xoffset = static_cast<GLint>(c.xoffset);
9375 GLint yoffset = static_cast<GLint>(c.yoffset);
9376 GLsizei width = static_cast<GLsizei>(c.width);
9377 GLsizei height = static_cast<GLsizei>(c.height);
9378 GLenum format = static_cast<GLenum>(c.format);
9379 GLenum type = static_cast<GLenum>(c.type);
9380 uint32 data_size;
9381 if (!GLES2Util::ComputeImageDataSizes(
9382 width, height, 1, format, type, state_.unpack_alignment, &data_size,
9383 NULL, NULL)) {
9384 return error::kOutOfBounds;
9386 const void* pixels = GetSharedMemoryAs<const void*>(
9387 c.pixels_shm_id, c.pixels_shm_offset, data_size);
9388 return DoTexSubImage2D(
9389 target, level, xoffset, yoffset, width, height, format, type, pixels);
9392 // TODO(zmo): Remove the below stub once we add the real function binding.
9393 // Currently it's missing due to a gmock limitation.
9394 static void glTexSubImage3D(
9395 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9396 GLsizei height, GLsizei width, GLsizei depth, GLenum format, GLenum type,
9397 const void* pixels) {
9398 NOTIMPLEMENTED();
9401 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
9402 const void* cmd_data) {
9403 // TODO(zmo): Unsafe ES3 API.
9404 if (!unsafe_es3_apis_enabled())
9405 return error::kUnknownCommand;
9407 const gles2::cmds::TexSubImage3D& c =
9408 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
9409 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
9410 "widthXheight", c.width * c.height, "depth", c.depth);
9411 GLenum target = static_cast<GLenum>(c.target);
9412 GLint level = static_cast<GLint>(c.level);
9413 GLint xoffset = static_cast<GLint>(c.xoffset);
9414 GLint yoffset = static_cast<GLint>(c.yoffset);
9415 GLint zoffset = static_cast<GLint>(c.zoffset);
9416 GLsizei width = static_cast<GLsizei>(c.width);
9417 GLsizei height = static_cast<GLsizei>(c.height);
9418 GLsizei depth = static_cast<GLsizei>(c.depth);
9419 GLenum format = static_cast<GLenum>(c.format);
9420 GLenum type = static_cast<GLenum>(c.type);
9421 uint32 data_size;
9422 if (!GLES2Util::ComputeImageDataSizes(
9423 width, height, depth, format, type, state_.unpack_alignment, &data_size,
9424 NULL, NULL)) {
9425 return error::kOutOfBounds;
9427 const void* pixels = GetSharedMemoryAs<const void*>(
9428 c.pixels_shm_id, c.pixels_shm_offset, data_size);
9429 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
9430 depth, format, type, pixels);
9431 return error::kNoError;
9434 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
9435 uint32 immediate_data_size,
9436 const void* cmd_data) {
9437 const gles2::cmds::GetVertexAttribPointerv& c =
9438 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
9439 GLuint index = static_cast<GLuint>(c.index);
9440 GLenum pname = static_cast<GLenum>(c.pname);
9441 typedef cmds::GetVertexAttribPointerv::Result Result;
9442 Result* result = GetSharedMemoryAs<Result*>(
9443 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
9444 if (!result) {
9445 return error::kOutOfBounds;
9447 // Check that the client initialized the result.
9448 if (result->size != 0) {
9449 return error::kInvalidArguments;
9451 if (!validators_->vertex_pointer.IsValid(pname)) {
9452 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9453 "glGetVertexAttribPointerv", pname, "pname");
9454 return error::kNoError;
9456 if (index >= group_->max_vertex_attribs()) {
9457 LOCAL_SET_GL_ERROR(
9458 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
9459 return error::kNoError;
9461 result->SetNumResults(1);
9462 *result->GetData() =
9463 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
9464 return error::kNoError;
9467 bool GLES2DecoderImpl::GetUniformSetup(
9468 GLuint program_id, GLint fake_location,
9469 uint32 shm_id, uint32 shm_offset,
9470 error::Error* error, GLint* real_location,
9471 GLuint* service_id, void** result_pointer, GLenum* result_type) {
9472 DCHECK(error);
9473 DCHECK(service_id);
9474 DCHECK(result_pointer);
9475 DCHECK(result_type);
9476 DCHECK(real_location);
9477 *error = error::kNoError;
9478 // Make sure we have enough room for the result on failure.
9479 SizedResult<GLint>* result;
9480 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9481 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
9482 if (!result) {
9483 *error = error::kOutOfBounds;
9484 return false;
9486 *result_pointer = result;
9487 // Set the result size to 0 so the client does not have to check for success.
9488 result->SetNumResults(0);
9489 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
9490 if (!program) {
9491 return false;
9493 if (!program->IsValid()) {
9494 // Program was not linked successfully. (ie, glLinkProgram)
9495 LOCAL_SET_GL_ERROR(
9496 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
9497 return false;
9499 *service_id = program->service_id();
9500 GLint array_index = -1;
9501 const Program::UniformInfo* uniform_info =
9502 program->GetUniformInfoByFakeLocation(
9503 fake_location, real_location, &array_index);
9504 if (!uniform_info) {
9505 // No such location.
9506 LOCAL_SET_GL_ERROR(
9507 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
9508 return false;
9510 GLenum type = uniform_info->type;
9511 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
9512 if (size == 0) {
9513 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
9514 return false;
9516 result = GetSharedMemoryAs<SizedResult<GLint>*>(
9517 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
9518 if (!result) {
9519 *error = error::kOutOfBounds;
9520 return false;
9522 result->size = size;
9523 *result_type = type;
9524 return true;
9527 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
9528 const void* cmd_data) {
9529 const gles2::cmds::GetUniformiv& c =
9530 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
9531 GLuint program = c.program;
9532 GLint fake_location = c.location;
9533 GLuint service_id;
9534 GLenum result_type;
9535 GLint real_location = -1;
9536 Error error;
9537 void* result;
9538 if (GetUniformSetup(
9539 program, fake_location, c.params_shm_id, c.params_shm_offset,
9540 &error, &real_location, &service_id, &result, &result_type)) {
9541 glGetUniformiv(
9542 service_id, real_location,
9543 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
9545 return error;
9548 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
9549 const void* cmd_data) {
9550 const gles2::cmds::GetUniformfv& c =
9551 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
9552 GLuint program = c.program;
9553 GLint fake_location = c.location;
9554 GLuint service_id;
9555 GLint real_location = -1;
9556 Error error;
9557 typedef cmds::GetUniformfv::Result Result;
9558 Result* result;
9559 GLenum result_type;
9560 if (GetUniformSetup(
9561 program, fake_location, c.params_shm_id, c.params_shm_offset,
9562 &error, &real_location, &service_id,
9563 reinterpret_cast<void**>(&result), &result_type)) {
9564 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
9565 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
9566 GLsizei num_values = result->GetNumResults();
9567 scoped_ptr<GLint[]> temp(new GLint[num_values]);
9568 glGetUniformiv(service_id, real_location, temp.get());
9569 GLfloat* dst = result->GetData();
9570 for (GLsizei ii = 0; ii < num_values; ++ii) {
9571 dst[ii] = (temp[ii] != 0);
9573 } else {
9574 glGetUniformfv(service_id, real_location, result->GetData());
9577 return error;
9580 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
9581 uint32 immediate_data_size,
9582 const void* cmd_data) {
9583 const gles2::cmds::GetShaderPrecisionFormat& c =
9584 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
9585 GLenum shader_type = static_cast<GLenum>(c.shadertype);
9586 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
9587 typedef cmds::GetShaderPrecisionFormat::Result Result;
9588 Result* result = GetSharedMemoryAs<Result*>(
9589 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9590 if (!result) {
9591 return error::kOutOfBounds;
9593 // Check that the client initialized the result.
9594 if (result->success != 0) {
9595 return error::kInvalidArguments;
9597 if (!validators_->shader_type.IsValid(shader_type)) {
9598 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9599 "glGetShaderPrecisionFormat", shader_type, "shader_type");
9600 return error::kNoError;
9602 if (!validators_->shader_precision.IsValid(precision_type)) {
9603 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9604 "glGetShaderPrecisionFormat", precision_type, "precision_type");
9605 return error::kNoError;
9608 result->success = 1; // true
9610 GLint range[2] = { 0, 0 };
9611 GLint precision = 0;
9612 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
9614 result->min_range = range[0];
9615 result->max_range = range[1];
9616 result->precision = precision;
9618 return error::kNoError;
9621 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
9622 uint32 immediate_data_size,
9623 const void* cmd_data) {
9624 const gles2::cmds::GetAttachedShaders& c =
9625 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
9626 uint32 result_size = c.result_size;
9627 GLuint program_id = static_cast<GLuint>(c.program);
9628 Program* program = GetProgramInfoNotShader(
9629 program_id, "glGetAttachedShaders");
9630 if (!program) {
9631 return error::kNoError;
9633 typedef cmds::GetAttachedShaders::Result Result;
9634 uint32 max_count = Result::ComputeMaxResults(result_size);
9635 Result* result = GetSharedMemoryAs<Result*>(
9636 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
9637 if (!result) {
9638 return error::kOutOfBounds;
9640 // Check that the client initialized the result.
9641 if (result->size != 0) {
9642 return error::kInvalidArguments;
9644 GLsizei count = 0;
9645 glGetAttachedShaders(
9646 program->service_id(), max_count, &count, result->GetData());
9647 for (GLsizei ii = 0; ii < count; ++ii) {
9648 if (!shader_manager()->GetClientId(result->GetData()[ii],
9649 &result->GetData()[ii])) {
9650 NOTREACHED();
9651 return error::kGenericError;
9654 result->SetNumResults(count);
9655 return error::kNoError;
9658 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
9659 uint32 immediate_data_size,
9660 const void* cmd_data) {
9661 const gles2::cmds::GetActiveUniform& c =
9662 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
9663 GLuint program_id = c.program;
9664 GLuint index = c.index;
9665 uint32 name_bucket_id = c.name_bucket_id;
9666 typedef cmds::GetActiveUniform::Result Result;
9667 Result* result = GetSharedMemoryAs<Result*>(
9668 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9669 if (!result) {
9670 return error::kOutOfBounds;
9672 // Check that the client initialized the result.
9673 if (result->success != 0) {
9674 return error::kInvalidArguments;
9676 Program* program = GetProgramInfoNotShader(
9677 program_id, "glGetActiveUniform");
9678 if (!program) {
9679 return error::kNoError;
9681 const Program::UniformInfo* uniform_info =
9682 program->GetUniformInfo(index);
9683 if (!uniform_info) {
9684 LOCAL_SET_GL_ERROR(
9685 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
9686 return error::kNoError;
9688 result->success = 1; // true.
9689 result->size = uniform_info->size;
9690 result->type = uniform_info->type;
9691 Bucket* bucket = CreateBucket(name_bucket_id);
9692 bucket->SetFromString(uniform_info->name.c_str());
9693 return error::kNoError;
9696 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
9697 const void* cmd_data) {
9698 const gles2::cmds::GetActiveAttrib& c =
9699 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
9700 GLuint program_id = c.program;
9701 GLuint index = c.index;
9702 uint32 name_bucket_id = c.name_bucket_id;
9703 typedef cmds::GetActiveAttrib::Result Result;
9704 Result* result = GetSharedMemoryAs<Result*>(
9705 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9706 if (!result) {
9707 return error::kOutOfBounds;
9709 // Check that the client initialized the result.
9710 if (result->success != 0) {
9711 return error::kInvalidArguments;
9713 Program* program = GetProgramInfoNotShader(
9714 program_id, "glGetActiveAttrib");
9715 if (!program) {
9716 return error::kNoError;
9718 const Program::VertexAttrib* attrib_info =
9719 program->GetAttribInfo(index);
9720 if (!attrib_info) {
9721 LOCAL_SET_GL_ERROR(
9722 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
9723 return error::kNoError;
9725 result->success = 1; // true.
9726 result->size = attrib_info->size;
9727 result->type = attrib_info->type;
9728 Bucket* bucket = CreateBucket(name_bucket_id);
9729 bucket->SetFromString(attrib_info->name.c_str());
9730 return error::kNoError;
9733 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
9734 const void* cmd_data) {
9735 #if 1 // No binary shader support.
9736 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
9737 return error::kNoError;
9738 #else
9739 GLsizei n = static_cast<GLsizei>(c.n);
9740 if (n < 0) {
9741 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
9742 return error::kNoError;
9744 GLsizei length = static_cast<GLsizei>(c.length);
9745 if (length < 0) {
9746 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
9747 return error::kNoError;
9749 uint32 data_size;
9750 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
9751 return error::kOutOfBounds;
9753 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
9754 c.shaders_shm_id, c.shaders_shm_offset, data_size);
9755 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
9756 const void* binary = GetSharedMemoryAs<const void*>(
9757 c.binary_shm_id, c.binary_shm_offset, length);
9758 if (shaders == NULL || binary == NULL) {
9759 return error::kOutOfBounds;
9761 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
9762 for (GLsizei ii = 0; ii < n; ++ii) {
9763 Shader* shader = GetShader(shaders[ii]);
9764 if (!shader) {
9765 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
9766 return error::kNoError;
9768 service_ids[ii] = shader->service_id();
9770 // TODO(gman): call glShaderBinary
9771 return error::kNoError;
9772 #endif
9775 void GLES2DecoderImpl::DoSwapBuffers() {
9776 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
9778 int this_frame_number = frame_number_++;
9779 // TRACE_EVENT for gpu tests:
9780 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
9781 TRACE_EVENT_SCOPE_THREAD,
9782 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
9783 "width", (is_offscreen ? offscreen_size_.width() :
9784 surface_->GetSize().width()));
9785 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
9786 "offscreen", is_offscreen,
9787 "frame", this_frame_number);
9789 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
9792 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
9793 "gpu_toplevel", "SwapBuffer");
9795 bool is_tracing;
9796 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
9797 &is_tracing);
9798 if (is_tracing) {
9799 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
9800 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
9801 is_offscreen ? offscreen_size_ : surface_->GetSize());
9804 // If offscreen then don't actually SwapBuffers to the display. Just copy
9805 // the rendered frame to another frame buffer.
9806 if (is_offscreen) {
9807 TRACE_EVENT2("gpu", "Offscreen",
9808 "width", offscreen_size_.width(), "height", offscreen_size_.height());
9809 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
9810 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
9811 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
9812 // fix this.
9813 if (workarounds().needs_offscreen_buffer_workaround) {
9814 offscreen_saved_frame_buffer_->Create();
9815 glFinish();
9818 // Allocate the offscreen saved color texture.
9819 DCHECK(offscreen_saved_color_format_);
9820 offscreen_saved_color_texture_->AllocateStorage(
9821 offscreen_size_, offscreen_saved_color_format_, false);
9823 offscreen_saved_frame_buffer_->AttachRenderTexture(
9824 offscreen_saved_color_texture_.get());
9825 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
9826 if (offscreen_saved_frame_buffer_->CheckStatus() !=
9827 GL_FRAMEBUFFER_COMPLETE) {
9828 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
9829 << "because offscreen saved FBO was incomplete.";
9830 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9831 return;
9834 // Clear the offscreen color texture.
9835 // TODO(piman): Is this still necessary?
9837 ScopedFrameBufferBinder binder(this,
9838 offscreen_saved_frame_buffer_->id());
9839 glClearColor(0, 0, 0, 0);
9840 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9841 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
9842 glClear(GL_COLOR_BUFFER_BIT);
9843 RestoreClearState();
9847 UpdateParentTextureInfo();
9850 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
9851 return;
9852 ScopedGLErrorSuppressor suppressor(
9853 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
9855 if (IsOffscreenBufferMultisampled()) {
9856 // For multisampled buffers, resolve the frame buffer.
9857 ScopedResolvedFrameBufferBinder binder(this, true, false);
9858 } else {
9859 ScopedFrameBufferBinder binder(this,
9860 offscreen_target_frame_buffer_->id());
9862 if (offscreen_target_buffer_preserved_) {
9863 // Copy the target frame buffer to the saved offscreen texture.
9864 offscreen_saved_color_texture_->Copy(
9865 offscreen_saved_color_texture_->size(),
9866 offscreen_saved_color_format_);
9867 } else {
9868 // Flip the textures in the parent context via the texture manager.
9869 if (!!offscreen_saved_color_texture_info_.get())
9870 offscreen_saved_color_texture_info_->texture()->
9871 SetServiceId(offscreen_target_color_texture_->id());
9873 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
9874 offscreen_target_frame_buffer_->AttachRenderTexture(
9875 offscreen_target_color_texture_.get());
9878 // Ensure the side effects of the copy are visible to the parent
9879 // context. There is no need to do this for ANGLE because it uses a
9880 // single D3D device for all contexts.
9881 if (!feature_info_->gl_version_info().is_angle)
9882 glFlush();
9884 } else {
9885 if (!surface_->SwapBuffers()) {
9886 LOG(ERROR) << "Context lost because SwapBuffers failed.";
9887 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
9891 // This may be a slow command. Exit command processing to allow for
9892 // context preemption and GPU watchdog checks.
9893 ExitCommandProcessingEarly();
9896 void GLES2DecoderImpl::DoSwapInterval(int interval)
9898 context_->SetSwapInterval(interval);
9901 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
9902 uint32 immediate_data_size,
9903 const void* cmd_data) {
9904 const gles2::cmds::EnableFeatureCHROMIUM& c =
9905 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
9906 Bucket* bucket = GetBucket(c.bucket_id);
9907 if (!bucket || bucket->size() == 0) {
9908 return error::kInvalidArguments;
9910 typedef cmds::EnableFeatureCHROMIUM::Result Result;
9911 Result* result = GetSharedMemoryAs<Result*>(
9912 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9913 if (!result) {
9914 return error::kOutOfBounds;
9916 // Check that the client initialized the result.
9917 if (*result != 0) {
9918 return error::kInvalidArguments;
9920 std::string feature_str;
9921 if (!bucket->GetAsString(&feature_str)) {
9922 return error::kInvalidArguments;
9925 // TODO(gman): make this some kind of table to function pointer thingy.
9926 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
9927 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
9928 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
9929 buffer_manager()->set_allow_fixed_attribs(true);
9930 // TODO(gman): decide how to remove the need for this const_cast.
9931 // I could make validators_ non const but that seems bad as this is the only
9932 // place it is needed. I could make some special friend class of validators
9933 // just to allow this to set them. That seems silly. I could refactor this
9934 // code to use the extension mechanism or the initialization attributes to
9935 // turn this feature on. Given that the only real point of this is to make
9936 // the conformance tests pass and given that there is lots of real work that
9937 // needs to be done it seems like refactoring for one to one of those
9938 // methods is a very low priority.
9939 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
9940 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
9941 force_webgl_glsl_validation_ = true;
9942 InitializeShaderTranslator();
9943 } else {
9944 return error::kNoError;
9947 *result = 1; // true.
9948 return error::kNoError;
9951 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
9952 uint32 immediate_data_size,
9953 const void* cmd_data) {
9954 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
9955 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
9956 cmd_data);
9957 Bucket* bucket = CreateBucket(c.bucket_id);
9958 scoped_refptr<FeatureInfo> info(new FeatureInfo());
9959 info->Initialize(disallowed_features_);
9960 bucket->SetFromString(info->extensions().c_str());
9961 return error::kNoError;
9964 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
9965 uint32 immediate_data_size,
9966 const void* cmd_data) {
9967 const gles2::cmds::RequestExtensionCHROMIUM& c =
9968 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
9969 Bucket* bucket = GetBucket(c.bucket_id);
9970 if (!bucket || bucket->size() == 0) {
9971 return error::kInvalidArguments;
9973 std::string feature_str;
9974 if (!bucket->GetAsString(&feature_str)) {
9975 return error::kInvalidArguments;
9978 bool desire_webgl_glsl_validation =
9979 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
9980 bool desire_standard_derivatives = false;
9981 bool desire_frag_depth = false;
9982 bool desire_draw_buffers = false;
9983 bool desire_shader_texture_lod = false;
9984 if (force_webgl_glsl_validation_) {
9985 desire_standard_derivatives =
9986 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
9987 desire_frag_depth =
9988 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
9989 desire_draw_buffers =
9990 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
9991 desire_shader_texture_lod =
9992 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
9995 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
9996 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
9997 desire_frag_depth != frag_depth_explicitly_enabled_ ||
9998 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
9999 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
10000 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
10001 frag_depth_explicitly_enabled_ |= desire_frag_depth;
10002 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
10003 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
10004 InitializeShaderTranslator();
10007 UpdateCapabilities();
10009 return error::kNoError;
10012 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
10013 uint32 immediate_data_size,
10014 const void* cmd_data) {
10015 const gles2::cmds::GetProgramInfoCHROMIUM& c =
10016 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
10017 GLuint program_id = static_cast<GLuint>(c.program);
10018 uint32 bucket_id = c.bucket_id;
10019 Bucket* bucket = CreateBucket(bucket_id);
10020 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
10021 Program* program = NULL;
10022 program = GetProgram(program_id);
10023 if (!program || !program->IsValid()) {
10024 return error::kNoError;
10026 program->GetProgramInfo(program_manager(), bucket);
10027 return error::kNoError;
10030 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
10031 switch (reset_status_) {
10032 case GL_NO_ERROR:
10033 // TODO(kbr): improve the precision of the error code in this case.
10034 // Consider delegating to context for error code if MakeCurrent fails.
10035 return error::kUnknown;
10036 case GL_GUILTY_CONTEXT_RESET_ARB:
10037 return error::kGuilty;
10038 case GL_INNOCENT_CONTEXT_RESET_ARB:
10039 return error::kInnocent;
10040 case GL_UNKNOWN_CONTEXT_RESET_ARB:
10041 return error::kUnknown;
10044 NOTREACHED();
10045 return error::kUnknown;
10048 void GLES2DecoderImpl::MaybeExitOnContextLost() {
10049 // Some D3D drivers cannot recover from device lost in the GPU process
10050 // sandbox. Allow a new GPU process to launch.
10051 if (workarounds().exit_on_context_lost) {
10052 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
10053 << " a D3D device in the Chrome GPU process sandbox.";
10054 #if defined(OS_WIN)
10055 base::win::SetShouldCrashOnProcessDetach(false);
10056 #endif
10057 exit(0);
10061 bool GLES2DecoderImpl::WasContextLost() {
10062 if (reset_status_ != GL_NO_ERROR) {
10063 MaybeExitOnContextLost();
10064 return true;
10066 if (context_->WasAllocatedUsingRobustnessExtension()) {
10067 GLenum status = GL_NO_ERROR;
10068 if (has_robustness_extension_)
10069 status = glGetGraphicsResetStatusARB();
10070 if (status != GL_NO_ERROR) {
10071 // The graphics card was reset. Signal a lost context to the application.
10072 reset_status_ = status;
10073 reset_by_robustness_extension_ = true;
10074 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
10075 << " context lost via ARB/EXT_robustness. Reset status = "
10076 << GLES2Util::GetStringEnum(status);
10077 MaybeExitOnContextLost();
10078 return true;
10081 return false;
10084 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
10085 return WasContextLost() && reset_by_robustness_extension_;
10088 void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
10089 // Only loses the context once.
10090 if (reset_status_ != GL_NO_ERROR) {
10091 return;
10094 if (workarounds().use_virtualized_gl_contexts) {
10095 // If the context is virtual, the real context being guilty does not ensure
10096 // that the virtual context is guilty.
10097 if (reset_status == GL_GUILTY_CONTEXT_RESET_ARB) {
10098 reset_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
10100 } else if (reset_status == GL_UNKNOWN_CONTEXT_RESET_ARB &&
10101 has_robustness_extension_) {
10102 // If the reason for the call was a GL error, we can try to determine the
10103 // reset status more accurately.
10104 GLenum driver_status = glGetGraphicsResetStatusARB();
10105 if (driver_status == GL_GUILTY_CONTEXT_RESET_ARB ||
10106 driver_status == GL_INNOCENT_CONTEXT_RESET_ARB) {
10107 reset_status = driver_status;
10111 // Marks this context as lost.
10112 reset_status_ = reset_status;
10113 current_decoder_error_ = error::kLostContext;
10116 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
10117 uint32 immediate_data_size,
10118 const void* cmd_data) {
10119 return error::kUnknownCommand;
10122 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
10123 uint32 immediate_data_size,
10124 const void* cmd_data) {
10125 const gles2::cmds::WaitSyncPointCHROMIUM& c =
10126 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
10127 uint32 sync_point = c.sync_point;
10128 if (wait_sync_point_callback_.is_null())
10129 return error::kNoError;
10131 return wait_sync_point_callback_.Run(sync_point) ?
10132 error::kNoError : error::kDeferCommandUntilLater;
10135 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
10136 uint32 immediate_data_size,
10137 const void* cmd_data) {
10138 if (surface_->DeferDraws())
10139 return error::kDeferCommandUntilLater;
10140 if (!surface_->SetBackbufferAllocation(false))
10141 return error::kLostContext;
10142 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
10143 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
10144 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
10145 return error::kNoError;
10148 bool GLES2DecoderImpl::GenQueriesEXTHelper(
10149 GLsizei n, const GLuint* client_ids) {
10150 for (GLsizei ii = 0; ii < n; ++ii) {
10151 if (query_manager_->GetQuery(client_ids[ii])) {
10152 return false;
10155 query_manager_->GenQueries(n, client_ids);
10156 return true;
10159 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
10160 GLsizei n, const GLuint* client_ids) {
10161 for (GLsizei ii = 0; ii < n; ++ii) {
10162 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
10163 if (query && !query->IsDeleted()) {
10164 ContextState::QueryMap::iterator it =
10165 state_.current_queries.find(query->target());
10166 if (it != state_.current_queries.end())
10167 state_.current_queries.erase(it);
10169 query->Destroy(true);
10171 query_manager_->RemoveQuery(client_ids[ii]);
10175 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
10176 if (query_manager_.get() == NULL) {
10177 return false;
10179 if (!query_manager_->ProcessPendingQueries(did_finish)) {
10180 current_decoder_error_ = error::kOutOfBounds;
10182 return query_manager_->HavePendingQueries();
10185 // Note that if there are no pending readpixels right now,
10186 // this function will call the callback immediately.
10187 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
10188 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
10189 pending_readpixel_fences_.back()->callbacks.push_back(callback);
10190 } else {
10191 callback.Run();
10195 void GLES2DecoderImpl::ProcessPendingReadPixels() {
10196 while (!pending_readpixel_fences_.empty() &&
10197 pending_readpixel_fences_.front()->fence->HasCompleted()) {
10198 std::vector<base::Closure> callbacks =
10199 pending_readpixel_fences_.front()->callbacks;
10200 pending_readpixel_fences_.pop();
10201 for (size_t i = 0; i < callbacks.size(); i++) {
10202 callbacks[i].Run();
10207 bool GLES2DecoderImpl::HasMoreIdleWork() {
10208 return !pending_readpixel_fences_.empty() ||
10209 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
10212 void GLES2DecoderImpl::PerformIdleWork() {
10213 ProcessPendingReadPixels();
10214 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
10215 return;
10216 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
10217 ProcessFinishedAsyncTransfers();
10220 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
10221 const void* cmd_data) {
10222 const gles2::cmds::BeginQueryEXT& c =
10223 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
10224 GLenum target = static_cast<GLenum>(c.target);
10225 GLuint client_id = static_cast<GLuint>(c.id);
10226 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
10227 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
10229 switch (target) {
10230 case GL_COMMANDS_ISSUED_CHROMIUM:
10231 case GL_LATENCY_QUERY_CHROMIUM:
10232 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
10233 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
10234 case GL_GET_ERROR_QUERY_CHROMIUM:
10235 break;
10236 case GL_COMMANDS_COMPLETED_CHROMIUM:
10237 if (!features().chromium_sync_query) {
10238 LOCAL_SET_GL_ERROR(
10239 GL_INVALID_OPERATION, "glBeginQueryEXT",
10240 "not enabled for commands completed queries");
10241 return error::kNoError;
10243 break;
10244 default:
10245 if (!features().occlusion_query_boolean) {
10246 LOCAL_SET_GL_ERROR(
10247 GL_INVALID_OPERATION, "glBeginQueryEXT",
10248 "not enabled for occlusion queries");
10249 return error::kNoError;
10251 break;
10254 if (state_.current_queries.find(target) != state_.current_queries.end()) {
10255 LOCAL_SET_GL_ERROR(
10256 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
10257 return error::kNoError;
10260 if (client_id == 0) {
10261 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
10262 return error::kNoError;
10265 QueryManager::Query* query = query_manager_->GetQuery(client_id);
10266 if (!query) {
10267 if (!query_manager_->IsValidQuery(client_id)) {
10268 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10269 "glBeginQueryEXT",
10270 "id not made by glGenQueriesEXT");
10271 return error::kNoError;
10273 query = query_manager_->CreateQuery(
10274 target, client_id, sync_shm_id, sync_shm_offset);
10277 if (query->target() != target) {
10278 LOCAL_SET_GL_ERROR(
10279 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
10280 return error::kNoError;
10281 } else if (query->shm_id() != sync_shm_id ||
10282 query->shm_offset() != sync_shm_offset) {
10283 DLOG(ERROR) << "Shared memory used by query not the same as before";
10284 return error::kInvalidArguments;
10287 if (!query_manager_->BeginQuery(query)) {
10288 return error::kOutOfBounds;
10291 state_.current_queries[target] = query;
10292 return error::kNoError;
10295 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
10296 const void* cmd_data) {
10297 const gles2::cmds::EndQueryEXT& c =
10298 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
10299 GLenum target = static_cast<GLenum>(c.target);
10300 uint32 submit_count = static_cast<GLuint>(c.submit_count);
10301 ContextState::QueryMap::iterator it = state_.current_queries.find(target);
10303 if (it == state_.current_queries.end()) {
10304 LOCAL_SET_GL_ERROR(
10305 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
10306 return error::kNoError;
10309 QueryManager::Query* query = it->second.get();
10310 if (!query_manager_->EndQuery(query, submit_count)) {
10311 return error::kOutOfBounds;
10314 query_manager_->ProcessPendingTransferQueries();
10316 state_.current_queries.erase(it);
10317 return error::kNoError;
10320 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
10321 GLsizei n, const GLuint* client_ids) {
10322 for (GLsizei ii = 0; ii < n; ++ii) {
10323 if (GetVertexAttribManager(client_ids[ii])) {
10324 return false;
10328 if (!features().native_vertex_array_object) {
10329 // Emulated VAO
10330 for (GLsizei ii = 0; ii < n; ++ii) {
10331 CreateVertexAttribManager(client_ids[ii], 0, true);
10333 } else {
10334 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
10336 glGenVertexArraysOES(n, service_ids.get());
10337 for (GLsizei ii = 0; ii < n; ++ii) {
10338 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
10342 return true;
10345 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
10346 GLsizei n, const GLuint* client_ids) {
10347 for (GLsizei ii = 0; ii < n; ++ii) {
10348 VertexAttribManager* vao =
10349 GetVertexAttribManager(client_ids[ii]);
10350 if (vao && !vao->IsDeleted()) {
10351 if (state_.vertex_attrib_manager.get() == vao) {
10352 DoBindVertexArrayOES(0);
10354 RemoveVertexAttribManager(client_ids[ii]);
10359 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
10360 VertexAttribManager* vao = NULL;
10361 if (client_id != 0) {
10362 vao = GetVertexAttribManager(client_id);
10363 if (!vao) {
10364 // Unlike most Bind* methods, the spec explicitly states that VertexArray
10365 // only allows names that have been previously generated. As such, we do
10366 // not generate new names here.
10367 LOCAL_SET_GL_ERROR(
10368 GL_INVALID_OPERATION,
10369 "glBindVertexArrayOES", "bad vertex array id.");
10370 current_decoder_error_ = error::kNoError;
10371 return;
10373 } else {
10374 vao = state_.default_vertex_attrib_manager.get();
10377 // Only set the VAO state if it's changed
10378 if (state_.vertex_attrib_manager.get() != vao) {
10379 state_.vertex_attrib_manager = vao;
10380 if (!features().native_vertex_array_object) {
10381 EmulateVertexArrayState();
10382 } else {
10383 GLuint service_id = vao->service_id();
10384 glBindVertexArrayOES(service_id);
10389 // Used when OES_vertex_array_object isn't natively supported
10390 void GLES2DecoderImpl::EmulateVertexArrayState() {
10391 // Setup the Vertex attribute state
10392 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
10393 RestoreStateForAttrib(vv, true);
10396 // Setup the element buffer
10397 Buffer* element_array_buffer =
10398 state_.vertex_attrib_manager->element_array_buffer();
10399 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
10400 element_array_buffer ? element_array_buffer->service_id() : 0);
10403 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
10404 const VertexAttribManager* vao =
10405 GetVertexAttribManager(client_id);
10406 return vao && vao->IsValid() && !vao->IsDeleted();
10409 #if defined(OS_MACOSX)
10410 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
10411 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
10412 texture_id);
10413 if (it != texture_to_io_surface_map_.end()) {
10414 // Found a previous IOSurface bound to this texture; release it.
10415 IOSurfaceRef surface = it->second;
10416 CFRelease(surface);
10417 texture_to_io_surface_map_.erase(it);
10420 #endif
10422 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
10423 GLenum target, GLsizei width, GLsizei height,
10424 GLuint io_surface_id, GLuint plane) {
10425 #if defined(OS_MACOSX)
10426 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
10427 LOCAL_SET_GL_ERROR(
10428 GL_INVALID_OPERATION,
10429 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
10430 return;
10433 if (target != GL_TEXTURE_RECTANGLE_ARB) {
10434 // This might be supported in the future, and if we could require
10435 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
10436 // could delete a lot of code. For now, perform strict validation so we
10437 // know what's going on.
10438 LOCAL_SET_GL_ERROR(
10439 GL_INVALID_OPERATION,
10440 "glTexImageIOSurface2DCHROMIUM",
10441 "requires TEXTURE_RECTANGLE_ARB target");
10442 return;
10445 // Default target might be conceptually valid, but disallow it to avoid
10446 // accidents.
10447 TextureRef* texture_ref =
10448 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10449 if (!texture_ref) {
10450 LOCAL_SET_GL_ERROR(
10451 GL_INVALID_OPERATION,
10452 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
10453 return;
10456 // Look up the new IOSurface. Note that because of asynchrony
10457 // between processes this might fail; during live resizing the
10458 // plugin process might allocate and release an IOSurface before
10459 // this process gets a chance to look it up. Hold on to any old
10460 // IOSurface in this case.
10461 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
10462 if (!surface) {
10463 LOCAL_SET_GL_ERROR(
10464 GL_INVALID_OPERATION,
10465 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
10466 return;
10469 // Release any IOSurface previously bound to this texture.
10470 ReleaseIOSurfaceForTexture(texture_ref->service_id());
10472 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
10473 texture_to_io_surface_map_.insert(
10474 std::make_pair(texture_ref->service_id(), surface));
10476 CGLContextObj context =
10477 static_cast<CGLContextObj>(context_->GetHandle());
10479 CGLError err = CGLTexImageIOSurface2D(
10480 context,
10481 target,
10482 GL_RGBA,
10483 width,
10484 height,
10485 GL_BGRA,
10486 GL_UNSIGNED_INT_8_8_8_8_REV,
10487 surface,
10488 plane);
10490 if (err != kCGLNoError) {
10491 LOCAL_SET_GL_ERROR(
10492 GL_INVALID_OPERATION,
10493 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
10494 return;
10497 texture_manager()->SetLevelInfo(
10498 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
10499 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
10501 #else
10502 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10503 "glTexImageIOSurface2DCHROMIUM", "not supported.");
10504 #endif
10507 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
10508 switch (internalformat) {
10509 case GL_RGB565:
10510 return GL_RGB;
10511 case GL_RGBA4:
10512 return GL_RGBA;
10513 case GL_RGB5_A1:
10514 return GL_RGBA;
10515 case GL_RGB8_OES:
10516 return GL_RGB;
10517 case GL_RGBA8_OES:
10518 return GL_RGBA;
10519 case GL_LUMINANCE8_ALPHA8_EXT:
10520 return GL_LUMINANCE_ALPHA;
10521 case GL_LUMINANCE8_EXT:
10522 return GL_LUMINANCE;
10523 case GL_ALPHA8_EXT:
10524 return GL_ALPHA;
10525 case GL_RGBA32F_EXT:
10526 return GL_RGBA;
10527 case GL_RGB32F_EXT:
10528 return GL_RGB;
10529 case GL_ALPHA32F_EXT:
10530 return GL_ALPHA;
10531 case GL_LUMINANCE32F_EXT:
10532 return GL_LUMINANCE;
10533 case GL_LUMINANCE_ALPHA32F_EXT:
10534 return GL_LUMINANCE_ALPHA;
10535 case GL_RGBA16F_EXT:
10536 return GL_RGBA;
10537 case GL_RGB16F_EXT:
10538 return GL_RGB;
10539 case GL_ALPHA16F_EXT:
10540 return GL_ALPHA;
10541 case GL_LUMINANCE16F_EXT:
10542 return GL_LUMINANCE;
10543 case GL_LUMINANCE_ALPHA16F_EXT:
10544 return GL_LUMINANCE_ALPHA;
10545 case GL_BGRA8_EXT:
10546 return GL_BGRA_EXT;
10547 case GL_SRGB8_ALPHA8_EXT:
10548 return GL_SRGB_ALPHA_EXT;
10549 default:
10550 return GL_NONE;
10554 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
10555 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
10556 GLenum internal_format, GLenum dest_type) {
10557 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
10559 TextureRef* dest_texture_ref = GetTexture(dest_id);
10560 TextureRef* source_texture_ref = GetTexture(source_id);
10562 if (!source_texture_ref || !dest_texture_ref) {
10563 LOCAL_SET_GL_ERROR(
10564 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
10565 return;
10568 if (GL_TEXTURE_2D != target) {
10569 LOCAL_SET_GL_ERROR(
10570 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
10571 return;
10574 Texture* source_texture = source_texture_ref->texture();
10575 Texture* dest_texture = dest_texture_ref->texture();
10576 if (dest_texture->target() != GL_TEXTURE_2D ||
10577 (source_texture->target() != GL_TEXTURE_2D &&
10578 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
10579 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
10580 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10581 "glCopyTextureCHROMIUM",
10582 "invalid texture target binding");
10583 return;
10586 int source_width, source_height, dest_width, dest_height;
10588 gfx::GLImage* image =
10589 source_texture->GetLevelImage(source_texture->target(), 0);
10590 if (image) {
10591 gfx::Size size = image->GetSize();
10592 source_width = size.width();
10593 source_height = size.height();
10594 if (source_width <= 0 || source_height <= 0) {
10595 LOCAL_SET_GL_ERROR(
10596 GL_INVALID_VALUE,
10597 "glCopyTextureChromium", "invalid image size");
10598 return;
10600 } else {
10601 if (!source_texture->GetLevelSize(
10602 source_texture->target(), 0, &source_width, &source_height)) {
10603 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
10604 "glCopyTextureChromium",
10605 "source texture has no level 0");
10606 return;
10609 // Check that this type of texture is allowed.
10610 if (!texture_manager()->ValidForTarget(
10611 source_texture->target(), level, source_width, source_height, 1)) {
10612 LOCAL_SET_GL_ERROR(
10613 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
10614 return;
10618 // Clear the source texture if necessary.
10619 if (!texture_manager()->ClearTextureLevel(
10620 this, source_texture_ref, source_texture->target(), 0)) {
10621 LOCAL_SET_GL_ERROR(
10622 GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
10623 return;
10626 GLenum source_type = 0;
10627 GLenum source_internal_format = 0;
10628 source_texture->GetLevelType(
10629 source_texture->target(), 0, &source_type, &source_internal_format);
10631 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
10632 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
10633 // renderable on some platforms.
10634 bool valid_dest_format = internal_format == GL_RGB ||
10635 internal_format == GL_RGBA ||
10636 internal_format == GL_BGRA_EXT;
10637 bool valid_source_format = source_internal_format == GL_ALPHA ||
10638 source_internal_format == GL_RGB ||
10639 source_internal_format == GL_RGBA ||
10640 source_internal_format == GL_LUMINANCE ||
10641 source_internal_format == GL_LUMINANCE_ALPHA ||
10642 source_internal_format == GL_BGRA_EXT;
10643 if (!valid_source_format || !valid_dest_format) {
10644 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10645 "glCopyTextureCHROMIUM",
10646 "invalid internal format");
10647 return;
10650 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
10651 // needed because it takes 10s of milliseconds to initialize.
10652 if (!copy_texture_CHROMIUM_.get()) {
10653 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10654 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
10655 copy_texture_CHROMIUM_->Initialize(this);
10656 RestoreCurrentFramebufferBindings();
10657 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
10658 return;
10661 GLenum dest_type_previous = dest_type;
10662 GLenum dest_internal_format = internal_format;
10663 bool dest_level_defined = dest_texture->GetLevelSize(
10664 GL_TEXTURE_2D, level, &dest_width, &dest_height);
10666 if (dest_level_defined) {
10667 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
10668 &dest_internal_format);
10671 // Resize the destination texture to the dimensions of the source texture.
10672 if (!dest_level_defined || dest_width != source_width ||
10673 dest_height != source_height ||
10674 dest_internal_format != internal_format ||
10675 dest_type_previous != dest_type) {
10676 // Ensure that the glTexImage2D succeeds.
10677 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
10678 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
10679 glTexImage2D(
10680 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
10681 0, internal_format, dest_type, NULL);
10682 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
10683 if (error != GL_NO_ERROR) {
10684 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
10685 return;
10688 texture_manager()->SetLevelInfo(
10689 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
10690 source_height, 1, 0, internal_format, dest_type, true);
10691 } else {
10692 texture_manager()->SetLevelCleared(
10693 dest_texture_ref, GL_TEXTURE_2D, level, true);
10696 ScopedModifyPixels modify(dest_texture_ref);
10698 // Try using GLImage::CopyTexImage when possible.
10699 bool unpack_premultiply_alpha_change =
10700 unpack_premultiply_alpha_ ^ unpack_unpremultiply_alpha_;
10701 if (image && !unpack_flip_y_ && !unpack_premultiply_alpha_change && !level) {
10702 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
10703 if (image->CopyTexImage(GL_TEXTURE_2D))
10704 return;
10707 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
10709 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
10710 // before presenting.
10711 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
10712 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
10713 // instead of using default matrix crbug.com/226218.
10714 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
10715 0.0f, 1.0f, 0.0f, 0.0f,
10716 0.0f, 0.0f, 1.0f, 0.0f,
10717 0.0f, 0.0f, 0.0f, 1.0f};
10718 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
10719 this,
10720 source_texture->target(),
10721 source_texture->service_id(),
10722 dest_texture->service_id(),
10723 level,
10724 source_width,
10725 source_height,
10726 unpack_flip_y_,
10727 unpack_premultiply_alpha_,
10728 unpack_unpremultiply_alpha_,
10729 default_matrix);
10730 } else {
10731 copy_texture_CHROMIUM_->DoCopyTexture(this,
10732 source_texture->target(),
10733 source_texture->service_id(),
10734 source_internal_format,
10735 dest_texture->service_id(),
10736 level,
10737 internal_format,
10738 source_width,
10739 source_height,
10740 unpack_flip_y_,
10741 unpack_premultiply_alpha_,
10742 unpack_unpremultiply_alpha_);
10745 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
10748 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
10749 switch (internalformat) {
10750 case GL_RGB565:
10751 return GL_UNSIGNED_SHORT_5_6_5;
10752 case GL_RGBA4:
10753 return GL_UNSIGNED_SHORT_4_4_4_4;
10754 case GL_RGB5_A1:
10755 return GL_UNSIGNED_SHORT_5_5_5_1;
10756 case GL_RGB8_OES:
10757 return GL_UNSIGNED_BYTE;
10758 case GL_RGBA8_OES:
10759 return GL_UNSIGNED_BYTE;
10760 case GL_LUMINANCE8_ALPHA8_EXT:
10761 return GL_UNSIGNED_BYTE;
10762 case GL_LUMINANCE8_EXT:
10763 return GL_UNSIGNED_BYTE;
10764 case GL_ALPHA8_EXT:
10765 return GL_UNSIGNED_BYTE;
10766 case GL_RGBA32F_EXT:
10767 return GL_FLOAT;
10768 case GL_RGB32F_EXT:
10769 return GL_FLOAT;
10770 case GL_ALPHA32F_EXT:
10771 return GL_FLOAT;
10772 case GL_LUMINANCE32F_EXT:
10773 return GL_FLOAT;
10774 case GL_LUMINANCE_ALPHA32F_EXT:
10775 return GL_FLOAT;
10776 case GL_RGBA16F_EXT:
10777 return GL_HALF_FLOAT_OES;
10778 case GL_RGB16F_EXT:
10779 return GL_HALF_FLOAT_OES;
10780 case GL_ALPHA16F_EXT:
10781 return GL_HALF_FLOAT_OES;
10782 case GL_LUMINANCE16F_EXT:
10783 return GL_HALF_FLOAT_OES;
10784 case GL_LUMINANCE_ALPHA16F_EXT:
10785 return GL_HALF_FLOAT_OES;
10786 case GL_BGRA8_EXT:
10787 return GL_UNSIGNED_BYTE;
10788 default:
10789 return GL_NONE;
10793 void GLES2DecoderImpl::DoTexStorage2DEXT(
10794 GLenum target,
10795 GLint levels,
10796 GLenum internal_format,
10797 GLsizei width,
10798 GLsizei height) {
10799 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
10800 "width", width, "height", height);
10801 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
10802 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
10803 LOCAL_SET_GL_ERROR(
10804 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
10805 return;
10807 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10808 &state_, target);
10809 if (!texture_ref) {
10810 LOCAL_SET_GL_ERROR(
10811 GL_INVALID_OPERATION,
10812 "glTexStorage2DEXT", "unknown texture for target");
10813 return;
10815 Texture* texture = texture_ref->texture();
10816 if (texture->IsAttachedToFramebuffer()) {
10817 framebuffer_state_.clear_state_dirty = true;
10819 if (texture->IsImmutable()) {
10820 LOCAL_SET_GL_ERROR(
10821 GL_INVALID_OPERATION,
10822 "glTexStorage2DEXT", "texture is immutable");
10823 return;
10826 GLenum format = ExtractFormatFromStorageFormat(internal_format);
10827 GLenum type = ExtractTypeFromStorageFormat(internal_format);
10830 GLsizei level_width = width;
10831 GLsizei level_height = height;
10832 uint32 estimated_size = 0;
10833 for (int ii = 0; ii < levels; ++ii) {
10834 uint32 level_size = 0;
10835 if (!GLES2Util::ComputeImageDataSizes(
10836 level_width, level_height, 1, format, type, state_.unpack_alignment,
10837 &estimated_size, NULL, NULL) ||
10838 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
10839 LOCAL_SET_GL_ERROR(
10840 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
10841 return;
10843 level_width = std::max(1, level_width >> 1);
10844 level_height = std::max(1, level_height >> 1);
10846 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10847 LOCAL_SET_GL_ERROR(
10848 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
10849 return;
10853 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
10854 glTexStorage2DEXT(target, levels, internal_format, width, height);
10855 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
10856 if (error == GL_NO_ERROR) {
10857 GLsizei level_width = width;
10858 GLsizei level_height = height;
10859 for (int ii = 0; ii < levels; ++ii) {
10860 texture_manager()->SetLevelInfo(
10861 texture_ref, target, ii, format,
10862 level_width, level_height, 1, 0, format, type, false);
10863 level_width = std::max(1, level_width >> 1);
10864 level_height = std::max(1, level_height >> 1);
10866 texture->SetImmutable(true);
10870 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
10871 uint32 immediate_data_size,
10872 const void* cmd_data) {
10873 return error::kUnknownCommand;
10876 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
10877 const GLbyte* data) {
10878 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
10879 "context", logger_.GetLogPrefix(),
10880 "mailbox[0]", static_cast<unsigned char>(data[0]));
10882 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10883 &state_, target);
10884 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
10887 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
10888 GLenum target, const GLbyte* data) {
10889 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
10890 "context", logger_.GetLogPrefix(),
10891 "mailbox[0]", static_cast<unsigned char>(data[0]));
10893 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
10894 target, data);
10897 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
10898 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
10899 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10900 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
10901 "mailbox that was not generated by "
10902 "GenMailboxCHROMIUM.";
10904 if (!texture_ref) {
10905 LOCAL_SET_GL_ERROR(
10906 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
10907 return;
10910 Texture* produced = texture_manager()->Produce(texture_ref);
10911 if (!produced) {
10912 LOCAL_SET_GL_ERROR(
10913 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
10914 return;
10917 if (produced->target() != target) {
10918 LOCAL_SET_GL_ERROR(
10919 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
10920 return;
10923 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
10926 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
10927 const GLbyte* data) {
10928 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
10929 "context", logger_.GetLogPrefix(),
10930 "mailbox[0]", static_cast<unsigned char>(data[0]));
10931 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
10932 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
10933 "mailbox that was not generated by "
10934 "GenMailboxCHROMIUM.";
10936 scoped_refptr<TextureRef> texture_ref =
10937 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
10938 if (!texture_ref.get()) {
10939 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10940 "glConsumeTextureCHROMIUM",
10941 "unknown texture for target");
10942 return;
10944 GLuint client_id = texture_ref->client_id();
10945 if (!client_id) {
10946 LOCAL_SET_GL_ERROR(
10947 GL_INVALID_OPERATION,
10948 "glConsumeTextureCHROMIUM", "unknown texture for target");
10949 return;
10951 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
10952 if (!texture) {
10953 LOCAL_SET_GL_ERROR(
10954 GL_INVALID_OPERATION,
10955 "glConsumeTextureCHROMIUM", "invalid mailbox name");
10956 return;
10958 if (texture->target() != target) {
10959 LOCAL_SET_GL_ERROR(
10960 GL_INVALID_OPERATION,
10961 "glConsumeTextureCHROMIUM", "invalid target");
10962 return;
10965 DeleteTexturesHelper(1, &client_id);
10966 texture_ref = texture_manager()->Consume(client_id, texture);
10967 glBindTexture(target, texture_ref->service_id());
10969 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10970 unit.bind_target = target;
10971 switch (target) {
10972 case GL_TEXTURE_2D:
10973 unit.bound_texture_2d = texture_ref;
10974 break;
10975 case GL_TEXTURE_CUBE_MAP:
10976 unit.bound_texture_cube_map = texture_ref;
10977 break;
10978 case GL_TEXTURE_EXTERNAL_OES:
10979 unit.bound_texture_external_oes = texture_ref;
10980 break;
10981 case GL_TEXTURE_RECTANGLE_ARB:
10982 unit.bound_texture_rectangle_arb = texture_ref;
10983 break;
10984 default:
10985 NOTREACHED(); // Validation should prevent us getting here.
10986 break;
10990 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
10991 uint32_t immediate_data_size,
10992 const void* cmd_data) {
10993 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
10994 *static_cast<
10995 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
10996 cmd_data);
10997 GLenum target = static_cast<GLenum>(c.target);
10998 uint32_t data_size;
10999 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
11000 return error::kOutOfBounds;
11002 if (data_size > immediate_data_size) {
11003 return error::kOutOfBounds;
11005 const GLbyte* mailbox =
11006 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
11007 if (!validators_->texture_bind_target.IsValid(target)) {
11008 LOCAL_SET_GL_ERROR_INVALID_ENUM(
11009 "glCreateAndConsumeTextureCHROMIUM", target, "target");
11010 return error::kNoError;
11012 if (mailbox == NULL) {
11013 return error::kOutOfBounds;
11015 uint32_t client_id = c.client_id;
11016 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
11017 return error::kNoError;
11020 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
11021 const GLbyte* data, GLuint client_id) {
11022 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
11023 "context", logger_.GetLogPrefix(),
11024 "mailbox[0]", static_cast<unsigned char>(data[0]));
11025 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
11026 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
11027 "passed a mailbox that was not "
11028 "generated by GenMailboxCHROMIUM.";
11030 TextureRef* texture_ref = GetTexture(client_id);
11031 if (texture_ref) {
11032 LOCAL_SET_GL_ERROR(
11033 GL_INVALID_OPERATION,
11034 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
11035 return;
11037 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
11038 if (!texture) {
11039 LOCAL_SET_GL_ERROR(
11040 GL_INVALID_OPERATION,
11041 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
11042 return;
11044 if (texture->target() != target) {
11045 LOCAL_SET_GL_ERROR(
11046 GL_INVALID_OPERATION,
11047 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
11048 return;
11051 texture_ref = texture_manager()->Consume(client_id, texture);
11054 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
11055 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
11056 return valuebuffer && valuebuffer->IsValid();
11059 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
11060 GLuint client_id) {
11061 Valuebuffer* valuebuffer = NULL;
11062 if (client_id != 0) {
11063 valuebuffer = GetValuebuffer(client_id);
11064 if (!valuebuffer) {
11065 if (!group_->bind_generates_resource()) {
11066 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
11067 "id not generated by glBindValuebufferCHROMIUM");
11068 return;
11071 // It's a new id so make a valuebuffer for it.
11072 CreateValuebuffer(client_id);
11073 valuebuffer = GetValuebuffer(client_id);
11075 valuebuffer->MarkAsValid();
11077 state_.bound_valuebuffer = valuebuffer;
11080 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
11081 GLenum subscription) {
11082 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
11083 return;
11085 state_.bound_valuebuffer.get()->AddSubscription(subscription);
11088 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
11089 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
11090 return;
11092 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
11095 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
11096 GLenum target,
11097 GLenum subscription) {
11098 if (!CheckCurrentValuebufferForSubscription(
11099 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
11100 return;
11102 if (!CheckSubscriptionTarget(location, subscription,
11103 "glPopulateSubscribedValuesCHROMIUM")) {
11104 return;
11106 const ValueState* state =
11107 state_.bound_valuebuffer.get()->GetState(subscription);
11108 if (state) {
11109 switch (subscription) {
11110 case GL_MOUSE_POSITION_CHROMIUM:
11111 DoUniform2iv(location, 1, state->int_value);
11112 break;
11113 default:
11114 NOTREACHED() << "Unhandled uniform subscription target "
11115 << subscription;
11116 break;
11121 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
11122 GLsizei length, const GLchar* marker) {
11123 if (!marker) {
11124 marker = "";
11126 debug_marker_manager_.SetMarker(
11127 length ? std::string(marker, length) : std::string(marker));
11130 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
11131 GLsizei length, const GLchar* marker) {
11132 if (!marker) {
11133 marker = "";
11135 std::string name = length ? std::string(marker, length) : std::string(marker);
11136 debug_marker_manager_.PushGroup(name);
11137 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_group_marker"), name,
11138 kTraceGroupMarker);
11141 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
11142 debug_marker_manager_.PopGroup();
11143 gpu_tracer_->End(kTraceGroupMarker);
11146 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
11147 GLenum target, GLint image_id) {
11148 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
11150 if (target == GL_TEXTURE_CUBE_MAP) {
11151 LOCAL_SET_GL_ERROR(
11152 GL_INVALID_ENUM,
11153 "glBindTexImage2DCHROMIUM", "invalid target");
11154 return;
11157 // Default target might be conceptually valid, but disallow it to avoid
11158 // accidents.
11159 TextureRef* texture_ref =
11160 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11161 if (!texture_ref) {
11162 LOCAL_SET_GL_ERROR(
11163 GL_INVALID_OPERATION,
11164 "glBindTexImage2DCHROMIUM", "no texture bound");
11165 return;
11168 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
11169 if (!gl_image) {
11170 LOCAL_SET_GL_ERROR(
11171 GL_INVALID_OPERATION,
11172 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
11173 return;
11177 ScopedGLErrorSuppressor suppressor(
11178 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
11179 if (!gl_image->BindTexImage(target)) {
11180 LOCAL_SET_GL_ERROR(
11181 GL_INVALID_OPERATION,
11182 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
11183 return;
11187 gfx::Size size = gl_image->GetSize();
11188 texture_manager()->SetLevelInfo(
11189 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
11190 GL_RGBA, GL_UNSIGNED_BYTE, true);
11191 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
11194 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
11195 GLenum target, GLint image_id) {
11196 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
11198 // Default target might be conceptually valid, but disallow it to avoid
11199 // accidents.
11200 TextureRef* texture_ref =
11201 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
11202 if (!texture_ref) {
11203 LOCAL_SET_GL_ERROR(
11204 GL_INVALID_OPERATION,
11205 "glReleaseTexImage2DCHROMIUM", "no texture bound");
11206 return;
11209 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
11210 if (!gl_image) {
11211 LOCAL_SET_GL_ERROR(
11212 GL_INVALID_OPERATION,
11213 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
11214 return;
11217 // Do nothing when image is not currently bound.
11218 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
11219 return;
11222 ScopedGLErrorSuppressor suppressor(
11223 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
11224 gl_image->ReleaseTexImage(target);
11227 texture_manager()->SetLevelInfo(
11228 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
11229 GL_RGBA, GL_UNSIGNED_BYTE, false);
11232 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
11233 uint32 immediate_data_size,
11234 const void* cmd_data) {
11235 const gles2::cmds::TraceBeginCHROMIUM& c =
11236 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
11237 Bucket* category_bucket = GetBucket(c.category_bucket_id);
11238 Bucket* name_bucket = GetBucket(c.name_bucket_id);
11239 if (!category_bucket || category_bucket->size() == 0 ||
11240 !name_bucket || name_bucket->size() == 0) {
11241 return error::kInvalidArguments;
11244 std::string category_name;
11245 std::string trace_name;
11246 if (!category_bucket->GetAsString(&category_name) ||
11247 !name_bucket->GetAsString(&trace_name)) {
11248 return error::kInvalidArguments;
11251 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
11252 LOCAL_SET_GL_ERROR(
11253 GL_INVALID_OPERATION,
11254 "glTraceBeginCHROMIUM", "unable to create begin trace");
11255 return error::kNoError;
11257 return error::kNoError;
11260 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
11261 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
11262 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11263 "glTraceEndCHROMIUM", "no trace begin found");
11264 return;
11268 void GLES2DecoderImpl::DoDrawBuffersEXT(
11269 GLsizei count, const GLenum* bufs) {
11270 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
11271 LOCAL_SET_GL_ERROR(
11272 GL_INVALID_VALUE,
11273 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
11274 return;
11277 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
11278 if (framebuffer) {
11279 for (GLsizei i = 0; i < count; ++i) {
11280 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
11281 bufs[i] != GL_NONE) {
11282 LOCAL_SET_GL_ERROR(
11283 GL_INVALID_OPERATION,
11284 "glDrawBuffersEXT",
11285 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
11286 return;
11289 glDrawBuffersARB(count, bufs);
11290 framebuffer->SetDrawBuffers(count, bufs);
11291 } else { // backbuffer
11292 if (count > 1 ||
11293 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
11294 LOCAL_SET_GL_ERROR(
11295 GL_INVALID_OPERATION,
11296 "glDrawBuffersEXT",
11297 "more than one buffer or bufs not GL_NONE or GL_BACK");
11298 return;
11300 GLenum mapped_buf = bufs[0];
11301 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
11302 bufs[0] == GL_BACK) {
11303 mapped_buf = GL_COLOR_ATTACHMENT0;
11305 glDrawBuffersARB(count, &mapped_buf);
11306 group_->set_draw_buffer(bufs[0]);
11310 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
11311 group_->LoseContexts(other);
11312 reset_status_ = current;
11313 current_decoder_error_ = error::kLostContext;
11316 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
11317 const GLfloat* matrix) {
11318 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
11319 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
11320 if (!features().chromium_path_rendering) {
11321 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11322 "glMatrixLoadfCHROMIUM",
11323 "function not available");
11324 return;
11327 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
11328 ? state_.projection_matrix
11329 : state_.modelview_matrix;
11330 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
11331 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
11332 // since the values of the _NV and _CHROMIUM tokens match.
11333 glMatrixLoadfEXT(matrix_mode, matrix);
11336 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
11337 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
11338 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
11340 if (!features().chromium_path_rendering) {
11341 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11342 "glMatrixLoadIdentityCHROMIUM",
11343 "function not available");
11344 return;
11347 static GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
11348 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
11349 0.0f, 0.0f, 0.0f, 1.0f};
11351 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
11352 ? state_.projection_matrix
11353 : state_.modelview_matrix;
11354 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
11355 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
11356 // since the values of the _NV and _CHROMIUM tokens match.
11357 glMatrixLoadIdentityEXT(matrix_mode);
11360 bool GLES2DecoderImpl::ValidateAsyncTransfer(
11361 const char* function_name,
11362 TextureRef* texture_ref,
11363 GLenum target,
11364 GLint level,
11365 const void * data) {
11366 // We only support async uploads to 2D textures for now.
11367 if (GL_TEXTURE_2D != target) {
11368 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
11369 return false;
11371 // We only support uploads to level zero for now.
11372 if (level != 0) {
11373 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
11374 return false;
11376 // A transfer buffer must be bound, even for asyncTexImage2D.
11377 if (data == NULL) {
11378 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
11379 return false;
11381 // We only support one async transfer in progress.
11382 if (!texture_ref ||
11383 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
11384 LOCAL_SET_GL_ERROR(
11385 GL_INVALID_OPERATION,
11386 function_name, "transfer already in progress");
11387 return false;
11389 return true;
11392 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
11393 uint32 async_upload_token,
11394 uint32 sync_data_shm_id,
11395 uint32 sync_data_shm_offset) {
11396 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
11397 if (!buffer.get() ||
11398 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
11399 return base::Closure();
11401 AsyncMemoryParams mem_params(buffer,
11402 sync_data_shm_offset,
11403 sizeof(AsyncUploadSync));
11405 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
11406 new AsyncUploadTokenCompletionObserver(async_upload_token));
11408 return base::Bind(
11409 &AsyncPixelTransferManager::AsyncNotifyCompletion,
11410 base::Unretained(GetAsyncPixelTransferManager()),
11411 mem_params,
11412 observer);
11415 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
11416 uint32 immediate_data_size,
11417 const void* cmd_data) {
11418 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
11419 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
11420 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
11421 GLenum target = static_cast<GLenum>(c.target);
11422 GLint level = static_cast<GLint>(c.level);
11423 GLenum internal_format = static_cast<GLenum>(c.internalformat);
11424 GLsizei width = static_cast<GLsizei>(c.width);
11425 GLsizei height = static_cast<GLsizei>(c.height);
11426 GLint border = static_cast<GLint>(c.border);
11427 GLenum format = static_cast<GLenum>(c.format);
11428 GLenum type = static_cast<GLenum>(c.type);
11429 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
11430 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
11431 uint32 pixels_size;
11432 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
11433 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
11434 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11436 base::ScopedClosureRunner scoped_completion_callback;
11437 if (async_upload_token) {
11438 base::Closure completion_closure =
11439 AsyncUploadTokenCompletionClosure(async_upload_token,
11440 sync_data_shm_id,
11441 sync_data_shm_offset);
11442 if (completion_closure.is_null())
11443 return error::kInvalidArguments;
11445 scoped_completion_callback.Reset(completion_closure);
11448 // TODO(epenner): Move this and copies of this memory validation
11449 // into ValidateTexImage2D step.
11450 if (!GLES2Util::ComputeImageDataSizes(
11451 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
11452 NULL, NULL)) {
11453 return error::kOutOfBounds;
11455 const void* pixels = NULL;
11456 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
11457 pixels = GetSharedMemoryAs<const void*>(
11458 pixels_shm_id, pixels_shm_offset, pixels_size);
11459 if (!pixels) {
11460 return error::kOutOfBounds;
11464 TextureManager::DoTextImage2DArguments args = {
11465 target, level, internal_format, width, height, border, format, type,
11466 pixels, pixels_size};
11467 TextureRef* texture_ref;
11468 // All the normal glTexSubImage2D validation.
11469 if (!texture_manager()->ValidateTexImage2D(
11470 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
11471 return error::kNoError;
11474 // Extra async validation.
11475 Texture* texture = texture_ref->texture();
11476 if (!ValidateAsyncTransfer(
11477 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
11478 return error::kNoError;
11480 // Don't allow async redefinition of a textures.
11481 if (texture->IsDefined()) {
11482 LOCAL_SET_GL_ERROR(
11483 GL_INVALID_OPERATION,
11484 "glAsyncTexImage2DCHROMIUM", "already defined");
11485 return error::kNoError;
11488 if (!EnsureGPUMemoryAvailable(pixels_size)) {
11489 LOCAL_SET_GL_ERROR(
11490 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
11491 return error::kNoError;
11494 // Setup the parameters.
11495 AsyncTexImage2DParams tex_params = {
11496 target, level, static_cast<GLenum>(internal_format),
11497 width, height, border, format, type};
11498 AsyncMemoryParams mem_params(
11499 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
11501 // Set up the async state if needed, and make the texture
11502 // immutable so the async state stays valid. The level info
11503 // is set up lazily when the transfer completes.
11504 AsyncPixelTransferDelegate* delegate =
11505 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
11506 tex_params);
11507 texture->SetImmutable(true);
11509 delegate->AsyncTexImage2D(
11510 tex_params,
11511 mem_params,
11512 base::Bind(&TextureManager::SetLevelInfoFromParams,
11513 // The callback is only invoked if the transfer delegate still
11514 // exists, which implies through manager->texture_ref->state
11515 // ownership that both of these pointers are valid.
11516 base::Unretained(texture_manager()),
11517 base::Unretained(texture_ref),
11518 tex_params));
11519 return error::kNoError;
11522 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
11523 uint32 immediate_data_size,
11524 const void* cmd_data) {
11525 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
11526 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
11527 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
11528 GLenum target = static_cast<GLenum>(c.target);
11529 GLint level = static_cast<GLint>(c.level);
11530 GLint xoffset = static_cast<GLint>(c.xoffset);
11531 GLint yoffset = static_cast<GLint>(c.yoffset);
11532 GLsizei width = static_cast<GLsizei>(c.width);
11533 GLsizei height = static_cast<GLsizei>(c.height);
11534 GLenum format = static_cast<GLenum>(c.format);
11535 GLenum type = static_cast<GLenum>(c.type);
11536 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
11537 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
11538 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11540 base::ScopedClosureRunner scoped_completion_callback;
11541 if (async_upload_token) {
11542 base::Closure completion_closure =
11543 AsyncUploadTokenCompletionClosure(async_upload_token,
11544 sync_data_shm_id,
11545 sync_data_shm_offset);
11546 if (completion_closure.is_null())
11547 return error::kInvalidArguments;
11549 scoped_completion_callback.Reset(completion_closure);
11552 // TODO(epenner): Move this and copies of this memory validation
11553 // into ValidateTexSubImage2D step.
11554 uint32 data_size;
11555 if (!GLES2Util::ComputeImageDataSizes(
11556 width, height, 1, format, type, state_.unpack_alignment, &data_size,
11557 NULL, NULL)) {
11558 return error::kOutOfBounds;
11560 const void* pixels = GetSharedMemoryAs<const void*>(
11561 c.data_shm_id, c.data_shm_offset, data_size);
11563 // All the normal glTexSubImage2D validation.
11564 error::Error error = error::kNoError;
11565 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
11566 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
11567 return error;
11570 // Extra async validation.
11571 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11572 &state_, target);
11573 Texture* texture = texture_ref->texture();
11574 if (!ValidateAsyncTransfer(
11575 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
11576 return error::kNoError;
11578 // Guarantee async textures are always 'cleared' as follows:
11579 // - AsyncTexImage2D can not redefine an existing texture
11580 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
11581 // - AsyncTexSubImage2D clears synchronously if not already cleared.
11582 // - Textures become immutable after an async call.
11583 // This way we know in all cases that an async texture is always clear.
11584 if (!texture->SafeToRenderFrom()) {
11585 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
11586 target, level)) {
11587 LOCAL_SET_GL_ERROR(
11588 GL_OUT_OF_MEMORY,
11589 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
11590 return error::kNoError;
11594 // Setup the parameters.
11595 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
11596 width, height, format, type};
11597 AsyncMemoryParams mem_params(
11598 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
11599 AsyncPixelTransferDelegate* delegate =
11600 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
11601 if (!delegate) {
11602 // TODO(epenner): We may want to enforce exclusive use
11603 // of async APIs in which case this should become an error,
11604 // (the texture should have been async defined).
11605 AsyncTexImage2DParams define_params = {target, level,
11606 0, 0, 0, 0, 0, 0};
11607 texture->GetLevelSize(target, level, &define_params.width,
11608 &define_params.height);
11609 texture->GetLevelType(target, level, &define_params.type,
11610 &define_params.internal_format);
11611 // Set up the async state if needed, and make the texture
11612 // immutable so the async state stays valid.
11613 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
11614 texture_ref, define_params);
11615 texture->SetImmutable(true);
11618 delegate->AsyncTexSubImage2D(tex_params, mem_params);
11619 return error::kNoError;
11622 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
11623 uint32 immediate_data_size,
11624 const void* cmd_data) {
11625 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
11626 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
11627 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11628 GLenum target = static_cast<GLenum>(c.target);
11630 if (GL_TEXTURE_2D != target) {
11631 LOCAL_SET_GL_ERROR(
11632 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
11633 return error::kNoError;
11635 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
11636 &state_, target);
11637 if (!texture_ref) {
11638 LOCAL_SET_GL_ERROR(
11639 GL_INVALID_OPERATION,
11640 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
11641 return error::kNoError;
11643 AsyncPixelTransferDelegate* delegate =
11644 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
11645 if (!delegate) {
11646 LOCAL_SET_GL_ERROR(
11647 GL_INVALID_OPERATION,
11648 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
11649 return error::kNoError;
11651 delegate->WaitForTransferCompletion();
11652 ProcessFinishedAsyncTransfers();
11653 return error::kNoError;
11656 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
11657 uint32 immediate_data_size,
11658 const void* data) {
11659 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
11661 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
11662 ProcessFinishedAsyncTransfers();
11663 return error::kNoError;
11666 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
11667 TextureRef* texture_ref) {
11668 Texture* texture = texture_ref->texture();
11669 DoDidUseTexImageIfNeeded(texture, texture->target());
11672 void GLES2DecoderImpl::OnContextLostError() {
11673 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
11676 void GLES2DecoderImpl::OnOutOfMemoryError() {
11677 if (lose_context_when_out_of_memory_) {
11678 group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB);
11682 // Include the auto-generated part of this file. We split this because it means
11683 // we can easily edit the non-auto generated parts right here in this file
11684 // instead of having to edit some template or the code generator.
11685 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
11687 } // namespace gles2
11688 } // namespace gpu