Mir

Merge lp:~kdub/mir/mali-client-render-support into lp:~mir-team/mir/trunk

Proposed by Kevin DuBois
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
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.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

On android (N4) I get:
./unit-tests
...
[ PASSED ] 730 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] ClientAndroidBufferTest.buffer_packs_anativewindowbuffer_info

(But it fixes a hang in SwitchingBundleTest.client_framerate_matches_compositor - so I guess it doesn't make anything worse.)

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

SwitchingBundleTest.client_framerate_matches_compositor is racy (and not fixed after all)

But this definitely breaks:

# ./unit-tests --gtest_filter=ClientAndroidBufferTest.buffer_packs_anativewindowbuffer_info
/home/alan/display_server/trunk-mir/tests/unit-tests/client/android/test_client_android_buffer.cpp:151: Failure
Value of: native_handle->stride
  Actual: 66
Expected: expected_stride_in_pixels
Which is: 16
[ FAILED ] ClientAndroidBufferTest.buffer_packs_anativewindowbuffer_info (2 ms)
[----------] 1 test from ClientAndroidBufferTest (2 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (4 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] ClientAndroidBufferTest.buffer_packs_anativewindowbuffer_info

 1 FAILED TEST

review: Needs Fixing
Revision history for this message
Kevin DuBois (kdub) wrote :

will have to take a look at stride on android again

Revision history for this message
Robert Carr (robertcarr) wrote :

121 + static MirPixelFormat select_format_for_visual_id(int visual_id)
122 + {
123 + if (visual_id == 5)
124 + return mir_pixel_format_argb_8888;

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_WINDOW_MIN_UNDEQUEUED_BUFFERS:
43 + return 2;
===

Wondering if this has implications on existing hardware support (n4, etc...)

review: Needs Information

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/shared/mir/graphics/android/mir_native_window.h'
--- include/shared/mir/graphics/android/mir_native_window.h 2013-05-16 20:19:12 +0000
+++ include/shared/mir/graphics/android/mir_native_window.h 2013-09-13 21:49:43 +0000
@@ -41,6 +41,7 @@
41 int perform(int key, va_list args );41 int perform(int key, va_list args );
42 int dequeueBuffer(struct ANativeWindowBuffer** buffer);42 int dequeueBuffer(struct ANativeWindowBuffer** buffer);
43 int queueBuffer(struct ANativeWindowBuffer* buffer, std::shared_ptr<SyncObject> const& fence);43 int queueBuffer(struct ANativeWindowBuffer* buffer, std::shared_ptr<SyncObject> const& fence);
44 int cancelBuffer(struct ANativeWindowBuffer* buffer, std::shared_ptr<SyncObject> const& fence);
44 int setSwapInterval(int interval);45 int setSwapInterval(int interval);
45private:46private:
4647
4748
=== modified file 'src/client/android/android_client_buffer.cpp'
--- src/client/android/android_client_buffer.cpp 2013-08-28 03:41:48 +0000
+++ src/client/android/android_client_buffer.cpp 2013-09-13 21:49:43 +0000
@@ -41,8 +41,7 @@
4141
42 native_window_buffer->height = static_cast<int32_t>(size.height.as_uint32_t());42 native_window_buffer->height = static_cast<int32_t>(size.height.as_uint32_t());
43 native_window_buffer->width = static_cast<int32_t>(size.width.as_uint32_t());43 native_window_buffer->width = static_cast<int32_t>(size.width.as_uint32_t());
44 native_window_buffer->stride = stride.as_uint32_t() /44 native_window_buffer->stride = stride.as_uint32_t();
45 geom::bytes_per_pixel(buffer_pf);
46 native_window_buffer->usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER;45 native_window_buffer->usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER;
47 native_window_buffer->handle = native_handle.get();46 native_window_buffer->handle = native_handle.get();
48}47}
4948
=== modified file 'src/client/android/client_surface_interpreter.cpp'
--- src/client/android/client_surface_interpreter.cpp 2013-05-16 20:19:12 +0000
+++ src/client/android/client_surface_interpreter.cpp 2013-09-13 21:49:43 +0000
@@ -33,6 +33,7 @@
33{33{
34 auto buffer = surface.get_current_buffer();34 auto buffer = surface.get_current_buffer();
35 auto buffer_to_driver = buffer->native_buffer_handle();35 auto buffer_to_driver = buffer->native_buffer_handle();
36
36 buffer_to_driver->format = driver_pixel_format;37 buffer_to_driver->format = driver_pixel_format;
3738
38 return buffer_to_driver.get();39 return buffer_to_driver.get();
@@ -65,6 +66,8 @@
65 return driver_pixel_format;66 return driver_pixel_format;
66 case NATIVE_WINDOW_TRANSFORM_HINT:67 case NATIVE_WINDOW_TRANSFORM_HINT:
67 return 0;68 return 0;
69 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
70 return 2;
68 default:71 default:
69 throw std::runtime_error("driver requested unsupported query");72 throw std::runtime_error("driver requested unsupported query");
70 }73 }
7174
=== modified file 'src/shared/graphics/android/mir_native_window.cpp'
--- src/shared/graphics/android/mir_native_window.cpp 2013-05-20 15:29:28 +0000
+++ src/shared/graphics/android/mir_native_window.cpp 2013-09-13 21:49:43 +0000
@@ -128,16 +128,19 @@
128 return 0;128 return 0;
129}129}
130130
131int cancelBuffer_deprecated_static(struct ANativeWindow* /*window*/,131int cancelBuffer_deprecated_static(struct ANativeWindow* window,
132 struct ANativeWindowBuffer* /*buffer*/)132 struct ANativeWindowBuffer* buffer)
133{133{
134 return 0;134 return cancelBuffer_static(window, buffer, -1);
135}135}
136136
137int cancelBuffer_static(struct ANativeWindow* /*window*/,137int cancelBuffer_static(struct ANativeWindow* window,
138 struct ANativeWindowBuffer* /*buffer*/, int /*fence_fd*/)138 struct ANativeWindowBuffer* buffer, int fence_fd)
139{139{
140 return 0;140 auto ioctl_control = std::make_shared<IoctlControl>();
141 auto fence = std::make_shared<mga::SyncFence>(fence_fd, ioctl_control);
142 auto self = static_cast<mga::MirNativeWindow*>(window);
143 return self->cancelBuffer(buffer, fence);
141}144}
142145
143}146}
@@ -182,7 +185,15 @@
182 return 0;185 return 0;
183}186}
184187
185int mga::MirNativeWindow::queueBuffer(struct ANativeWindowBuffer* buffer, std::shared_ptr<mga::SyncObject> const& fence)188int mga::MirNativeWindow::queueBuffer(struct ANativeWindowBuffer* buffer,
189 std::shared_ptr<mga::SyncObject> const& fence)
190{
191 driver_interpreter->driver_returns_buffer(buffer, fence);
192 return 0;
193}
194
195int mga::MirNativeWindow::cancelBuffer(struct ANativeWindowBuffer* buffer,
196 std::shared_ptr<mga::SyncObject> const& fence)
186{197{
187 driver_interpreter->driver_returns_buffer(buffer, fence);198 driver_interpreter->driver_returns_buffer(buffer, fence);
188 return 0;199 return 0;
189200
=== modified file 'tests/integration-tests/client/test_client_render.cpp'
--- tests/integration-tests/client/test_client_render.cpp 2013-08-28 03:41:48 +0000
+++ tests/integration-tests/client/test_client_render.cpp 2013-09-13 21:49:43 +0000
@@ -29,6 +29,7 @@
2929
30#include "mir/frontend/communicator.h"30#include "mir/frontend/communicator.h"
3131
32#include <iostream>
32#include <gmock/gmock.h>33#include <gmock/gmock.h>
33#include <thread>34#include <thread>
34#include <hardware/gralloc.h>35#include <hardware/gralloc.h>
@@ -65,10 +66,6 @@
65 *surf = surface;66 *surf = surface;
66}67}
6768
68static void next_callback(MirSurface *, void*)
69{
70}
71
72static uint32_t pattern0 [2][2] = {{0x12345678, 0x23456789},69static uint32_t pattern0 [2][2] = {{0x12345678, 0x23456789},
73 {0x34567890, 0x45678901}};70 {0x34567890, 0x45678901}};
7471
@@ -76,6 +73,15 @@
76 {0xFF00FF00, 0xFF0000FF}};73 {0xFF00FF00, 0xFF0000FF}};
77struct TestClient74struct TestClient
78{75{
76 static MirPixelFormat select_format_for_visual_id(int visual_id)
77 {
78 if (visual_id == 5)
79 return mir_pixel_format_argb_8888;
80 if (visual_id == 1)
81 return mir_pixel_format_abgr_8888;
82
83 return mir_pixel_format_invalid;
84 }
7985
80 static void sig_handle(int)86 static void sig_handle(int)
81 {87 {
@@ -115,6 +121,8 @@
115 /* render pattern */121 /* render pattern */
116 mtd::DrawPatternCheckered<2,2> draw_pattern0(mt::pattern0);122 mtd::DrawPatternCheckered<2,2> draw_pattern0(mt::pattern0);
117 draw_pattern0.draw(graphics_region);123 draw_pattern0.draw(graphics_region);
124
125 mir_surface_swap_buffers_sync(surface);
118126
119 mir_wait_for(mir_surface_release(surface, &create_callback, &surface));127 mir_wait_for(mir_surface_release(surface, &create_callback, &surface));
120128
@@ -156,11 +164,13 @@
156 mtd::DrawPatternCheckered<2,2> draw_pattern0(mt::pattern0);164 mtd::DrawPatternCheckered<2,2> draw_pattern0(mt::pattern0);
157 draw_pattern0.draw(graphics_region);165 draw_pattern0.draw(graphics_region);
158166
159 mir_wait_for(mir_surface_swap_buffers(surface, &next_callback, (void*) NULL));167 mir_surface_swap_buffers_sync(surface);
160 mir_surface_get_graphics_region( surface, graphics_region.get());168 mir_surface_get_graphics_region( surface, graphics_region.get());
161 mtd::DrawPatternCheckered<2,2> draw_pattern1(mt::pattern1);169 mtd::DrawPatternCheckered<2,2> draw_pattern1(mt::pattern1);
162 draw_pattern1.draw(graphics_region);170 draw_pattern1.draw(graphics_region);
163171
172 mir_surface_swap_buffers_sync(surface);
173
164 mir_wait_for(mir_surface_release(surface, &create_callback, &surface));174 mir_wait_for(mir_surface_release(surface, &create_callback, &surface));
165175
166 /* release */176 /* release */
@@ -168,68 +178,62 @@
168 return 0;178 return 0;
169 }179 }
170180
181 static MirSurface* create_mir_surface(MirConnection * connection, EGLDisplay display, EGLConfig config)
182 {
183 int visual_id;
184 eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &visual_id);
185
186 /* make surface */
187 MirSurfaceParameters surface_parameters;
188 surface_parameters.name = "testsurface";
189 surface_parameters.width = test_width;
190 surface_parameters.height = test_height;
191 surface_parameters.pixel_format = select_format_for_visual_id(visual_id);
192 return mir_connection_create_surface_sync(connection, &surface_parameters);
193 }
194
171 static int render_accelerated()195 static int render_accelerated()
172 {196 {
173 if (signal(SIGCONT, sig_handle) == SIG_ERR)197 if (signal(SIGCONT, sig_handle) == SIG_ERR)
174 return -1;198 return -1;
175 pause();199 pause();
176200
177 /* only use C api */
178 MirConnection* connection = NULL;
179 MirSurface* surface;
180 MirSurfaceParameters surface_parameters;
181
182 /* establish connection. wait for server to come up */
183 while (connection == NULL)
184 {
185 mir_wait_for(mir_connect("./test_socket_surface", "test_renderer",
186 &connected_callback, &connection));
187 std::this_thread::sleep_for(std::chrono::milliseconds(10));
188 }
189 /* make surface */
190 surface_parameters.name = "testsurface";
191 surface_parameters.width = test_width;
192 surface_parameters.height = test_height;
193 surface_parameters.pixel_format = mir_pixel_format_abgr_8888;
194
195 mir_wait_for(mir_connection_create_surface(connection,
196 &surface_parameters,
197 &create_callback,
198 &surface));
199
200 int major, minor, n;201 int major, minor, n;
201 EGLDisplay disp;
202 EGLContext context;202 EGLContext context;
203 EGLSurface egl_surface;203 EGLSurface egl_surface;
204 EGLConfig egl_config;204 EGLConfig egl_config;
205 EGLint attribs[] = {205 EGLint attribs[] = {
206 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,206 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
207 EGL_GREEN_SIZE, 8,207 EGL_BUFFER_SIZE, 32,
208 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,208 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
209 EGL_NONE };209 EGL_NONE };
210 EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };210 EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
211211
212 EGLNativeDisplayType native_display = (EGLNativeDisplayType)mir_connection_get_egl_native_display(connection);212 auto connection = mir_connect_sync("./test_socket_surface", "test_renderer");
213 EGLNativeWindowType native_window = (EGLNativeWindowType) mir_surface_get_egl_native_window(surface);213
214214 auto native_display = mir_connection_get_egl_native_display(connection);
215 disp = eglGetDisplay(native_display);215 auto egl_display = eglGetDisplay(native_display);
216 eglInitialize(disp, &major, &minor);216 eglInitialize(egl_display, &major, &minor);
217217 eglChooseConfig(egl_display, attribs, &egl_config, 1, &n);
218 eglChooseConfig(disp, attribs, &egl_config, 1, &n);218
219 egl_surface = eglCreateWindowSurface(disp, egl_config, native_window, NULL);219 auto mir_surface = create_mir_surface(connection, egl_display, egl_config);
220 context = eglCreateContext(disp, egl_config, EGL_NO_CONTEXT, context_attribs);220 auto native_window = static_cast<EGLNativeWindowType>(
221 eglMakeCurrent(disp, egl_surface, egl_surface, context);221 mir_surface_get_egl_native_window(mir_surface));
222
223 egl_surface = eglCreateWindowSurface(egl_display, egl_config, native_window, NULL);
224 context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, context_attribs);
225 eglMakeCurrent(egl_display, egl_surface, egl_surface, context);
222226
223 glClearColor(1.0, 0.0, 0.0, 1.0);227 glClearColor(1.0, 0.0, 0.0, 1.0);
224 glClear(GL_COLOR_BUFFER_BIT);228 glClear(GL_COLOR_BUFFER_BIT);
225229
226 eglSwapBuffers(disp, egl_surface);230 eglSwapBuffers(egl_display, egl_surface);
227 mir_wait_for(mir_surface_release(surface, &create_callback, &surface));231
232 mir_surface_release_sync(mir_surface);
228233
229 /* release */234 /* release */
230 mir_connection_release(connection);235 mir_connection_release(connection);
231 return 0;236 return 0;
232
233 }237 }
234238
235 static int render_accelerated_double()239 static int render_accelerated_double()
@@ -238,68 +242,46 @@
238 return -1;242 return -1;
239 pause();243 pause();
240244
241 /* only use C api */
242 MirConnection* connection = NULL;
243 MirSurface* surface;
244 MirSurfaceParameters surface_parameters;
245
246 /* establish connection. wait for server to come up */
247 while (connection == NULL)
248 {
249 mir_wait_for(mir_connect("./test_socket_surface", "test_renderer",
250 &connected_callback, &connection));
251 std::this_thread::sleep_for(std::chrono::milliseconds(10));
252 }
253 /* make surface */
254 surface_parameters.name = "testsurface";
255 surface_parameters.width = test_width;
256 surface_parameters.height = test_height;
257 surface_parameters.pixel_format = mir_pixel_format_abgr_8888;
258
259 mir_wait_for(mir_connection_create_surface(connection,
260 &surface_parameters,
261 &create_callback,
262 &surface));
263
264 int major, minor, n;245 int major, minor, n;
265 EGLDisplay disp;
266 EGLContext context;246 EGLContext context;
267 EGLSurface egl_surface;247 EGLSurface egl_surface;
268 EGLConfig egl_config;248 EGLConfig egl_config;
269 EGLint attribs[] = {249 EGLint attribs[] = {
270 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,250 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
271 EGL_GREEN_SIZE, 8,251 EGL_BUFFER_SIZE, 32,
272 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,252 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
273 EGL_NONE };253 EGL_NONE };
274 EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };254 EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
275255
276 EGLNativeDisplayType native_display = (EGLNativeDisplayType)mir_connection_get_egl_native_display(connection);256 auto connection = mir_connect_sync("./test_socket_surface", "test_renderer");
277 EGLNativeWindowType native_window = (EGLNativeWindowType)mir_surface_get_egl_native_window(surface);257
278258 auto native_display = mir_connection_get_egl_native_display(connection);
279 disp = eglGetDisplay(native_display);259 auto egl_display = eglGetDisplay(native_display);
280 eglInitialize(disp, &major, &minor);260 eglInitialize(egl_display, &major, &minor);
281261 eglChooseConfig(egl_display, attribs, &egl_config, 1, &n);
282 eglChooseConfig(disp, attribs, &egl_config, 1, &n);262
283 egl_surface = eglCreateWindowSurface(disp, egl_config, native_window, NULL);263 auto mir_surface = create_mir_surface(connection, egl_display, egl_config);
284 context = eglCreateContext(disp, egl_config, EGL_NO_CONTEXT, context_attribs);264 auto native_window = static_cast<EGLNativeWindowType>(
285 eglMakeCurrent(disp, egl_surface, egl_surface, context);265 mir_surface_get_egl_native_window(mir_surface));
286266
267 egl_surface = eglCreateWindowSurface(egl_display, egl_config, native_window, NULL);
268 context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, context_attribs);
269 eglMakeCurrent(egl_display, egl_surface, egl_surface, context);
270
271 //draw red
287 glClearColor(1.0, 0.0, 0.0, 1.0);272 glClearColor(1.0, 0.0, 0.0, 1.0);
288 glClear(GL_COLOR_BUFFER_BIT);273 glClear(GL_COLOR_BUFFER_BIT);
289274 eglSwapBuffers(egl_display, egl_surface);
290 eglSwapBuffers(disp, egl_surface);275
291276 //draw green
292 glClearColor(0.0, 1.0, 0.0, 1.0);277 glClearColor(0.0, 1.0, 0.0, 1.0);
293 glClear(GL_COLOR_BUFFER_BIT);278 glClear(GL_COLOR_BUFFER_BIT);
294279 eglSwapBuffers(egl_display, egl_surface);
295 eglSwapBuffers(disp, egl_surface);280
296281 mir_surface_release_sync(mir_surface);
297 mir_wait_for(mir_surface_release(surface, &create_callback, &surface));282
298
299 /* release */
300 mir_connection_release(connection);283 mir_connection_release(connection);
301 return 0;284 return 0;
302
303 }285 }
304286
305 static int exit_function()287 static int exit_function()
@@ -311,13 +293,13 @@
311/* server code */293/* server code */
312struct StubServerGenerator : public mt::StubServerTool294struct StubServerGenerator : public mt::StubServerTool
313{295{
314 StubServerGenerator(std::shared_ptr<MirNativeBuffer> const& handle, int id)296 StubServerGenerator(std::shared_ptr<MirNativeBuffer> const& handle0,
315 : handle(handle),297 std::shared_ptr<MirNativeBuffer> const& handle1)
316 next_received(false),298 : handle0(handle0),
317 next_allowed(false),299 handle1(handle1),
318 handle_id(id)300 next_buffer_count(0),
301 buffer_count(2)
319 {302 {
320
321 }303 }
322304
323 void create_surface(google::protobuf::RpcController* /*controller*/,305 void create_surface(google::protobuf::RpcController* /*controller*/,
@@ -325,18 +307,21 @@
325 mir::protobuf::Surface* response,307 mir::protobuf::Surface* response,
326 google::protobuf::Closure* done)308 google::protobuf::Closure* done)
327 {309 {
328 response->mutable_id()->set_value(13); // TODO distinct numbers & tracking310 auto next_handle = get_next_handle();
311
312 response->mutable_id()->set_value(13); //surface id
329 response->set_width(test_width);313 response->set_width(test_width);
330 response->set_height(test_height);314 response->set_height(test_height);
315 surface_pf = geom::PixelFormat(request->pixel_format());
331 response->set_pixel_format(request->pixel_format());316 response->set_pixel_format(request->pixel_format());
332 response->mutable_buffer()->set_buffer_id(handle_id);317 response->mutable_buffer()->set_buffer_id(next_buffer_count % buffer_count);
333 response->mutable_buffer()->set_stride(handle->stride);318 response->mutable_buffer()->set_stride(next_handle->stride);
334319
335 response->mutable_buffer()->set_fds_on_side_channel(1);320 response->mutable_buffer()->set_fds_on_side_channel(1);
336 native_handle_t const* native_handle = handle->handle;321 native_handle_t const* native_handle = next_handle->handle;
337 for(auto i=0; i<native_handle->numFds; i++)322 for(auto i=0; i < native_handle->numFds; i++)
338 response->mutable_buffer()->add_fd(native_handle->data[i]);323 response->mutable_buffer()->add_fd(native_handle->data[i]);
339 for(auto i=0; i<native_handle->numInts; i++)324 for(auto i=0; i < native_handle->numInts; i++)
340 response->mutable_buffer()->add_data(native_handle->data[native_handle->numFds+i]);325 response->mutable_buffer()->add_data(native_handle->data[native_handle->numFds+i]);
341326
342 std::unique_lock<std::mutex> lock(guard);327 std::unique_lock<std::mutex> lock(guard);
@@ -352,22 +337,12 @@
352 ::mir::protobuf::Buffer* response,337 ::mir::protobuf::Buffer* response,
353 ::google::protobuf::Closure* done)338 ::google::protobuf::Closure* done)
354 {339 {
355 {340 auto next_handle = get_next_handle();
356 std::unique_lock<std::mutex> lk(next_guard);341 response->set_buffer_id(next_buffer_count % buffer_count);
357 next_received = true;
358 next_cv.notify_all();
359
360 while (!next_allowed) {
361 allow_cv.wait(lk);
362 }
363 next_allowed = false;
364 }
365
366 response->set_buffer_id(handle_id);
367342
368 response->set_fds_on_side_channel(1);343 response->set_fds_on_side_channel(1);
369 native_handle_t const* native_handle = handle->handle;344 native_handle_t const* native_handle = next_handle->handle;
370 response->set_stride(handle->stride);345 response->set_stride(next_handle->stride);
371 for(auto i=0; i<native_handle->numFds; i++)346 for(auto i=0; i<native_handle->numFds; i++)
372 response->add_fd(native_handle->data[i]);347 response->add_fd(native_handle->data[i]);
373 for(auto i=0; i<native_handle->numInts; i++)348 for(auto i=0; i<native_handle->numInts; i++)
@@ -376,41 +351,46 @@
376 done->Run();351 done->Run();
377 }352 }
378353
379 void wait_on_next_buffer()354 std::shared_ptr<MirNativeBuffer> get_next_handle()
380 {355 {
381 std::unique_lock<std::mutex> lk(next_guard);356 std::swap(handle0, handle1);
382 while (!next_received)357 next_buffer_count++;
383 next_cv.wait(lk);358 return handle0;
384 next_received = false;359 }
385 }360
386361 std::shared_ptr<MirNativeBuffer> second_to_last_returned()
387 void allow_next_continue()362 {
388 {363 return handle0;
389 std::unique_lock<std::mutex> lk(next_guard);364 }
390 next_allowed = true;365
391 allow_cv.notify_all();366 std::shared_ptr<MirNativeBuffer> last_returned()
392 lk.unlock();367 {
393 }368 return handle1;
394369 }
395 void set_handle(std::shared_ptr<MirNativeBuffer> const& pack, int id)370
396 {371 uint32_t red_value_for_surface()
397 handle = pack;372 {
398 handle_id = id;373 if ((surface_pf == geom::PixelFormat::abgr_8888) || (surface_pf == geom::PixelFormat::xbgr_8888))
374 return 0xFF0000FF;
375
376 if ((surface_pf == geom::PixelFormat::argb_8888) || (surface_pf == geom::PixelFormat::xrgb_8888))
377 return 0xFFFF0000;
378
379 return 0x0;
380 }
381
382 uint32_t green_value_for_surface()
383 {
384 return 0xFF00FF00;
399 }385 }
400386
401private:387private:
402 std::shared_ptr<MirNativeBuffer> handle;388 geom::PixelFormat surface_pf; //must be a 32 bit one;
403389 std::shared_ptr<MirNativeBuffer> handle0, handle1;
404 std::mutex next_guard;390 int next_buffer_count;
405 std::condition_variable next_cv;391 int const buffer_count;
406 std::condition_variable allow_cv;
407 bool next_received;
408 bool next_allowed;
409
410 int handle_id;
411};392};
412393
413
414}394}
415}395}
416396
@@ -429,11 +409,6 @@
429 mt::TestClient::render_double,409 mt::TestClient::render_double,
430 mt::TestClient::exit_function);410 mt::TestClient::exit_function);
431411
432 second_render_with_same_buffer_client_process
433 = mtf::fork_and_run_in_a_different_process(
434 mt::TestClient::render_double,
435 mt::TestClient::exit_function);
436
437 render_accelerated_process412 render_accelerated_process
438 = mtf::fork_and_run_in_a_different_process(413 = mtf::fork_and_run_in_a_different_process(
439 mt::TestClient::render_accelerated,414 mt::TestClient::render_accelerated,
@@ -448,22 +423,22 @@
448 void SetUp() {423 void SetUp() {
449 ASSERT_FALSE(mtd::is_surface_flinger_running());424 ASSERT_FALSE(mtd::is_surface_flinger_running());
450425
451 size = geom::Size{test_width, test_height};426 auto size = geom::Size{test_width, test_height};
452 pf = geom::PixelFormat::abgr_8888;427 auto pf = geom::PixelFormat::argb_8888;
428
429 buffer_converter = std::make_shared<mtd::TestGrallocMapper>();
453430
454 auto initializer = std::make_shared<mg::NullBufferInitializer>();431 auto initializer = std::make_shared<mg::NullBufferInitializer>();
455 allocator = std::make_shared<mga::AndroidGraphicBufferAllocator> (initializer);432 auto allocator = std::make_shared<mga::AndroidGraphicBufferAllocator> (initializer);
456 mg::BufferProperties properties(size, pf, mg::BufferUsage::hardware);433 mg::BufferProperties properties(size, pf, mg::BufferUsage::hardware);
457 android_buffer = allocator->alloc_buffer(properties);434 android_buffer0 = allocator->alloc_buffer(properties);
458 second_android_buffer = allocator->alloc_buffer(properties);435 android_buffer1 = allocator->alloc_buffer(properties);
459436
460 buffer_converter = std::make_shared<mtd::TestGrallocMapper>();437 auto handle0 = android_buffer0->native_buffer_handle();
461438 auto handle1 = android_buffer1->native_buffer_handle();
462 handle = android_buffer->native_buffer_handle();
463 second_handle = second_android_buffer->native_buffer_handle();
464439
465 /* start a server */440 /* start a server */
466 mock_server = std::make_shared<mt::StubServerGenerator>(handle, 14);441 mock_server = std::make_shared<mt::StubServerGenerator>(handle0, handle1);
467 test_server = std::make_shared<mt::TestProtobufServer>("./test_socket_surface", mock_server);442 test_server = std::make_shared<mt::TestProtobufServer>("./test_socket_surface", mock_server);
468 test_server->comm->start();443 test_server->comm->start();
469 }444 }
@@ -478,29 +453,19 @@
478 std::shared_ptr<mt::TestProtobufServer> test_server;453 std::shared_ptr<mt::TestProtobufServer> test_server;
479 std::shared_ptr<mt::StubServerGenerator> mock_server;454 std::shared_ptr<mt::StubServerGenerator> mock_server;
480455
481 geom::Size size;
482 geom::PixelFormat pf;
483 mg::BufferID id1;
484 mg::BufferID id2;
485 std::shared_ptr<mtd::TestGrallocMapper> buffer_converter;456 std::shared_ptr<mtd::TestGrallocMapper> buffer_converter;
486 std::shared_ptr<mtf::Process> client_process;457 std::shared_ptr<mtf::Process> client_process;
487458
488 std::shared_ptr<MirNativeBuffer> handle;459 std::shared_ptr<mg::Buffer> android_buffer0;
489 std::shared_ptr<MirNativeBuffer> second_handle;460 std::shared_ptr<mg::Buffer> android_buffer1;
490
491 std::shared_ptr<mg::Buffer> android_buffer;
492 std::shared_ptr<mg::Buffer> second_android_buffer;
493 std::shared_ptr<mga::AndroidGraphicBufferAllocator> allocator;
494461
495 static std::shared_ptr<mtf::Process> render_single_client_process;462 static std::shared_ptr<mtf::Process> render_single_client_process;
496 static std::shared_ptr<mtf::Process> render_double_client_process;463 static std::shared_ptr<mtf::Process> render_double_client_process;
497 static std::shared_ptr<mtf::Process> second_render_with_same_buffer_client_process;
498 static std::shared_ptr<mtf::Process> render_accelerated_process;464 static std::shared_ptr<mtf::Process> render_accelerated_process;
499 static std::shared_ptr<mtf::Process> render_accelerated_process_double;465 static std::shared_ptr<mtf::Process> render_accelerated_process_double;
500};466};
501std::shared_ptr<mtf::Process> TestClientIPCRender::render_single_client_process;467std::shared_ptr<mtf::Process> TestClientIPCRender::render_single_client_process;
502std::shared_ptr<mtf::Process> TestClientIPCRender::render_double_client_process;468std::shared_ptr<mtf::Process> TestClientIPCRender::render_double_client_process;
503std::shared_ptr<mtf::Process> TestClientIPCRender::second_render_with_same_buffer_client_process;
504std::shared_ptr<mtf::Process> TestClientIPCRender::render_accelerated_process;469std::shared_ptr<mtf::Process> TestClientIPCRender::render_accelerated_process;
505std::shared_ptr<mtf::Process> TestClientIPCRender::render_accelerated_process_double;470std::shared_ptr<mtf::Process> TestClientIPCRender::render_accelerated_process_double;
506471
@@ -514,8 +479,8 @@
514 EXPECT_TRUE(render_single_client_process->wait_for_termination().succeeded());479 EXPECT_TRUE(render_single_client_process->wait_for_termination().succeeded());
515480
516 /* check content */481 /* check content */
517 auto region = buffer_converter->graphic_region_from_handle(handle);482 auto last_handle = mock_server->last_returned();
518 EXPECT_TRUE(rendered_pattern.check(region));483 EXPECT_TRUE(rendered_pattern.check(buffer_converter->graphic_region_from_handle(last_handle)));
519}484}
520485
521TEST_F(TestClientIPCRender, test_render_double)486TEST_F(TestClientIPCRender, test_render_double)
@@ -525,80 +490,42 @@
525 /* activate client */490 /* activate client */
526 render_double_client_process->cont();491 render_double_client_process->cont();
527492
528 /* wait for next buffer */493 /* wait for client to finish */
529 mock_server->wait_on_next_buffer();494 EXPECT_TRUE(render_double_client_process->wait_for_termination().succeeded());
530 auto region = buffer_converter->graphic_region_from_handle(handle);495
496 auto second_to_last_handle = mock_server->second_to_last_returned();
497 auto region = buffer_converter->graphic_region_from_handle(second_to_last_handle);
531 EXPECT_TRUE(rendered_pattern0.check(region));498 EXPECT_TRUE(rendered_pattern0.check(region));
532499
533 mock_server->set_handle(second_handle, 15);500 auto last_handle = mock_server->last_returned();
534 mock_server->allow_next_continue();501 auto second_region = buffer_converter->graphic_region_from_handle(last_handle);
535
536 /* wait for client to finish */
537 EXPECT_TRUE(render_double_client_process->wait_for_termination().succeeded());
538
539 auto second_region = buffer_converter->graphic_region_from_handle(second_handle);
540 EXPECT_TRUE(rendered_pattern1.check(second_region));502 EXPECT_TRUE(rendered_pattern1.check(second_region));
541}503}
542504
543TEST_F(TestClientIPCRender, test_second_render_with_same_buffer)
544{
545 mtd::DrawPatternCheckered<2,2> rendered_pattern(mt::pattern1);
546 /* activate client */
547 second_render_with_same_buffer_client_process->cont();
548
549 /* wait for next buffer */
550 mock_server->wait_on_next_buffer();
551 mock_server->allow_next_continue();
552
553 /* wait for client to finish */
554 EXPECT_TRUE(second_render_with_same_buffer_client_process->wait_for_termination().succeeded());
555
556 /* check content */
557 auto region = buffer_converter->graphic_region_from_handle(handle);
558 EXPECT_TRUE(rendered_pattern.check(region));
559}
560
561TEST_F(TestClientIPCRender, test_accelerated_render)505TEST_F(TestClientIPCRender, test_accelerated_render)
562{506{
563 mtd::DrawPatternSolid red_pattern(0xFF0000FF);
564
565 /* activate client */
566 render_accelerated_process->cont();507 render_accelerated_process->cont();
567
568 /* wait for next buffer */
569 mock_server->wait_on_next_buffer();
570 mock_server->allow_next_continue();
571
572 /* wait for client to finish */
573 EXPECT_TRUE(render_accelerated_process->wait_for_termination().succeeded());508 EXPECT_TRUE(render_accelerated_process->wait_for_termination().succeeded());
574509
575 /* check content */510 /* check content */
576 auto region = buffer_converter->graphic_region_from_handle(handle);511 mtd::DrawPatternSolid red_pattern(mock_server->red_value_for_surface());
577 EXPECT_TRUE(red_pattern.check(region));512 auto last_handle = mock_server->last_returned();
513 EXPECT_TRUE(red_pattern.check(buffer_converter->graphic_region_from_handle(last_handle)));
578}514}
579515
580TEST_F(TestClientIPCRender, test_accelerated_render_double)516TEST_F(TestClientIPCRender, test_accelerated_render_double)
581{517{
582 mtd::DrawPatternSolid red_pattern(0xFF0000FF);
583 mtd::DrawPatternSolid green_pattern(0xFF00FF00);
584 /* activate client */
585 render_accelerated_process_double->cont();518 render_accelerated_process_double->cont();
586
587 /* wait for next buffer */
588 mock_server->wait_on_next_buffer();
589 mock_server->set_handle(second_handle, 15);
590 mock_server->allow_next_continue();
591
592 mock_server->wait_on_next_buffer();
593 mock_server->allow_next_continue();
594
595 /* wait for client to finish */
596 EXPECT_TRUE(render_accelerated_process_double->wait_for_termination().succeeded());519 EXPECT_TRUE(render_accelerated_process_double->wait_for_termination().succeeded());
597520
598 /* check content */521 /* check content */
599 auto region = buffer_converter->graphic_region_from_handle(handle);522 mtd::DrawPatternSolid red_pattern(mock_server->red_value_for_surface());
523 auto second_to_last_handle = mock_server->second_to_last_returned();
524 auto region = buffer_converter->graphic_region_from_handle(second_to_last_handle);
600 EXPECT_TRUE(red_pattern.check(region));525 EXPECT_TRUE(red_pattern.check(region));
601526
602 auto second_region = buffer_converter->graphic_region_from_handle(second_handle);527 mtd::DrawPatternSolid green_pattern(mock_server->green_value_for_surface());
528 auto last_handle = mock_server->last_returned();
529 auto second_region = buffer_converter->graphic_region_from_handle(last_handle);
603 EXPECT_TRUE(green_pattern.check(second_region));530 EXPECT_TRUE(green_pattern.check(second_region));
604}531}
605532
=== modified file 'tests/unit-tests/client/android/test_android_native_window.cpp'
--- tests/unit-tests/client/android/test_android_native_window.cpp 2013-05-16 20:07:39 +0000
+++ tests/unit-tests/client/android/test_android_native_window.cpp 2013-09-13 21:49:43 +0000
@@ -288,3 +288,17 @@
288 auto ret = window->dequeueBuffer(window.get(), &tmp, &fencefd);288 auto ret = window->dequeueBuffer(window.get(), &tmp, &fencefd);
289 EXPECT_EQ(0, ret);289 EXPECT_EQ(0, ret);
290}290}
291
292TEST_F(AndroidNativeWindowTest, native_window_cancel_hook_behavior)
293{
294 using namespace testing;
295 ANativeWindowBuffer buffer;
296 int fence_fd = 33;
297
298 EXPECT_CALL(*mock_driver_interpreter, driver_returns_buffer(&buffer, _))
299 .Times(1);
300
301 std::shared_ptr<ANativeWindow> window = std::make_shared<mga::MirNativeWindow>(mock_driver_interpreter);
302 auto rc = window->cancelBuffer(window.get(), &buffer, fence_fd);
303 EXPECT_EQ(0, rc);
304}
291305
=== modified file 'tests/unit-tests/client/android/test_client_surface_interpreter.cpp'
--- tests/unit-tests/client/android/test_client_surface_interpreter.cpp 2013-07-01 15:10:36 +0000
+++ tests/unit-tests/client/android/test_client_surface_interpreter.cpp 2013-09-13 21:49:43 +0000
@@ -227,3 +227,19 @@
227227
228 EXPECT_EQ(surf_params.height, height);228 EXPECT_EQ(surf_params.height, height);
229}229}
230
231/* this is query key is a bit confusing from the system/window.h description.
232 what it means is the minimum number of buffers that the server reserves for its own use in steady
233 state. The drivers consider 'steady state' to begin after the first call to queueBuffer.
234 So, for instance, if a driver requires 3 buffers to run at steady state, and the server needs
235 to keep 2 buffers on hand at all time, the driver might dequeue 5 buffers, then cancel those 5 buffers.
236 After the first call to queueBuffer however, the client may never own more than the number it has
237 reserved (in this case, 3 buffers) */
238TEST_F(AndroidInterpreterTest, native_window_minimum_undequeued_query_hook)
239{
240 testing::NiceMock<MockMirSurface> mock_surface{surf_params};
241 mcla::ClientSurfaceInterpreter interpreter(mock_surface);
242
243 auto num_buffers = interpreter.driver_requests_info(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS);
244 EXPECT_EQ(2, num_buffers);
245}

Subscribers

People subscribed via source and target branches