source: mainline/uspace/lib/ipcgfx/src/server.c@ b7eea3c9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b7eea3c9 was b7eea3c9, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Identify places where we should free resources for ill-behaved clients

  • Property mode set to 100644
File size: 9.3 KB
RevLine 
[aac5069]1/*
2 * Copyright (c) 2019 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libipcgfx
30 * @{
31 */
32/**
33 * @file GFX IPC server
34 *
35 * Serve a graphics context via HelenOS IPC.
36 */
37
[0008c0f]38#include <as.h>
[aac5069]39#include <errno.h>
[0008c0f]40#include <gfx/bitmap.h>
[aac5069]41#include <gfx/color.h>
42#include <gfx/render.h>
43#include <ipc/bd.h>
44#include <ipcgfx/ipc/gc.h>
45#include <ipcgfx/server.h>
46#include <stdint.h>
[0008c0f]47#include <stdlib.h>
[c8cf261]48#include <stdio.h>
49
[0008c0f]50#include "../private/server.h"
51
52static ipc_gc_srv_bitmap_t *gc_bitmap_lookup(ipc_gc_srv_t *, sysarg_t);
[aac5069]53
[0008c0f]54static void gc_set_rgb_color_srv(ipc_gc_srv_t *srvgc, ipc_call_t *call)
[aac5069]55{
56 uint16_t r, g, b;
57 gfx_color_t *color;
58 errno_t rc;
59
60 r = ipc_get_arg1(call);
61 g = ipc_get_arg2(call);
62 b = ipc_get_arg3(call);
63
64 rc = gfx_color_new_rgb_i16(r, g, b, &color);
65 if (rc != EOK) {
66 async_answer_0(call, ENOMEM);
67 return;
68 }
69
[0008c0f]70 rc = gfx_set_color(srvgc->gc, color);
[aac5069]71 async_answer_0(call, rc);
72}
73
[0008c0f]74static void gc_fill_rect_srv(ipc_gc_srv_t *srvgc, ipc_call_t *call)
[aac5069]75{
76 gfx_rect_t rect;
77 errno_t rc;
78
79 rect.p0.x = ipc_get_arg1(call);
80 rect.p0.y = ipc_get_arg2(call);
81 rect.p1.x = ipc_get_arg3(call);
82 rect.p1.y = ipc_get_arg4(call);
83
[0008c0f]84 rc = gfx_fill_rect(srvgc->gc, &rect);
85 async_answer_0(call, rc);
86}
87
88static void gc_bitmap_create_srv(ipc_gc_srv_t *srvgc, ipc_call_t *icall)
89{
90 gfx_bitmap_params_t params;
91 gfx_bitmap_alloc_t alloc;
92 gfx_bitmap_t *bitmap;
93 gfx_coord2_t dim;
94 ipc_gc_srv_bitmap_t *srvbmp = NULL;
95 ipc_call_t call;
96 size_t size;
97 unsigned int flags;
98 void *pixels;
99 errno_t rc;
100
101 if (!async_data_write_receive(&call, &size)) {
102 async_answer_0(&call, EREFUSED);
103 async_answer_0(icall, EREFUSED);
104 return;
105 }
106
107 if (size != sizeof(gfx_bitmap_params_t)) {
108 async_answer_0(&call, EINVAL);
109 async_answer_0(icall, EINVAL);
110 return;
111 }
112
113 rc = async_data_write_finalize(&call, &params, size);
114 if (rc != EOK) {
115 async_answer_0(&call, rc);
116 async_answer_0(icall, rc);
117 return;
118 }
119
120 /* Bitmap dimensions */
121 gfx_coord2_subtract(&params.rect.p1, &params.rect.p0, &dim);
122
123 if (!async_share_out_receive(&call, &size, &flags)) {
124 async_answer_0(icall, EINVAL);
125 return;
126 }
127
128 /* Check size */
129 if (size != PAGES2SIZE(SIZE2PAGES(dim.x * dim.y * sizeof(uint32_t)))) {
130 async_answer_0(icall, EINVAL);
131 return;
132 }
133
134 rc = async_share_out_finalize(&call, &pixels);
135 if (rc != EOK || pixels == AS_MAP_FAILED) {
136 async_answer_0(icall, ENOMEM);
137 return;
138 }
139
140 alloc.pitch = dim.x * sizeof(uint32_t);
141 alloc.off0 = 0;
142 alloc.pixels = pixels;
143
144 srvbmp = calloc(1, sizeof(ipc_gc_srv_bitmap_t));
145 if (srvbmp == NULL) {
146 as_area_destroy(pixels);
147 async_answer_0(icall, ENOMEM);
148 return;
149 }
150
151 rc = gfx_bitmap_create(srvgc->gc, &params, &alloc, &bitmap);
152 if (rc != EOK) {
153 free(srvbmp);
154 as_area_destroy(pixels);
155 async_answer_0(icall, rc);
156 return;
157 }
158
159 srvbmp->srvgc = srvgc;
160 list_append(&srvbmp->lbitmaps, &srvgc->bitmaps);
161 srvbmp->bmp = bitmap;
162 srvbmp->bmp_id = srvgc->next_bmp_id++;
[bf22cb78]163 printf("gc_bitmap_create_srv: storing bmp_id=%u\n",
164 (unsigned) srvbmp->bmp_id);
[0008c0f]165
[5e3e42c7]166 /* We created the memory area by sharing it in */
167 srvbmp->myalloc = true;
168 srvbmp->pixels = pixels;
169
[0008c0f]170 async_answer_1(icall, EOK, srvbmp->bmp_id);
171}
172
[afcf704]173static void gc_bitmap_create_doutput_srv(ipc_gc_srv_t *srvgc, ipc_call_t *icall)
174{
175 gfx_bitmap_params_t params;
176 gfx_bitmap_alloc_t alloc;
177 gfx_bitmap_t *bitmap;
178 gfx_coord2_t dim;
179 ipc_gc_srv_bitmap_t *srvbmp = NULL;
180 ipc_call_t call;
181 size_t size;
182 errno_t rc;
183
184 if (!async_data_write_receive(&call, &size)) {
185 async_answer_0(&call, EREFUSED);
186 async_answer_0(icall, EREFUSED);
187 return;
188 }
189
190 if (size != sizeof(gfx_bitmap_params_t)) {
191 async_answer_0(&call, EINVAL);
192 async_answer_0(icall, EINVAL);
193 return;
194 }
195
196 rc = async_data_write_finalize(&call, &params, size);
197 if (rc != EOK) {
198 async_answer_0(&call, rc);
199 async_answer_0(icall, rc);
200 return;
201 }
202
203 /* Bitmap dimensions */
204 gfx_coord2_subtract(&params.rect.p1, &params.rect.p0, &dim);
205
206 if (!async_share_in_receive(&call, &size)) {
207 async_answer_0(icall, EINVAL);
208 return;
209 }
210
211 /* Check size */
212 if (size != PAGES2SIZE(SIZE2PAGES(dim.x * dim.y * sizeof(uint32_t)))) {
213 async_answer_0(&call, EINVAL);
214 async_answer_0(icall, EINVAL);
215 return;
216 }
217
218 rc = gfx_bitmap_create(srvgc->gc, &params, NULL, &bitmap);
219 if (rc != EOK) {
220 async_answer_0(&call, rc);
221 async_answer_0(icall, rc);
222 return;
223 }
224
225 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
226 if (rc != EOK) {
227 gfx_bitmap_destroy(bitmap);
228 async_answer_0(&call, rc);
229 async_answer_0(icall, rc);
230 return;
231 }
232
233 rc = async_share_in_finalize(&call, alloc.pixels, AS_AREA_READ |
234 AS_AREA_WRITE | AS_AREA_CACHEABLE);
235 if (rc != EOK) {
236 gfx_bitmap_destroy(bitmap);
237 async_answer_0(icall, EIO);
238 return;
239 }
240
241 srvbmp = calloc(1, sizeof(ipc_gc_srv_bitmap_t));
242 if (srvbmp == NULL) {
243 gfx_bitmap_destroy(bitmap);
244 async_answer_0(icall, ENOMEM);
245 return;
246 }
247
248 srvbmp->srvgc = srvgc;
249 list_append(&srvbmp->lbitmaps, &srvgc->bitmaps);
250 srvbmp->bmp = bitmap;
251 srvbmp->bmp_id = srvgc->next_bmp_id++;
[5e3e42c7]252
253 /* Area allocated by backing GC, we just shared it out */
254 srvbmp->myalloc = false;
255 srvbmp->pixels = alloc.pixels; // Not really needed
256
[afcf704]257 printf("gc_bitmap_create_doutput_srv: storing bmp_id=%u\n",
258 (unsigned) srvbmp->bmp_id);
259
260 async_answer_1(icall, EOK, srvbmp->bmp_id);
261}
262
[0008c0f]263static void gc_bitmap_destroy_srv(ipc_gc_srv_t *srvgc, ipc_call_t *call)
264{
265 sysarg_t bmp_id;
266 ipc_gc_srv_bitmap_t *bitmap;
267 errno_t rc;
268
269 bmp_id = ipc_get_arg1(call);
270
271 bitmap = gc_bitmap_lookup(srvgc, bmp_id);
272 if (bitmap == NULL) {
273 async_answer_0(call, ENOENT);
274 return;
275 }
276
277 rc = gfx_bitmap_destroy(bitmap->bmp);
278 if (rc != EOK) {
279 async_answer_0(call, rc);
280 return;
281 }
282
[5e3e42c7]283 if (bitmap->myalloc)
284 as_area_destroy(bitmap->pixels);
285
[0008c0f]286 list_remove(&bitmap->lbitmaps);
287 free(bitmap);
288
[aac5069]289 async_answer_0(call, rc);
290}
291
[0008c0f]292static void gc_bitmap_render_srv(ipc_gc_srv_t *srvgc, ipc_call_t *icall)
293{
294 ipc_gc_srv_bitmap_t *bitmap;
295 sysarg_t bmp_id;
296 gfx_rect_t srect;
297 gfx_coord2_t offs;
298 ipc_call_t call;
299 size_t size;
300 errno_t rc;
301
302 if (!async_data_write_receive(&call, &size)) {
303 async_answer_0(&call, EREFUSED);
304 async_answer_0(icall, EREFUSED);
305 return;
306 }
307
308 if (size != sizeof(gfx_rect_t)) {
309 async_answer_0(&call, EINVAL);
310 async_answer_0(icall, EINVAL);
311 return;
312 }
313
314 rc = async_data_write_finalize(&call, &srect, size);
315 if (rc != EOK) {
316 async_answer_0(&call, rc);
317 async_answer_0(icall, rc);
318 return;
319 }
320
321 bmp_id = ipc_get_arg1(icall);
322 offs.x = ipc_get_arg2(icall);
323 offs.y = ipc_get_arg3(icall);
324
325 bitmap = gc_bitmap_lookup(srvgc, bmp_id);
326 if (bitmap == NULL) {
327 async_answer_0(icall, ENOENT);
328 return;
329 }
330
331 rc = gfx_bitmap_render(bitmap->bmp, &srect, &offs);
332 async_answer_0(icall, rc);
333}
334
[aac5069]335errno_t gc_conn(ipc_call_t *icall, gfx_context_t *gc)
336{
[0008c0f]337 ipc_gc_srv_t srvgc;
338
[aac5069]339 /* Accept the connection */
340 async_accept_0(icall);
341
[c8cf261]342 printf("gc_conn: accepted connection\n");
[0008c0f]343 srvgc.gc = gc;
344 list_initialize(&srvgc.bitmaps);
345 srvgc.next_bmp_id = 1;
[c8cf261]346
[aac5069]347 while (true) {
348 ipc_call_t call;
349 async_get_call(&call);
350 sysarg_t method = ipc_get_imethod(&call);
351
352 if (!method) {
353 /* The other side has hung up */
354 async_answer_0(&call, EOK);
355 break;
356 }
357
358 switch (method) {
359 case GC_SET_RGB_COLOR:
[0008c0f]360 gc_set_rgb_color_srv(&srvgc, &call);
[aac5069]361 break;
362 case GC_FILL_RECT:
[0008c0f]363 gc_fill_rect_srv(&srvgc, &call);
[aac5069]364 break;
[0008c0f]365 case GC_BITMAP_CREATE:
366 gc_bitmap_create_srv(&srvgc, &call);
367 break;
[afcf704]368 case GC_BITMAP_CREATE_DOUTPUT:
369 gc_bitmap_create_doutput_srv(&srvgc, &call);
370 break;
[0008c0f]371 case GC_BITMAP_DESTROY:
372 gc_bitmap_destroy_srv(&srvgc, &call);
373 break;
374 case GC_BITMAP_RENDER:
375 gc_bitmap_render_srv(&srvgc, &call);
376 break;
[aac5069]377 default:
378 async_answer_0(&call, EINVAL);
[48f7e47]379 break;
[aac5069]380 }
381 }
382
[b7eea3c9]383 // TODO: Destroy all remaining bitmaps (+ emit warning?)
[aac5069]384 return EOK;
385}
386
[0008c0f]387static ipc_gc_srv_bitmap_t *gc_bitmap_lookup(ipc_gc_srv_t *srvgc,
388 sysarg_t bmp_id)
389{
390 link_t *link;
391 ipc_gc_srv_bitmap_t *bmp;
392
393 link = list_first(&srvgc->bitmaps);
394 while (link != NULL) {
395 bmp = list_get_instance(link, ipc_gc_srv_bitmap_t, lbitmaps);
396 if (bmp->bmp_id == bmp_id)
397 return bmp;
398 link = list_next(link, &srvgc->bitmaps);
399 }
400
401 return NULL;
402}
403
[aac5069]404/** @}
405 */
Note: See TracBrowser for help on using the repository browser.