Merge lp:~kdub/mir/mali-client-render-support into lp:~mir-team/mir/trunk
- mali-client-render-support
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~kdub/mir/mali-client-render-support |
Merge into: | lp:~mir-team/mir/trunk |
Diff against target: |
734 lines (+209/-238) 7 files modified
include/shared/mir/graphics/android/mir_native_window.h (+1/-0) src/client/android/android_client_buffer.cpp (+1/-2) src/client/android/client_surface_interpreter.cpp (+3/-0) src/shared/graphics/android/mir_native_window.cpp (+18/-7) tests/integration-tests/client/test_client_render.cpp (+156/-229) tests/unit-tests/client/android/test_android_native_window.cpp (+14/-0) tests/unit-tests/client/android/test_client_surface_interpreter.cpp (+16/-0) |
To merge this branch: | bzr merge lp:~kdub/mir/mali-client-render-support |
Related bugs: | |
Related blueprints: |
Mir on the Nexus 10
(Undefined)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robert Carr (community) | Needs Information | ||
Alan Griffiths | Needs Fixing | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+185603@code.launchpad.net |
This proposal has been superseded by a proposal from 2013-09-24.
Commit message
android: support driver hooks for the Mali T604 (present in nexus 10)
Description of the change
android: support driver hooks for the Mali T604 (present in nexus 10)
The exynos driver needed some function hooks implemented. This change implements those hooks and gets the TestClientIPCRender test to pass. This test sends buffers over IPC to a client, and the client then establishes an egl context, renders to the buffer, and checks the buffer content back on the server side.
Please note: the nexus 10 display is still broken (so running a demo server won't go well), but supporting the hooks for the driver is the first step.
PS Jenkins bot (ps-jenkins) wrote : | # |
Alan Griffiths (alan-griffiths) wrote : | # |
On android (N4) I get:
./unit-tests
...
[ PASSED ] 730 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] ClientAndroidBu
(But it fixes a hang in SwitchingBundle
Alan Griffiths (alan-griffiths) wrote : | # |
SwitchingBundle
But this definitely breaks:
# ./unit-tests --gtest_
/home/alan/
Value of: native_
Actual: 66
Expected: expected_
Which is: 16
[ FAILED ] ClientAndroidBu
[----------] 1 test from ClientAndroidBu
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (4 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] ClientAndroidBu
1 FAILED TEST
Kevin DuBois (kdub) wrote : | # |
will have to take a look at stride on android again
Robert Carr (robertcarr) wrote : | # |
121 + static MirPixelFormat select_
122 + {
123 + if (visual_id == 5)
124 + return mir_pixel_
It would be nice to see some constants for visual_id.
Haven't tested on nexus 4. Let me know if it needs some runs.
==
+ case NATIVE_
43 + return 2;
===
Wondering if this has implications on existing hardware support (n4, etc...)
Preview Diff
1 | === modified file 'include/shared/mir/graphics/android/mir_native_window.h' |
2 | --- include/shared/mir/graphics/android/mir_native_window.h 2013-05-16 20:19:12 +0000 |
3 | +++ include/shared/mir/graphics/android/mir_native_window.h 2013-09-13 21:49:43 +0000 |
4 | @@ -41,6 +41,7 @@ |
5 | int perform(int key, va_list args ); |
6 | int dequeueBuffer(struct ANativeWindowBuffer** buffer); |
7 | int queueBuffer(struct ANativeWindowBuffer* buffer, std::shared_ptr<SyncObject> const& fence); |
8 | + int cancelBuffer(struct ANativeWindowBuffer* buffer, std::shared_ptr<SyncObject> const& fence); |
9 | int setSwapInterval(int interval); |
10 | private: |
11 | |
12 | |
13 | === modified file 'src/client/android/android_client_buffer.cpp' |
14 | --- src/client/android/android_client_buffer.cpp 2013-08-28 03:41:48 +0000 |
15 | +++ src/client/android/android_client_buffer.cpp 2013-09-13 21:49:43 +0000 |
16 | @@ -41,8 +41,7 @@ |
17 | |
18 | native_window_buffer->height = static_cast<int32_t>(size.height.as_uint32_t()); |
19 | native_window_buffer->width = static_cast<int32_t>(size.width.as_uint32_t()); |
20 | - native_window_buffer->stride = stride.as_uint32_t() / |
21 | - geom::bytes_per_pixel(buffer_pf); |
22 | + native_window_buffer->stride = stride.as_uint32_t(); |
23 | native_window_buffer->usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER; |
24 | native_window_buffer->handle = native_handle.get(); |
25 | } |
26 | |
27 | === modified file 'src/client/android/client_surface_interpreter.cpp' |
28 | --- src/client/android/client_surface_interpreter.cpp 2013-05-16 20:19:12 +0000 |
29 | +++ src/client/android/client_surface_interpreter.cpp 2013-09-13 21:49:43 +0000 |
30 | @@ -33,6 +33,7 @@ |
31 | { |
32 | auto buffer = surface.get_current_buffer(); |
33 | auto buffer_to_driver = buffer->native_buffer_handle(); |
34 | + |
35 | buffer_to_driver->format = driver_pixel_format; |
36 | |
37 | return buffer_to_driver.get(); |
38 | @@ -65,6 +66,8 @@ |
39 | return driver_pixel_format; |
40 | case NATIVE_WINDOW_TRANSFORM_HINT: |
41 | return 0; |
42 | + case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: |
43 | + return 2; |
44 | default: |
45 | throw std::runtime_error("driver requested unsupported query"); |
46 | } |
47 | |
48 | === modified file 'src/shared/graphics/android/mir_native_window.cpp' |
49 | --- src/shared/graphics/android/mir_native_window.cpp 2013-05-20 15:29:28 +0000 |
50 | +++ src/shared/graphics/android/mir_native_window.cpp 2013-09-13 21:49:43 +0000 |
51 | @@ -128,16 +128,19 @@ |
52 | return 0; |
53 | } |
54 | |
55 | -int cancelBuffer_deprecated_static(struct ANativeWindow* /*window*/, |
56 | - struct ANativeWindowBuffer* /*buffer*/) |
57 | +int cancelBuffer_deprecated_static(struct ANativeWindow* window, |
58 | + struct ANativeWindowBuffer* buffer) |
59 | { |
60 | - return 0; |
61 | + return cancelBuffer_static(window, buffer, -1); |
62 | } |
63 | |
64 | -int cancelBuffer_static(struct ANativeWindow* /*window*/, |
65 | - struct ANativeWindowBuffer* /*buffer*/, int /*fence_fd*/) |
66 | +int cancelBuffer_static(struct ANativeWindow* window, |
67 | + struct ANativeWindowBuffer* buffer, int fence_fd) |
68 | { |
69 | - return 0; |
70 | + auto ioctl_control = std::make_shared<IoctlControl>(); |
71 | + auto fence = std::make_shared<mga::SyncFence>(fence_fd, ioctl_control); |
72 | + auto self = static_cast<mga::MirNativeWindow*>(window); |
73 | + return self->cancelBuffer(buffer, fence); |
74 | } |
75 | |
76 | } |
77 | @@ -182,7 +185,15 @@ |
78 | return 0; |
79 | } |
80 | |
81 | -int mga::MirNativeWindow::queueBuffer(struct ANativeWindowBuffer* buffer, std::shared_ptr<mga::SyncObject> const& fence) |
82 | +int mga::MirNativeWindow::queueBuffer(struct ANativeWindowBuffer* buffer, |
83 | + std::shared_ptr<mga::SyncObject> const& fence) |
84 | +{ |
85 | + driver_interpreter->driver_returns_buffer(buffer, fence); |
86 | + return 0; |
87 | +} |
88 | + |
89 | +int mga::MirNativeWindow::cancelBuffer(struct ANativeWindowBuffer* buffer, |
90 | + std::shared_ptr<mga::SyncObject> const& fence) |
91 | { |
92 | driver_interpreter->driver_returns_buffer(buffer, fence); |
93 | return 0; |
94 | |
95 | === modified file 'tests/integration-tests/client/test_client_render.cpp' |
96 | --- tests/integration-tests/client/test_client_render.cpp 2013-08-28 03:41:48 +0000 |
97 | +++ tests/integration-tests/client/test_client_render.cpp 2013-09-13 21:49:43 +0000 |
98 | @@ -29,6 +29,7 @@ |
99 | |
100 | #include "mir/frontend/communicator.h" |
101 | |
102 | +#include <iostream> |
103 | #include <gmock/gmock.h> |
104 | #include <thread> |
105 | #include <hardware/gralloc.h> |
106 | @@ -65,10 +66,6 @@ |
107 | *surf = surface; |
108 | } |
109 | |
110 | -static void next_callback(MirSurface *, void*) |
111 | -{ |
112 | -} |
113 | - |
114 | static uint32_t pattern0 [2][2] = {{0x12345678, 0x23456789}, |
115 | {0x34567890, 0x45678901}}; |
116 | |
117 | @@ -76,6 +73,15 @@ |
118 | {0xFF00FF00, 0xFF0000FF}}; |
119 | struct TestClient |
120 | { |
121 | + static MirPixelFormat select_format_for_visual_id(int visual_id) |
122 | + { |
123 | + if (visual_id == 5) |
124 | + return mir_pixel_format_argb_8888; |
125 | + if (visual_id == 1) |
126 | + return mir_pixel_format_abgr_8888; |
127 | + |
128 | + return mir_pixel_format_invalid; |
129 | + } |
130 | |
131 | static void sig_handle(int) |
132 | { |
133 | @@ -115,6 +121,8 @@ |
134 | /* render pattern */ |
135 | mtd::DrawPatternCheckered<2,2> draw_pattern0(mt::pattern0); |
136 | draw_pattern0.draw(graphics_region); |
137 | + |
138 | + mir_surface_swap_buffers_sync(surface); |
139 | |
140 | mir_wait_for(mir_surface_release(surface, &create_callback, &surface)); |
141 | |
142 | @@ -156,11 +164,13 @@ |
143 | mtd::DrawPatternCheckered<2,2> draw_pattern0(mt::pattern0); |
144 | draw_pattern0.draw(graphics_region); |
145 | |
146 | - mir_wait_for(mir_surface_swap_buffers(surface, &next_callback, (void*) NULL)); |
147 | + mir_surface_swap_buffers_sync(surface); |
148 | mir_surface_get_graphics_region( surface, graphics_region.get()); |
149 | mtd::DrawPatternCheckered<2,2> draw_pattern1(mt::pattern1); |
150 | draw_pattern1.draw(graphics_region); |
151 | |
152 | + mir_surface_swap_buffers_sync(surface); |
153 | + |
154 | mir_wait_for(mir_surface_release(surface, &create_callback, &surface)); |
155 | |
156 | /* release */ |
157 | @@ -168,68 +178,62 @@ |
158 | return 0; |
159 | } |
160 | |
161 | + static MirSurface* create_mir_surface(MirConnection * connection, EGLDisplay display, EGLConfig config) |
162 | + { |
163 | + int visual_id; |
164 | + eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &visual_id); |
165 | + |
166 | + /* make surface */ |
167 | + MirSurfaceParameters surface_parameters; |
168 | + surface_parameters.name = "testsurface"; |
169 | + surface_parameters.width = test_width; |
170 | + surface_parameters.height = test_height; |
171 | + surface_parameters.pixel_format = select_format_for_visual_id(visual_id); |
172 | + return mir_connection_create_surface_sync(connection, &surface_parameters); |
173 | + } |
174 | + |
175 | static int render_accelerated() |
176 | { |
177 | if (signal(SIGCONT, sig_handle) == SIG_ERR) |
178 | return -1; |
179 | pause(); |
180 | |
181 | - /* only use C api */ |
182 | - MirConnection* connection = NULL; |
183 | - MirSurface* surface; |
184 | - MirSurfaceParameters surface_parameters; |
185 | - |
186 | - /* establish connection. wait for server to come up */ |
187 | - while (connection == NULL) |
188 | - { |
189 | - mir_wait_for(mir_connect("./test_socket_surface", "test_renderer", |
190 | - &connected_callback, &connection)); |
191 | - std::this_thread::sleep_for(std::chrono::milliseconds(10)); |
192 | - } |
193 | - /* make surface */ |
194 | - surface_parameters.name = "testsurface"; |
195 | - surface_parameters.width = test_width; |
196 | - surface_parameters.height = test_height; |
197 | - surface_parameters.pixel_format = mir_pixel_format_abgr_8888; |
198 | - |
199 | - mir_wait_for(mir_connection_create_surface(connection, |
200 | - &surface_parameters, |
201 | - &create_callback, |
202 | - &surface)); |
203 | - |
204 | int major, minor, n; |
205 | - EGLDisplay disp; |
206 | EGLContext context; |
207 | EGLSurface egl_surface; |
208 | EGLConfig egl_config; |
209 | EGLint attribs[] = { |
210 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
211 | - EGL_GREEN_SIZE, 8, |
212 | + EGL_BUFFER_SIZE, 32, |
213 | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
214 | EGL_NONE }; |
215 | EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; |
216 | |
217 | - EGLNativeDisplayType native_display = (EGLNativeDisplayType)mir_connection_get_egl_native_display(connection); |
218 | - EGLNativeWindowType native_window = (EGLNativeWindowType) mir_surface_get_egl_native_window(surface); |
219 | - |
220 | - disp = eglGetDisplay(native_display); |
221 | - eglInitialize(disp, &major, &minor); |
222 | - |
223 | - eglChooseConfig(disp, attribs, &egl_config, 1, &n); |
224 | - egl_surface = eglCreateWindowSurface(disp, egl_config, native_window, NULL); |
225 | - context = eglCreateContext(disp, egl_config, EGL_NO_CONTEXT, context_attribs); |
226 | - eglMakeCurrent(disp, egl_surface, egl_surface, context); |
227 | + auto connection = mir_connect_sync("./test_socket_surface", "test_renderer"); |
228 | + |
229 | + auto native_display = mir_connection_get_egl_native_display(connection); |
230 | + auto egl_display = eglGetDisplay(native_display); |
231 | + eglInitialize(egl_display, &major, &minor); |
232 | + eglChooseConfig(egl_display, attribs, &egl_config, 1, &n); |
233 | + |
234 | + auto mir_surface = create_mir_surface(connection, egl_display, egl_config); |
235 | + auto native_window = static_cast<EGLNativeWindowType>( |
236 | + mir_surface_get_egl_native_window(mir_surface)); |
237 | + |
238 | + egl_surface = eglCreateWindowSurface(egl_display, egl_config, native_window, NULL); |
239 | + context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, context_attribs); |
240 | + eglMakeCurrent(egl_display, egl_surface, egl_surface, context); |
241 | |
242 | glClearColor(1.0, 0.0, 0.0, 1.0); |
243 | glClear(GL_COLOR_BUFFER_BIT); |
244 | |
245 | - eglSwapBuffers(disp, egl_surface); |
246 | - mir_wait_for(mir_surface_release(surface, &create_callback, &surface)); |
247 | + eglSwapBuffers(egl_display, egl_surface); |
248 | + |
249 | + mir_surface_release_sync(mir_surface); |
250 | |
251 | /* release */ |
252 | mir_connection_release(connection); |
253 | return 0; |
254 | - |
255 | } |
256 | |
257 | static int render_accelerated_double() |
258 | @@ -238,68 +242,46 @@ |
259 | return -1; |
260 | pause(); |
261 | |
262 | - /* only use C api */ |
263 | - MirConnection* connection = NULL; |
264 | - MirSurface* surface; |
265 | - MirSurfaceParameters surface_parameters; |
266 | - |
267 | - /* establish connection. wait for server to come up */ |
268 | - while (connection == NULL) |
269 | - { |
270 | - mir_wait_for(mir_connect("./test_socket_surface", "test_renderer", |
271 | - &connected_callback, &connection)); |
272 | - std::this_thread::sleep_for(std::chrono::milliseconds(10)); |
273 | - } |
274 | - /* make surface */ |
275 | - surface_parameters.name = "testsurface"; |
276 | - surface_parameters.width = test_width; |
277 | - surface_parameters.height = test_height; |
278 | - surface_parameters.pixel_format = mir_pixel_format_abgr_8888; |
279 | - |
280 | - mir_wait_for(mir_connection_create_surface(connection, |
281 | - &surface_parameters, |
282 | - &create_callback, |
283 | - &surface)); |
284 | - |
285 | int major, minor, n; |
286 | - EGLDisplay disp; |
287 | EGLContext context; |
288 | EGLSurface egl_surface; |
289 | EGLConfig egl_config; |
290 | EGLint attribs[] = { |
291 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
292 | - EGL_GREEN_SIZE, 8, |
293 | + EGL_BUFFER_SIZE, 32, |
294 | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
295 | EGL_NONE }; |
296 | EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; |
297 | |
298 | - EGLNativeDisplayType native_display = (EGLNativeDisplayType)mir_connection_get_egl_native_display(connection); |
299 | - EGLNativeWindowType native_window = (EGLNativeWindowType)mir_surface_get_egl_native_window(surface); |
300 | - |
301 | - disp = eglGetDisplay(native_display); |
302 | - eglInitialize(disp, &major, &minor); |
303 | - |
304 | - eglChooseConfig(disp, attribs, &egl_config, 1, &n); |
305 | - egl_surface = eglCreateWindowSurface(disp, egl_config, native_window, NULL); |
306 | - context = eglCreateContext(disp, egl_config, EGL_NO_CONTEXT, context_attribs); |
307 | - eglMakeCurrent(disp, egl_surface, egl_surface, context); |
308 | - |
309 | + auto connection = mir_connect_sync("./test_socket_surface", "test_renderer"); |
310 | + |
311 | + auto native_display = mir_connection_get_egl_native_display(connection); |
312 | + auto egl_display = eglGetDisplay(native_display); |
313 | + eglInitialize(egl_display, &major, &minor); |
314 | + eglChooseConfig(egl_display, attribs, &egl_config, 1, &n); |
315 | + |
316 | + auto mir_surface = create_mir_surface(connection, egl_display, egl_config); |
317 | + auto native_window = static_cast<EGLNativeWindowType>( |
318 | + mir_surface_get_egl_native_window(mir_surface)); |
319 | + |
320 | + egl_surface = eglCreateWindowSurface(egl_display, egl_config, native_window, NULL); |
321 | + context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, context_attribs); |
322 | + eglMakeCurrent(egl_display, egl_surface, egl_surface, context); |
323 | + |
324 | + //draw red |
325 | glClearColor(1.0, 0.0, 0.0, 1.0); |
326 | glClear(GL_COLOR_BUFFER_BIT); |
327 | - |
328 | - eglSwapBuffers(disp, egl_surface); |
329 | - |
330 | + eglSwapBuffers(egl_display, egl_surface); |
331 | + |
332 | + //draw green |
333 | glClearColor(0.0, 1.0, 0.0, 1.0); |
334 | glClear(GL_COLOR_BUFFER_BIT); |
335 | - |
336 | - eglSwapBuffers(disp, egl_surface); |
337 | - |
338 | - mir_wait_for(mir_surface_release(surface, &create_callback, &surface)); |
339 | - |
340 | - /* release */ |
341 | + eglSwapBuffers(egl_display, egl_surface); |
342 | + |
343 | + mir_surface_release_sync(mir_surface); |
344 | + |
345 | mir_connection_release(connection); |
346 | return 0; |
347 | - |
348 | } |
349 | |
350 | static int exit_function() |
351 | @@ -311,13 +293,13 @@ |
352 | /* server code */ |
353 | struct StubServerGenerator : public mt::StubServerTool |
354 | { |
355 | - StubServerGenerator(std::shared_ptr<MirNativeBuffer> const& handle, int id) |
356 | - : handle(handle), |
357 | - next_received(false), |
358 | - next_allowed(false), |
359 | - handle_id(id) |
360 | + StubServerGenerator(std::shared_ptr<MirNativeBuffer> const& handle0, |
361 | + std::shared_ptr<MirNativeBuffer> const& handle1) |
362 | + : handle0(handle0), |
363 | + handle1(handle1), |
364 | + next_buffer_count(0), |
365 | + buffer_count(2) |
366 | { |
367 | - |
368 | } |
369 | |
370 | void create_surface(google::protobuf::RpcController* /*controller*/, |
371 | @@ -325,18 +307,21 @@ |
372 | mir::protobuf::Surface* response, |
373 | google::protobuf::Closure* done) |
374 | { |
375 | - response->mutable_id()->set_value(13); // TODO distinct numbers & tracking |
376 | + auto next_handle = get_next_handle(); |
377 | + |
378 | + response->mutable_id()->set_value(13); //surface id |
379 | response->set_width(test_width); |
380 | response->set_height(test_height); |
381 | + surface_pf = geom::PixelFormat(request->pixel_format()); |
382 | response->set_pixel_format(request->pixel_format()); |
383 | - response->mutable_buffer()->set_buffer_id(handle_id); |
384 | - response->mutable_buffer()->set_stride(handle->stride); |
385 | + response->mutable_buffer()->set_buffer_id(next_buffer_count % buffer_count); |
386 | + response->mutable_buffer()->set_stride(next_handle->stride); |
387 | |
388 | response->mutable_buffer()->set_fds_on_side_channel(1); |
389 | - native_handle_t const* native_handle = handle->handle; |
390 | - for(auto i=0; i<native_handle->numFds; i++) |
391 | + native_handle_t const* native_handle = next_handle->handle; |
392 | + for(auto i=0; i < native_handle->numFds; i++) |
393 | response->mutable_buffer()->add_fd(native_handle->data[i]); |
394 | - for(auto i=0; i<native_handle->numInts; i++) |
395 | + for(auto i=0; i < native_handle->numInts; i++) |
396 | response->mutable_buffer()->add_data(native_handle->data[native_handle->numFds+i]); |
397 | |
398 | std::unique_lock<std::mutex> lock(guard); |
399 | @@ -352,22 +337,12 @@ |
400 | ::mir::protobuf::Buffer* response, |
401 | ::google::protobuf::Closure* done) |
402 | { |
403 | - { |
404 | - std::unique_lock<std::mutex> lk(next_guard); |
405 | - next_received = true; |
406 | - next_cv.notify_all(); |
407 | - |
408 | - while (!next_allowed) { |
409 | - allow_cv.wait(lk); |
410 | - } |
411 | - next_allowed = false; |
412 | - } |
413 | - |
414 | - response->set_buffer_id(handle_id); |
415 | + auto next_handle = get_next_handle(); |
416 | + response->set_buffer_id(next_buffer_count % buffer_count); |
417 | |
418 | response->set_fds_on_side_channel(1); |
419 | - native_handle_t const* native_handle = handle->handle; |
420 | - response->set_stride(handle->stride); |
421 | + native_handle_t const* native_handle = next_handle->handle; |
422 | + response->set_stride(next_handle->stride); |
423 | for(auto i=0; i<native_handle->numFds; i++) |
424 | response->add_fd(native_handle->data[i]); |
425 | for(auto i=0; i<native_handle->numInts; i++) |
426 | @@ -376,41 +351,46 @@ |
427 | done->Run(); |
428 | } |
429 | |
430 | - void wait_on_next_buffer() |
431 | - { |
432 | - std::unique_lock<std::mutex> lk(next_guard); |
433 | - while (!next_received) |
434 | - next_cv.wait(lk); |
435 | - next_received = false; |
436 | - } |
437 | - |
438 | - void allow_next_continue() |
439 | - { |
440 | - std::unique_lock<std::mutex> lk(next_guard); |
441 | - next_allowed = true; |
442 | - allow_cv.notify_all(); |
443 | - lk.unlock(); |
444 | - } |
445 | - |
446 | - void set_handle(std::shared_ptr<MirNativeBuffer> const& pack, int id) |
447 | - { |
448 | - handle = pack; |
449 | - handle_id = id; |
450 | + std::shared_ptr<MirNativeBuffer> get_next_handle() |
451 | + { |
452 | + std::swap(handle0, handle1); |
453 | + next_buffer_count++; |
454 | + return handle0; |
455 | + } |
456 | + |
457 | + std::shared_ptr<MirNativeBuffer> second_to_last_returned() |
458 | + { |
459 | + return handle0; |
460 | + } |
461 | + |
462 | + std::shared_ptr<MirNativeBuffer> last_returned() |
463 | + { |
464 | + return handle1; |
465 | + } |
466 | + |
467 | + uint32_t red_value_for_surface() |
468 | + { |
469 | + if ((surface_pf == geom::PixelFormat::abgr_8888) || (surface_pf == geom::PixelFormat::xbgr_8888)) |
470 | + return 0xFF0000FF; |
471 | + |
472 | + if ((surface_pf == geom::PixelFormat::argb_8888) || (surface_pf == geom::PixelFormat::xrgb_8888)) |
473 | + return 0xFFFF0000; |
474 | + |
475 | + return 0x0; |
476 | + } |
477 | + |
478 | + uint32_t green_value_for_surface() |
479 | + { |
480 | + return 0xFF00FF00; |
481 | } |
482 | |
483 | private: |
484 | - std::shared_ptr<MirNativeBuffer> handle; |
485 | - |
486 | - std::mutex next_guard; |
487 | - std::condition_variable next_cv; |
488 | - std::condition_variable allow_cv; |
489 | - bool next_received; |
490 | - bool next_allowed; |
491 | - |
492 | - int handle_id; |
493 | + geom::PixelFormat surface_pf; //must be a 32 bit one; |
494 | + std::shared_ptr<MirNativeBuffer> handle0, handle1; |
495 | + int next_buffer_count; |
496 | + int const buffer_count; |
497 | }; |
498 | |
499 | - |
500 | } |
501 | } |
502 | |
503 | @@ -429,11 +409,6 @@ |
504 | mt::TestClient::render_double, |
505 | mt::TestClient::exit_function); |
506 | |
507 | - second_render_with_same_buffer_client_process |
508 | - = mtf::fork_and_run_in_a_different_process( |
509 | - mt::TestClient::render_double, |
510 | - mt::TestClient::exit_function); |
511 | - |
512 | render_accelerated_process |
513 | = mtf::fork_and_run_in_a_different_process( |
514 | mt::TestClient::render_accelerated, |
515 | @@ -448,22 +423,22 @@ |
516 | void SetUp() { |
517 | ASSERT_FALSE(mtd::is_surface_flinger_running()); |
518 | |
519 | - size = geom::Size{test_width, test_height}; |
520 | - pf = geom::PixelFormat::abgr_8888; |
521 | + auto size = geom::Size{test_width, test_height}; |
522 | + auto pf = geom::PixelFormat::argb_8888; |
523 | + |
524 | + buffer_converter = std::make_shared<mtd::TestGrallocMapper>(); |
525 | |
526 | auto initializer = std::make_shared<mg::NullBufferInitializer>(); |
527 | - allocator = std::make_shared<mga::AndroidGraphicBufferAllocator> (initializer); |
528 | + auto allocator = std::make_shared<mga::AndroidGraphicBufferAllocator> (initializer); |
529 | mg::BufferProperties properties(size, pf, mg::BufferUsage::hardware); |
530 | - android_buffer = allocator->alloc_buffer(properties); |
531 | - second_android_buffer = allocator->alloc_buffer(properties); |
532 | - |
533 | - buffer_converter = std::make_shared<mtd::TestGrallocMapper>(); |
534 | - |
535 | - handle = android_buffer->native_buffer_handle(); |
536 | - second_handle = second_android_buffer->native_buffer_handle(); |
537 | + android_buffer0 = allocator->alloc_buffer(properties); |
538 | + android_buffer1 = allocator->alloc_buffer(properties); |
539 | + |
540 | + auto handle0 = android_buffer0->native_buffer_handle(); |
541 | + auto handle1 = android_buffer1->native_buffer_handle(); |
542 | |
543 | /* start a server */ |
544 | - mock_server = std::make_shared<mt::StubServerGenerator>(handle, 14); |
545 | + mock_server = std::make_shared<mt::StubServerGenerator>(handle0, handle1); |
546 | test_server = std::make_shared<mt::TestProtobufServer>("./test_socket_surface", mock_server); |
547 | test_server->comm->start(); |
548 | } |
549 | @@ -478,29 +453,19 @@ |
550 | std::shared_ptr<mt::TestProtobufServer> test_server; |
551 | std::shared_ptr<mt::StubServerGenerator> mock_server; |
552 | |
553 | - geom::Size size; |
554 | - geom::PixelFormat pf; |
555 | - mg::BufferID id1; |
556 | - mg::BufferID id2; |
557 | std::shared_ptr<mtd::TestGrallocMapper> buffer_converter; |
558 | std::shared_ptr<mtf::Process> client_process; |
559 | |
560 | - std::shared_ptr<MirNativeBuffer> handle; |
561 | - std::shared_ptr<MirNativeBuffer> second_handle; |
562 | - |
563 | - std::shared_ptr<mg::Buffer> android_buffer; |
564 | - std::shared_ptr<mg::Buffer> second_android_buffer; |
565 | - std::shared_ptr<mga::AndroidGraphicBufferAllocator> allocator; |
566 | + std::shared_ptr<mg::Buffer> android_buffer0; |
567 | + std::shared_ptr<mg::Buffer> android_buffer1; |
568 | |
569 | static std::shared_ptr<mtf::Process> render_single_client_process; |
570 | static std::shared_ptr<mtf::Process> render_double_client_process; |
571 | - static std::shared_ptr<mtf::Process> second_render_with_same_buffer_client_process; |
572 | static std::shared_ptr<mtf::Process> render_accelerated_process; |
573 | static std::shared_ptr<mtf::Process> render_accelerated_process_double; |
574 | }; |
575 | std::shared_ptr<mtf::Process> TestClientIPCRender::render_single_client_process; |
576 | std::shared_ptr<mtf::Process> TestClientIPCRender::render_double_client_process; |
577 | -std::shared_ptr<mtf::Process> TestClientIPCRender::second_render_with_same_buffer_client_process; |
578 | std::shared_ptr<mtf::Process> TestClientIPCRender::render_accelerated_process; |
579 | std::shared_ptr<mtf::Process> TestClientIPCRender::render_accelerated_process_double; |
580 | |
581 | @@ -514,8 +479,8 @@ |
582 | EXPECT_TRUE(render_single_client_process->wait_for_termination().succeeded()); |
583 | |
584 | /* check content */ |
585 | - auto region = buffer_converter->graphic_region_from_handle(handle); |
586 | - EXPECT_TRUE(rendered_pattern.check(region)); |
587 | + auto last_handle = mock_server->last_returned(); |
588 | + EXPECT_TRUE(rendered_pattern.check(buffer_converter->graphic_region_from_handle(last_handle))); |
589 | } |
590 | |
591 | TEST_F(TestClientIPCRender, test_render_double) |
592 | @@ -525,80 +490,42 @@ |
593 | /* activate client */ |
594 | render_double_client_process->cont(); |
595 | |
596 | - /* wait for next buffer */ |
597 | - mock_server->wait_on_next_buffer(); |
598 | - auto region = buffer_converter->graphic_region_from_handle(handle); |
599 | + /* wait for client to finish */ |
600 | + EXPECT_TRUE(render_double_client_process->wait_for_termination().succeeded()); |
601 | + |
602 | + auto second_to_last_handle = mock_server->second_to_last_returned(); |
603 | + auto region = buffer_converter->graphic_region_from_handle(second_to_last_handle); |
604 | EXPECT_TRUE(rendered_pattern0.check(region)); |
605 | |
606 | - mock_server->set_handle(second_handle, 15); |
607 | - mock_server->allow_next_continue(); |
608 | - |
609 | - /* wait for client to finish */ |
610 | - EXPECT_TRUE(render_double_client_process->wait_for_termination().succeeded()); |
611 | - |
612 | - auto second_region = buffer_converter->graphic_region_from_handle(second_handle); |
613 | + auto last_handle = mock_server->last_returned(); |
614 | + auto second_region = buffer_converter->graphic_region_from_handle(last_handle); |
615 | EXPECT_TRUE(rendered_pattern1.check(second_region)); |
616 | } |
617 | |
618 | -TEST_F(TestClientIPCRender, test_second_render_with_same_buffer) |
619 | -{ |
620 | - mtd::DrawPatternCheckered<2,2> rendered_pattern(mt::pattern1); |
621 | - /* activate client */ |
622 | - second_render_with_same_buffer_client_process->cont(); |
623 | - |
624 | - /* wait for next buffer */ |
625 | - mock_server->wait_on_next_buffer(); |
626 | - mock_server->allow_next_continue(); |
627 | - |
628 | - /* wait for client to finish */ |
629 | - EXPECT_TRUE(second_render_with_same_buffer_client_process->wait_for_termination().succeeded()); |
630 | - |
631 | - /* check content */ |
632 | - auto region = buffer_converter->graphic_region_from_handle(handle); |
633 | - EXPECT_TRUE(rendered_pattern.check(region)); |
634 | -} |
635 | - |
636 | TEST_F(TestClientIPCRender, test_accelerated_render) |
637 | { |
638 | - mtd::DrawPatternSolid red_pattern(0xFF0000FF); |
639 | - |
640 | - /* activate client */ |
641 | render_accelerated_process->cont(); |
642 | - |
643 | - /* wait for next buffer */ |
644 | - mock_server->wait_on_next_buffer(); |
645 | - mock_server->allow_next_continue(); |
646 | - |
647 | - /* wait for client to finish */ |
648 | EXPECT_TRUE(render_accelerated_process->wait_for_termination().succeeded()); |
649 | |
650 | /* check content */ |
651 | - auto region = buffer_converter->graphic_region_from_handle(handle); |
652 | - EXPECT_TRUE(red_pattern.check(region)); |
653 | + mtd::DrawPatternSolid red_pattern(mock_server->red_value_for_surface()); |
654 | + auto last_handle = mock_server->last_returned(); |
655 | + EXPECT_TRUE(red_pattern.check(buffer_converter->graphic_region_from_handle(last_handle))); |
656 | } |
657 | |
658 | TEST_F(TestClientIPCRender, test_accelerated_render_double) |
659 | { |
660 | - mtd::DrawPatternSolid red_pattern(0xFF0000FF); |
661 | - mtd::DrawPatternSolid green_pattern(0xFF00FF00); |
662 | - /* activate client */ |
663 | render_accelerated_process_double->cont(); |
664 | - |
665 | - /* wait for next buffer */ |
666 | - mock_server->wait_on_next_buffer(); |
667 | - mock_server->set_handle(second_handle, 15); |
668 | - mock_server->allow_next_continue(); |
669 | - |
670 | - mock_server->wait_on_next_buffer(); |
671 | - mock_server->allow_next_continue(); |
672 | - |
673 | - /* wait for client to finish */ |
674 | EXPECT_TRUE(render_accelerated_process_double->wait_for_termination().succeeded()); |
675 | |
676 | /* check content */ |
677 | - auto region = buffer_converter->graphic_region_from_handle(handle); |
678 | + mtd::DrawPatternSolid red_pattern(mock_server->red_value_for_surface()); |
679 | + auto second_to_last_handle = mock_server->second_to_last_returned(); |
680 | + auto region = buffer_converter->graphic_region_from_handle(second_to_last_handle); |
681 | EXPECT_TRUE(red_pattern.check(region)); |
682 | |
683 | - auto second_region = buffer_converter->graphic_region_from_handle(second_handle); |
684 | + mtd::DrawPatternSolid green_pattern(mock_server->green_value_for_surface()); |
685 | + auto last_handle = mock_server->last_returned(); |
686 | + auto second_region = buffer_converter->graphic_region_from_handle(last_handle); |
687 | EXPECT_TRUE(green_pattern.check(second_region)); |
688 | } |
689 | |
690 | === modified file 'tests/unit-tests/client/android/test_android_native_window.cpp' |
691 | --- tests/unit-tests/client/android/test_android_native_window.cpp 2013-05-16 20:07:39 +0000 |
692 | +++ tests/unit-tests/client/android/test_android_native_window.cpp 2013-09-13 21:49:43 +0000 |
693 | @@ -288,3 +288,17 @@ |
694 | auto ret = window->dequeueBuffer(window.get(), &tmp, &fencefd); |
695 | EXPECT_EQ(0, ret); |
696 | } |
697 | + |
698 | +TEST_F(AndroidNativeWindowTest, native_window_cancel_hook_behavior) |
699 | +{ |
700 | + using namespace testing; |
701 | + ANativeWindowBuffer buffer; |
702 | + int fence_fd = 33; |
703 | + |
704 | + EXPECT_CALL(*mock_driver_interpreter, driver_returns_buffer(&buffer, _)) |
705 | + .Times(1); |
706 | + |
707 | + std::shared_ptr<ANativeWindow> window = std::make_shared<mga::MirNativeWindow>(mock_driver_interpreter); |
708 | + auto rc = window->cancelBuffer(window.get(), &buffer, fence_fd); |
709 | + EXPECT_EQ(0, rc); |
710 | +} |
711 | |
712 | === modified file 'tests/unit-tests/client/android/test_client_surface_interpreter.cpp' |
713 | --- tests/unit-tests/client/android/test_client_surface_interpreter.cpp 2013-07-01 15:10:36 +0000 |
714 | +++ tests/unit-tests/client/android/test_client_surface_interpreter.cpp 2013-09-13 21:49:43 +0000 |
715 | @@ -227,3 +227,19 @@ |
716 | |
717 | EXPECT_EQ(surf_params.height, height); |
718 | } |
719 | + |
720 | +/* this is query key is a bit confusing from the system/window.h description. |
721 | + what it means is the minimum number of buffers that the server reserves for its own use in steady |
722 | + state. The drivers consider 'steady state' to begin after the first call to queueBuffer. |
723 | + So, for instance, if a driver requires 3 buffers to run at steady state, and the server needs |
724 | + to keep 2 buffers on hand at all time, the driver might dequeue 5 buffers, then cancel those 5 buffers. |
725 | + After the first call to queueBuffer however, the client may never own more than the number it has |
726 | + reserved (in this case, 3 buffers) */ |
727 | +TEST_F(AndroidInterpreterTest, native_window_minimum_undequeued_query_hook) |
728 | +{ |
729 | + testing::NiceMock<MockMirSurface> mock_surface{surf_params}; |
730 | + mcla::ClientSurfaceInterpreter interpreter(mock_surface); |
731 | + |
732 | + auto num_buffers = interpreter.driver_requests_info(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS); |
733 | + EXPECT_EQ(2, num_buffers); |
734 | +} |
PASSED: Continuous integration, rev:1075 jenkins. qa.ubuntu. com/job/ mir-ci/ 1477/ jenkins. qa.ubuntu. com/job/ mir-android- saucy-i386- build/1995 jenkins. qa.ubuntu. com/job/ mir-clang- saucy-amd64- build/1880 jenkins. qa.ubuntu. com/job/ mir-saucy- amd64-ci/ 715 jenkins. qa.ubuntu. com/job/ mir-saucy- amd64-ci/ 715/artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ mir-ci/ 1477/rebuild
http://