OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gl/gl_image_egl.h" | 5 #include "ui/gl/gl_image_egl.h" |
6 | 6 |
7 #include "ui/gl/gl_bindings.h" | |
8 #include "ui/gl/gl_surface_egl.h" | 7 #include "ui/gl/gl_surface_egl.h" |
9 #include "ui/gl/scoped_binders.h" | |
10 | 8 |
11 namespace gfx { | 9 namespace gfx { |
12 | 10 |
13 GLImageEGL::GLImageEGL(gfx::Size size) | 11 GLImageEGL::GLImageEGL(gfx::Size size) |
14 : egl_image_(EGL_NO_IMAGE_KHR), | 12 : egl_image_(EGL_NO_IMAGE_KHR), size_(size) {} |
15 size_(size), | |
16 release_after_use_(false), | |
17 in_use_(false), | |
18 target_(0), | |
19 egl_image_for_unbind_(EGL_NO_IMAGE_KHR), | |
20 texture_id_for_unbind_(0) {} | |
21 | 13 |
22 GLImageEGL::~GLImageEGL() { Destroy(); } | 14 GLImageEGL::~GLImageEGL() { Destroy(); } |
23 | 15 |
24 bool GLImageEGL::Initialize(gfx::GpuMemoryBufferHandle buffer) { | 16 bool GLImageEGL::Initialize(EGLenum target, |
25 DCHECK(buffer.native_buffer); | 17 EGLClientBuffer buffer, |
26 | 18 const EGLint* attrs) { |
27 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; | 19 DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_); |
28 egl_image_ = eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), | 20 egl_image_ = eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), |
29 EGL_NO_CONTEXT, | 21 EGL_NO_CONTEXT, |
30 EGL_NATIVE_BUFFER_ANDROID, | 22 target, |
31 buffer.native_buffer, | 23 buffer, |
32 attrs); | 24 attrs); |
33 if (egl_image_ == EGL_NO_IMAGE_KHR) { | 25 if (egl_image_ == EGL_NO_IMAGE_KHR) { |
34 EGLint error = eglGetError(); | 26 EGLint error = eglGetError(); |
35 LOG(ERROR) << "Error creating EGLImage: " << error; | 27 LOG(ERROR) << "Error creating EGLImage: " << error; |
36 return false; | 28 return false; |
37 } | 29 } |
38 | 30 |
39 return true; | 31 return true; |
40 } | 32 } |
41 | 33 |
42 void GLImageEGL::Destroy() { | 34 void GLImageEGL::Destroy() { |
43 if (egl_image_ != EGL_NO_IMAGE_KHR) { | 35 if (egl_image_ != EGL_NO_IMAGE_KHR) { |
44 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_); | 36 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_); |
45 egl_image_ = EGL_NO_IMAGE_KHR; | 37 egl_image_ = EGL_NO_IMAGE_KHR; |
46 } | 38 } |
47 | |
48 if (egl_image_for_unbind_ != EGL_NO_IMAGE_KHR) { | |
49 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), | |
50 egl_image_for_unbind_); | |
51 egl_image_for_unbind_ = EGL_NO_IMAGE_KHR; | |
52 } | |
53 | |
54 if (texture_id_for_unbind_) { | |
55 glDeleteTextures(1, &texture_id_for_unbind_); | |
56 texture_id_for_unbind_ = 0; | |
57 } | |
58 } | 39 } |
59 | 40 |
60 gfx::Size GLImageEGL::GetSize() { return size_; } | 41 gfx::Size GLImageEGL::GetSize() { return size_; } |
61 | 42 |
62 bool GLImageEGL::BindTexImage(unsigned target) { | 43 bool GLImageEGL::BindTexImage(unsigned target) { |
63 if (egl_image_ == EGL_NO_IMAGE_KHR) { | 44 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); |
64 LOG(ERROR) << "NULL EGLImage in BindTexImage"; | 45 glEGLImageTargetTexture2DOES(target, egl_image_); |
65 return false; | |
66 } | |
67 | |
68 if (target == GL_TEXTURE_RECTANGLE_ARB) { | |
69 LOG(ERROR) << "EGLImage cannot be bound to TEXTURE_RECTANGLE_ARB target"; | |
70 return false; | |
71 } | |
72 | |
73 if (target_ && target_ != target) { | |
74 LOG(ERROR) << "EGLImage can only be bound to one target"; | |
75 return false; | |
76 } | |
77 target_ = target; | |
78 | |
79 // Defer ImageTargetTexture2D if not currently in use. | |
80 if (!in_use_) | |
81 return true; | |
82 | |
83 glEGLImageTargetTexture2DOES(target_, egl_image_); | |
84 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | 46 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
85 return true; | 47 return true; |
86 } | 48 } |
87 | 49 |
88 void GLImageEGL::ReleaseTexImage(unsigned target) { | |
89 // Nothing to do here as image is released after each use or there is no need | |
90 // to release image. | |
91 } | |
92 | |
93 void GLImageEGL::WillUseTexImage() { | |
94 DCHECK(egl_image_); | |
95 DCHECK(!in_use_); | |
96 in_use_ = true; | |
97 glEGLImageTargetTexture2DOES(target_, egl_image_); | |
98 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
99 } | |
100 | |
101 void GLImageEGL::DidUseTexImage() { | |
102 DCHECK(in_use_); | |
103 in_use_ = false; | |
104 | |
105 if (!release_after_use_) | |
106 return; | |
107 | |
108 if (egl_image_for_unbind_ == EGL_NO_IMAGE_KHR) { | |
109 DCHECK_EQ(0u, texture_id_for_unbind_); | |
110 glGenTextures(1, &texture_id_for_unbind_); | |
111 | |
112 { | |
113 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_for_unbind_); | |
114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
117 | |
118 char zero[4] = {0, }; | |
119 glTexImage2D( | |
120 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &zero); | |
121 } | |
122 | |
123 EGLint attrs[] = {EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_IMAGE_PRESERVED_KHR, | |
124 EGL_TRUE, EGL_NONE}; | |
125 // Need to pass current EGL rendering context to eglCreateImageKHR for | |
126 // target type EGL_GL_TEXTURE_2D_KHR. | |
127 egl_image_for_unbind_ = eglCreateImageKHR( | |
128 GLSurfaceEGL::GetHardwareDisplay(), | |
129 eglGetCurrentContext(), | |
130 EGL_GL_TEXTURE_2D_KHR, | |
131 reinterpret_cast<EGLClientBuffer>(texture_id_for_unbind_), | |
132 attrs); | |
133 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_for_unbind_) | |
134 << "Error creating EGLImage: " << eglGetError(); | |
135 } | |
136 | |
137 glEGLImageTargetTexture2DOES(target_, egl_image_for_unbind_); | |
138 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
139 } | |
140 | |
141 void GLImageEGL::SetReleaseAfterUse() { release_after_use_ = true; } | |
142 | |
143 } // namespace gfx | 50 } // namespace gfx |
OLD | NEW |