Index: gpu/command_buffer/service/texture_definition.cc |
diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..33a3d7b7ce3bc1716a3849ef09f5e7a4d2e4fa00 |
--- /dev/null |
+++ b/gpu/command_buffer/service/texture_definition.cc |
@@ -0,0 +1,290 @@ |
+// Copyright (c) 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "gpu/command_buffer/service/texture_definition.h" |
+ |
+#include "gpu/command_buffer/service/texture_manager.h" |
+#include "ui/gl/gl_fence.h" |
+#include "ui/gl/gl_image.h" |
+#include "ui/gl/gl_implementation.h" |
+#include "ui/gl/gl_surface_egl.h" |
+#include "ui/gl/scoped_binders.h" |
+ |
+namespace gpu { |
+namespace gles2 { |
+ |
+namespace { |
+ |
+class GLImageSync : public gfx::GLImage { |
+ public: |
+ explicit GLImageSync( |
+ const scoped_refptr<const NativeImageBuffer>& buffer, |
+ const scoped_refptr<const SharedGLFence>& fence); |
+ |
+ // Implement GLImage. |
+ virtual void Destroy() OVERRIDE; |
+ virtual gfx::Size GetSize() OVERRIDE; |
+ virtual bool BindTexImage(unsigned target) OVERRIDE; |
+ virtual void ReleaseTexImage(unsigned target) OVERRIDE; |
+ virtual void WillUseTexImage() OVERRIDE; |
+ virtual void DidUseTexImage() OVERRIDE; |
+ virtual void SetReleaseAfterUse() OVERRIDE; |
+ |
+ protected: |
+ virtual ~GLImageSync(); |
+ |
+ private: |
+ scoped_refptr<const NativeImageBuffer> buffer_; |
+ scoped_refptr<const SharedGLFence> fence_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(GLImageSync); |
+}; |
+ |
+GLImageSync::GLImageSync(const scoped_refptr<const NativeImageBuffer>& buffer, |
+ const scoped_refptr<const SharedGLFence>& fence) |
+ : buffer_(buffer), fence_(fence) {} |
+ |
+GLImageSync::~GLImageSync() {} |
+ |
+void GLImageSync::Destroy() {} |
+ |
+gfx::Size GLImageSync::GetSize() { |
+ NOTREACHED(); |
+ return gfx::Size(); |
+} |
+ |
+bool GLImageSync::BindTexImage(unsigned target) { |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+void GLImageSync::ReleaseTexImage(unsigned target) { |
+ NOTREACHED(); |
+} |
+ |
+void GLImageSync::WillUseTexImage() { |
+ if (fence_.get()) { |
+ fence_->GpuWaitSync(); |
+ fence_ = NULL; |
+ } |
+} |
+ |
+void GLImageSync::DidUseTexImage() {} |
+ |
+void GLImageSync::SetReleaseAfterUse() { |
+ NOTREACHED(); |
+} |
+ |
+class NativeImageBufferEGL : public NativeImageBuffer { |
+ public: |
+ static NativeImageBufferEGL* Create(GLuint texture_id); |
+ |
+ private: |
+ explicit NativeImageBufferEGL(EGLDisplay display, EGLImageKHR image); |
+ virtual ~NativeImageBufferEGL(); |
+ virtual void BindToTexture(GLenum target) OVERRIDE; |
+ |
+ EGLDisplay egl_display_; |
+ EGLImageKHR egl_image_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(NativeImageBufferEGL); |
+}; |
+ |
+NativeImageBufferEGL* NativeImageBufferEGL::Create(GLuint texture_id) { |
+ EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
+ EGLContext egl_context = eglGetCurrentContext(); |
+ |
+ if (egl_context == EGL_NO_CONTEXT || egl_display == EGL_NO_DISPLAY || |
+ !glIsTexture(texture_id)) { |
+ return NULL; |
+ } |
+ |
+ if (!gfx::g_driver_egl.ext.b_EGL_KHR_image_base || |
+ !gfx::g_driver_gl.ext.b_GL_OES_EGL_image) { |
+ return NULL; |
+ } |
+ |
+ const EGLint egl_attrib_list[] = { |
+ EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; |
+ EGLClientBuffer egl_buffer = reinterpret_cast<EGLClientBuffer>(texture_id); |
+ EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; // TODO |
+ |
+ EGLImageKHR egl_image = eglCreateImageKHR( |
+ egl_display, egl_context, egl_target, egl_buffer, egl_attrib_list); |
+ |
+ if (egl_image == EGL_NO_IMAGE_KHR) |
+ return NULL; |
+ |
+ return new NativeImageBufferEGL(egl_display, egl_image); |
+} |
+ |
+NativeImageBufferEGL::NativeImageBufferEGL(EGLDisplay display, |
+ EGLImageKHR image) |
+ : egl_display_(display), egl_image_(image) { |
+ DCHECK(egl_display_ != EGL_NO_DISPLAY); |
+ DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); |
+} |
+ |
+NativeImageBufferEGL::~NativeImageBufferEGL() { |
+ if (egl_image_ != EGL_NO_IMAGE_KHR) |
+ eglDestroyImageKHR(egl_display_, egl_image_); |
+} |
+ |
+void NativeImageBufferEGL::BindToTexture(GLenum target) { |
+ DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); |
+ glEGLImageTargetTexture2DOES(target, egl_image_); |
+ DCHECK_EQ(EGL_SUCCESS, (EGLint)eglGetError()); |
+ DCHECK_EQ(GL_NO_ERROR, (GLint)glGetError()); |
+} |
+ |
+} // anonymous namespace |
+ |
+// static |
+NativeImageBuffer* NativeImageBuffer::Create(GLuint texture_id) { |
+ switch (gfx::GetGLImplementation()) { |
+ case gfx::kGLImplementationEGLGLES2: |
+ return NativeImageBufferEGL::Create(texture_id); |
+ case gfx::kGLImplementationMockGL: |
+ default: |
+ NOTREACHED(); |
+ return NULL; |
+ } |
+} |
+ |
+SharedGLFence::SharedGLFence() : fence_(gfx::GLFence::Create()) {} |
+ |
+SharedGLFence::~SharedGLFence() {} |
+ |
+void SharedGLFence::GpuWaitSync() const { |
+ fence_->ServerWait(); |
+} |
+ |
+TextureDefinition::LevelInfo::LevelInfo(GLenum target, |
+ GLenum internal_format, |
+ GLsizei width, |
+ GLsizei height, |
+ GLsizei depth, |
+ GLint border, |
+ GLenum format, |
+ GLenum type, |
+ bool cleared) |
+ : target(target), |
+ internal_format(internal_format), |
+ width(width), |
+ height(height), |
+ depth(depth), |
+ border(border), |
+ format(format), |
+ type(type), |
+ cleared(cleared) {} |
+ |
+TextureDefinition::LevelInfo::~LevelInfo() {} |
+ |
+TextureDefinition::TextureDefinition(GLenum target, |
+ Texture* texture, |
+ NativeImageBuffer* image, |
+ const scoped_refptr<SharedGLFence>& fence) |
+ : target_(target), |
+ image_(image ? image : NativeImageBuffer::Create(texture->service_id())), |
+ fence_(fence), |
+ min_filter_(texture->min_filter()), |
+ mag_filter_(texture->mag_filter()), |
+ wrap_s_(texture->wrap_s()), |
+ wrap_t_(texture->wrap_t()), |
+ usage_(texture->usage()), |
+ immutable_(texture->IsImmutable()) { |
+ |
+ // TODO |
+ DCHECK(!texture->level_infos_.empty()); |
+ DCHECK(!texture->level_infos_[0].empty()); |
+ DCHECK(!texture->NeedsMips()); |
+ DCHECK(texture->level_infos_[0][0].width); |
+ DCHECK(texture->level_infos_[0][0].height); |
+ |
+ // TODO: If the texture is not complete, we should defer creating the image |
+ // until the next sync after it becomes complete. |
+ scoped_refptr<gfx::GLImage> gl_image(new GLImageSync(image, fence)); |
+ texture->SetLevelImage(NULL, target, 0, gl_image); |
+ |
+ // TODO: all levels |
+ level_infos_.clear(); |
+ const Texture::LevelInfo& level = texture->level_infos_[0][0]; |
+ LevelInfo info(level.target, |
+ level.internal_format, |
+ level.width, |
+ level.height, |
+ level.depth, |
+ level.border, |
+ level.format, |
+ level.type, |
+ level.cleared); |
+ std::vector<LevelInfo> infos; |
+ infos.push_back(info); |
+ level_infos_.push_back(infos); |
+ |
+} |
+ |
+TextureDefinition::~TextureDefinition() { |
+} |
+ |
+Texture* TextureDefinition::CreateTexture() const { |
+ if (!image_) |
+ return NULL; |
+ |
+ GLuint texture_id; |
+ glGenTextures(1, &texture_id); |
+ |
+ Texture* texture(new Texture(texture_id)); |
+ UpdateTexture(texture); |
+ |
+ return texture; |
+} |
+ |
+void TextureDefinition::UpdateTexture(Texture* texture) const { |
+ gfx::ScopedTextureBinder texture_binder(target_, texture->service_id()); |
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_); |
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_); |
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_); |
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_); |
+ DCHECK(image_); |
+ if (image_) |
+ image_->BindToTexture(target_); |
+ glFlush(); |
+ |
+ texture->level_infos_.resize(1); |
+ for (size_t i = 0; i < level_infos_.size(); i++) { |
+ const LevelInfo& base_info = level_infos_[i][0]; |
+ const size_t levels_needed = TextureManager::ComputeMipMapCount( |
+ base_info.target, base_info.width, base_info.height, base_info.depth); |
+ DCHECK(level_infos_.size() <= levels_needed); |
+ texture->level_infos_[0].resize(levels_needed); |
+ for (size_t n = 0; n < level_infos_.size(); n++) { |
+ const LevelInfo& info = level_infos_[i][n]; |
+ texture->SetLevelInfo(NULL, |
+ info.target, |
+ i, |
+ info.internal_format, |
+ info.width, |
+ info.height, |
+ info.depth, |
+ info.border, |
+ info.format, |
+ info.type, |
+ info.cleared); |
+ } |
+ } |
+ if (image_) |
+ texture->SetLevelImage(NULL, target_, 0, new GLImageSync(image_, fence_)); |
+ |
+ texture->target_ = target_; |
+ texture->SetImmutable(immutable_); |
+ texture->min_filter_ = min_filter_; |
+ texture->mag_filter_ = mag_filter_; |
+ texture->wrap_s_ = wrap_s_; |
+ texture->wrap_t_ = wrap_t_; |
+ texture->usage_ = usage_; |
+} |
+ |
+} // namespace gles2 |
+} // namespace gpu |