Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(677)

Side by Side Diff: ui/gl/async_pixel_transfer_delegate_android.cc

Issue 11428140: gpu: Add async pixel transfer interface, stub and tests. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "ui/gl/async_pixel_transfer_delegate_android.h"
6
7 #include "base/bind.h"
8 #include "base/cancelable_callback.h"
9 #include "base/debug/trace_event.h"
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/threading/thread.h"
14 #include "build/build_config.h"
15 #include "third_party/angle/include/EGL/egl.h"
16 #include "third_party/angle/include/EGL/eglext.h"
17 #include "ui/gfx/point.h"
18 #include "ui/gfx/size.h"
19 #include "ui/gl/async_pixel_transfer_delegate.h"
20 #include "ui/gl/egl_util.h"
21 #include "ui/gl/gl_bindings.h"
22 #include "ui/gl/gl_context.h"
23 #include "ui/gl/gl_surface_egl.h"
24
25 namespace gfx {
26
27
apatrick 2012/12/03 21:23:59 nit: delete blank line.
epennerAtGoogle 2012/12/04 19:56:48 Done.
28 bool check_errors(const char* file, int line) {
apatrick 2012/12/03 21:23:59 nit: CheckErrors
epennerAtGoogle 2012/12/04 19:56:48 Done.
29 EGLint eglerror;
30 GLenum glerror;
31 bool success = true;
32 while ((eglerror = eglGetError()) != EGL_SUCCESS) {
33 LOG(ERROR) << "ESP eglerror " << file << ":" << line << " " << eglerror;
34 success = false;
35 }
36 while ((glerror = glGetError()) != GL_NO_ERROR) {
37 LOG(ERROR) << "ESP openglerror " << file << ":" << line << " " << glerror;
38 success = false;
39 }
40 return success;
41 }
42 #define CHK() check_errors(__FILE__, __LINE__)
43
44
45 class AsyncTransferStateAndroid : public AsyncPixelTransferState {
46 public:
47 AsyncTransferStateAndroid(GLuint texture_id)
48 : texture_id_(texture_id)
49 , egl_image_(0) {}
apatrick 2012/12/03 21:23:59 nit: comma to line above.
epennerAtGoogle 2012/12/04 19:56:48 Done.
50 virtual ~AsyncTransferStateAndroid() {
51 if (egl_image_) {
52 EGLDisplay display = eglGetCurrentDisplay();
53 eglDestroyImageKHR(display, egl_image_);
54 }
55 }
56 void no_op() {}
apatrick 2012/12/03 21:23:59 I think you sent with the free function in the ano
epennerAtGoogle 2012/12/03 22:48:45 I use this one too, solely such that a reply holds
greggman 2012/12/05 02:23:42 nit: functions are CamelCase
epenner 2012/12/08 03:15:03 Done.
57 GLuint texture_id_;
58 EGLImageKHR egl_image_;
59 };
60
61
62 // Class which handles async pixel transfers on Android (using
63 // EGLImageKHR and another upload thread)
64 class AsyncPixelTransferDelegateAndroid : public AsyncPixelTransferDelegate {
65 public:
66 AsyncPixelTransferDelegateAndroid();
67 virtual ~AsyncPixelTransferDelegateAndroid();
68
69 // implement AsyncPixelTransferDelegate:
70 virtual scoped_refptr<AsyncPixelTransferState>
71 CreatePixelTransferState(GLuint);
72 virtual void AsyncNotifyCompletion(
73 const base::Closure& task);
74 virtual void AsyncTexSubImage2D(
75 AsyncPixelTransferState*,
76 GLenum target,
77 GLint level,
78 GLint xoffset,
79 GLint yoffset,
80 GLsizei width,
81 GLsizei height,
82 GLenum format,
83 GLenum type,
84 const void* data);
85
86 private:
87 void Initialize();
88 void Shutdown();
89 void PerformInitialize();
90 void PerformShutdown();
91
92 void PerformAsyncTexSubImage2D(
93 EGLImageKHR egl_image,
94 gfx::Point offset,
95 gfx::Size size,
96 GLenum format,
97 GLenum type,
98 const void * data);
99
100 scoped_ptr<base::Thread> thread_;
101 scoped_refptr<gfx::GLContext> thread_context_;
102 scoped_refptr<gfx::GLSurface> thread_surface_;
103
104 DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateAndroid);
105 };
106
107 // Lazy instance creation.
108 base::LazyInstance<AsyncPixelTransferDelegateAndroid>
109 g_async_pixel_transfer_delegate_ = LAZY_INSTANCE_INITIALIZER;
110
111 AsyncPixelTransferDelegate* AsyncPixelTransferDelegate::Get() {
112 return g_async_pixel_transfer_delegate_.Pointer();
113 }
114
115 scoped_refptr<AsyncPixelTransferState>
116 AsyncPixelTransferDelegateAndroid::
117 CreatePixelTransferState(GLuint texture_id) {
118 return make_scoped_refptr((AsyncPixelTransferState*)
apatrick 2012/12/03 21:23:59 nit: no c-style casts.
epennerAtGoogle 2012/12/04 19:56:48 Done.
119 new AsyncTransferStateAndroid(texture_id));
120 }
121
122 AsyncPixelTransferDelegateAndroid::AsyncPixelTransferDelegateAndroid()
123 : thread_(new base::Thread("GPUAsyncTransferThread"))
124 {
greggman 2012/12/05 02:23:42 nit: { wants to be on previous line
epenner 2012/12/08 03:15:03 Done.
125 Initialize();
126 }
127
128 AsyncPixelTransferDelegateAndroid::~AsyncPixelTransferDelegateAndroid()
129 {
greggman 2012/12/05 02:23:42 nit: { wants to be on previous line
epenner 2012/12/08 03:15:03 Done.
130 Shutdown();
131 }
132
133 void AsyncPixelTransferDelegateAndroid::Initialize() {
134 // Start the thread and initialize on the thread.
135 thread_->Start();
136 thread_->message_loop()->PostTask(FROM_HERE, base::Bind(
137 &AsyncPixelTransferDelegateAndroid::PerformInitialize,
138 base::Unretained(this)));
139 }
140
141 void AsyncPixelTransferDelegateAndroid::Shutdown() {
142 // Shutdown and wait for the thread to finish.
143 thread_->message_loop()->PostTask(FROM_HERE, base::Bind(
144 &AsyncPixelTransferDelegateAndroid::PerformShutdown,
145 base::Unretained(this)));
146 thread_->Stop();
147 }
148
149 namespace {
150 void no_op() {}
apatrick 2012/12/03 21:23:59 nit: no indentation. NoOp.
epennerAtGoogle 2012/12/04 19:56:48 Done.
151 }
152
153 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion(
154 const base::Closure& task) {
155 // Post a no-op task to the upload thread followed
156 // by a reply to the callback. The reply will occur after
157 // all async transfers are complete.
158 thread_->message_loop_proxy()->PostTaskAndReply(FROM_HERE,
159 base::Bind(&no_op), task);
160 }
161
162
163 void AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2D(
164 AsyncPixelTransferState* transfer_state,
165 GLenum target,
166 GLint level,
167 GLint xoffset,
168 GLint yoffset,
169 GLsizei width,
170 GLsizei height,
171 GLenum format,
172 GLenum type,
173 const void* data) {
174 TRACE_EVENT2("gpu", "AsyncTexSubImage2D",
175 "width", width,
176 "height", height);
177 AsyncTransferStateAndroid* state =(AsyncTransferStateAndroid*)transfer_state;
apatrick 2012/12/03 21:23:59 nit: no c-style casts.
epennerAtGoogle 2012/12/04 19:56:48 Done.
178 DCHECK(state);
179 DCHECK(state->texture_id_);
180
181 // TODO: Implement other targets/levels if needed.
182 DCHECK(target == GL_TEXTURE_2D);
183 DCHECK(level == 0);
184
185 // Create the EGLImage if it hasn't already been created.
186 if (!state->egl_image_) {
187 EGLDisplay egl_display = eglGetCurrentDisplay();
188 EGLContext egl_context = eglGetCurrentContext();
189 EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR;
190 EGLClientBuffer egl_buffer = (EGLClientBuffer) state->texture_id_;
apatrick 2012/12/03 21:23:59 nit: c-style casts.
epennerAtGoogle 2012/12/04 19:56:48 Done.
191 EGLint egl_attrib_list[] = {
192 EGL_GL_TEXTURE_LEVEL_KHR, level, // mip-map level to reference.
193 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, // preserve the data in the texture.
194 EGL_NONE
195 };
196 state->egl_image_ = eglCreateImageKHR(
197 egl_display,
198 egl_context,
199 egl_target,
200 egl_buffer,
201 egl_attrib_list);
202 }
203
204 // Post the upload task. The reply is a no-op but keeps
205 // the texture state referenced, so the EGLImage is not destroyed
206 // before it is used on the upload thead.
207 thread_->message_loop_proxy()->PostTaskAndReply(FROM_HERE,
208 base::Bind(
209 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D,
210 base::Unretained(this),
211 state->egl_image_,
212 gfx::Point(xoffset, yoffset),
213 gfx::Size(width, height),
214 format, type, data),
215 base::Bind(
216 &AsyncTransferStateAndroid::no_op,
217 state));
218 CHK();
219 }
220
221
222 void AsyncPixelTransferDelegateAndroid::PerformInitialize() {
223 DCHECK(!thread_surface_);
224 DCHECK(!thread_context_);
225 GLShareGroup* share_group = NULL;
226 bool software = false;
227 thread_surface_ = new gfx::PbufferGLSurfaceEGL(software, gfx::Size(1,1));
apatrick 2012/12/03 21:23:59 Neither GLSurface or GLContext implementations are
epennerAtGoogle 2012/12/03 22:48:45 I see! I think since this is self-contained and p
epennerAtGoogle 2012/12/04 00:47:14 Actually after looking at this it appears some of
228 thread_surface_->Initialize();
229 thread_context_ = gfx::GLContext::CreateGLContext(share_group,
230 thread_surface_,
231 gfx::PreferDiscreteGpu);
232 bool is_current = thread_context_->MakeCurrent(thread_surface_);
apatrick 2012/12/03 21:23:59 This will modify the current context pointer, shar
epennerAtGoogle 2012/12/03 22:48:45 Very good to know, thanks!
233 DCHECK(thread_surface_);
234 DCHECK(thread_context_);
235 DCHECK(is_current);
236 }
237
238 void AsyncPixelTransferDelegateAndroid::PerformShutdown() {
239 DCHECK(thread_surface_);
240 DCHECK(thread_context_);
241 thread_surface_ = NULL;
242 thread_context_->ReleaseCurrent(thread_surface_);
243 thread_context_ = NULL;
244 }
245
246 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D(
247 EGLImageKHR egl_image,
248 gfx::Point offset,
249 gfx::Size size,
250 GLenum format,
251 GLenum type,
252 const void* data) {
253 // For a texSubImage, the texture must already have been
254 // created on the main thread, along with EGLImageKHR.
255 DCHECK(egl_image);
256 TRACE_EVENT2("gpu", "performAsyncTexSubImage2D",
257 "width", size.width(),
258 "height", size.height());
259
260 // Create a texture from the image and upload to it.
261 GLuint texture = 0;
262 glGenTextures(1, &texture);
263 glActiveTexture(GL_TEXTURE0);
264 glBindTexture(GL_TEXTURE_2D, texture);
265 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image);
266 {
267 TRACE_EVENT0("gpu", "performAsyncTexSubImage2D glTexSubImage2D");
268 glTexSubImage2D(GL_TEXTURE_2D, 0,
269 offset.x(), offset.y(),
270 size.width(), size.height(),
271 format, type, data);
272 }
273
274 // Uploads usually finish on the GPU, but just in case add a fence
275 // and guarantee the upload has completed.
276 // EGLSyncKHR fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL);
277 // EGLint flags = EGL_SYNC_FLUSH_COMMANDS_BIT_KHR;
278 // EGLTimeKHR time = EGL_FOREVER_KHR;
279 // eglClientWaitSyncKHR(display, fence, flags, time);
280
281 // TODO: Fix bindings (link errors) to enable the above instead of glFinish.
282 glFinish();
283
284 // We can delete this thread's texture as the real texture
285 // now contains the data.
286 glDeleteTextures(1, &texture);
287 CHK();
288 }
289
290
291
292 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698