source: mainline/uspace/lib/memgfx/src/xlategc.c

Last change on this file was 8ce56a6, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Translate window rendering in console/SSR with translation GC

In full-screen mode (such as text/console) and server-side rendering
we need other mechanism than memory GC to translate the coordinates
while rendering. We use a translation GC (xlategc).

Note the extensively elaborate testing of this very simple GC seems
quite overboard. At least the very elaborate test_gc_t could be hoisted
into a library and used wherever a test GC is required.

  • Property mode set to 100644
File size: 8.6 KB
Line 
1/*
2 * Copyright (c) 2021 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 libmemgfx
30 * @{
31 */
32/**
33 * @file Translating graphics context
34 *
35 * A graphics context that just forwards all operations to another graphics
36 * context with an offset.
37 */
38
39#include <assert.h>
40#include <gfx/color.h>
41#include <gfx/context.h>
42#include <gfx/cursor.h>
43#include <gfx/render.h>
44#include <memgfx/xlategc.h>
45#include <stdlib.h>
46#include "../private/xlategc.h"
47
48static errno_t xlate_gc_set_clip_rect(void *, gfx_rect_t *);
49static errno_t xlate_gc_set_color(void *, gfx_color_t *);
50static errno_t xlate_gc_fill_rect(void *, gfx_rect_t *);
51static errno_t xlate_gc_update(void *);
52static errno_t xlate_gc_bitmap_create(void *, gfx_bitmap_params_t *,
53 gfx_bitmap_alloc_t *, void **);
54static errno_t xlate_gc_bitmap_destroy(void *);
55static errno_t xlate_gc_bitmap_render(void *, gfx_rect_t *, gfx_coord2_t *);
56static errno_t xlate_gc_bitmap_get_alloc(void *, gfx_bitmap_alloc_t *);
57static errno_t xlate_gc_cursor_get_pos(void *, gfx_coord2_t *);
58static errno_t xlate_gc_cursor_set_pos(void *, gfx_coord2_t *);
59static errno_t xlate_gc_cursor_set_visible(void *, bool);
60
61gfx_context_ops_t xlate_gc_ops = {
62 .set_clip_rect = xlate_gc_set_clip_rect,
63 .set_color = xlate_gc_set_color,
64 .fill_rect = xlate_gc_fill_rect,
65 .update = xlate_gc_update,
66 .bitmap_create = xlate_gc_bitmap_create,
67 .bitmap_destroy = xlate_gc_bitmap_destroy,
68 .bitmap_render = xlate_gc_bitmap_render,
69 .bitmap_get_alloc = xlate_gc_bitmap_get_alloc,
70 .cursor_get_pos = xlate_gc_cursor_get_pos,
71 .cursor_set_pos = xlate_gc_cursor_set_pos,
72 .cursor_set_visible = xlate_gc_cursor_set_visible
73};
74
75/** Set clipping rectangle on translating GC.
76 *
77 * @param arg Translating GC
78 * @param rect Rectangle
79 *
80 * @return EOK on success or an error code
81 */
82static errno_t xlate_gc_set_clip_rect(void *arg, gfx_rect_t *rect)
83{
84 xlate_gc_t *xgc = (xlate_gc_t *) arg;
85 gfx_rect_t crect;
86
87 if (rect != NULL) {
88 gfx_rect_translate(&xgc->off, rect, &crect);
89 return gfx_set_clip_rect(xgc->bgc, &crect);
90 } else {
91 return gfx_set_clip_rect(xgc->bgc, NULL);
92 }
93}
94
95/** Set color on translating GC.
96 *
97 * Set drawing color on translating GC.
98 *
99 * @param arg Translating GC
100 * @param color Color
101 *
102 * @return EOK on success or an error code
103 */
104static errno_t xlate_gc_set_color(void *arg, gfx_color_t *color)
105{
106 xlate_gc_t *xgc = (xlate_gc_t *) arg;
107
108 return gfx_set_color(xgc->bgc, color);
109}
110
111/** Fill rectangle on translating GC.
112 *
113 * @param arg Translating GC
114 * @param rect Rectangle
115 *
116 * @return EOK on success or an error code
117 */
118static errno_t xlate_gc_fill_rect(void *arg, gfx_rect_t *rect)
119{
120 xlate_gc_t *xgc = (xlate_gc_t *) arg;
121 gfx_rect_t frect;
122
123 gfx_rect_translate(&xgc->off, rect, &frect);
124 return gfx_fill_rect(xgc->bgc, &frect);
125}
126
127/** Update translating GC.
128 *
129 * @param arg Translating GC
130 *
131 * @return EOK on success or an error code
132 */
133static errno_t xlate_gc_update(void *arg)
134{
135 xlate_gc_t *xgc = (xlate_gc_t *) arg;
136
137 return gfx_update(xgc->bgc);
138}
139
140/** Create translating GC.
141 *
142 * Create graphics context that renders into another GC with offset.
143 *
144 * @param off Offset
145 * @param bgc Backing GC
146 * @param rgc Place to store pointer to new translating GC
147 *
148 * @return EOK on success or an error code
149 */
150errno_t xlate_gc_create(gfx_coord2_t *off, gfx_context_t *bgc,
151 xlate_gc_t **rgc)
152{
153 xlate_gc_t *xgc = NULL;
154 gfx_context_t *gc = NULL;
155 errno_t rc;
156
157 xgc = calloc(1, sizeof(xlate_gc_t));
158 if (xgc == NULL) {
159 rc = ENOMEM;
160 goto error;
161 }
162
163 rc = gfx_context_new(&xlate_gc_ops, xgc, &gc);
164 if (rc != EOK)
165 goto error;
166
167 xgc->bgc = bgc;
168 xgc->gc = gc;
169 xgc->off = *off;
170
171 *rgc = xgc;
172 return EOK;
173error:
174 if (xgc != NULL)
175 free(xgc);
176 gfx_context_delete(gc);
177 return rc;
178}
179
180/** Delete translating GC.
181 *
182 * @param xgc Translating GC
183 */
184errno_t xlate_gc_delete(xlate_gc_t *xgc)
185{
186 errno_t rc;
187
188 rc = gfx_context_delete(xgc->gc);
189 if (rc != EOK)
190 return rc;
191
192 free(xgc);
193 return EOK;
194}
195
196/** Get generic graphic context from translating GC.
197 *
198 * @param xgc Translating GC
199 * @return Graphic context
200 */
201gfx_context_t *xlate_gc_get_ctx(xlate_gc_t *xgc)
202{
203 return xgc->gc;
204}
205
206/** Create bitmap in translating GC.
207 *
208 * @param arg Translating GC
209 * @param params Bitmap params
210 * @param alloc Bitmap allocation info or @c NULL
211 * @param rbm Place to store pointer to new bitmap
212 * @return EOK on success or an error code
213 */
214errno_t xlate_gc_bitmap_create(void *arg, gfx_bitmap_params_t *params,
215 gfx_bitmap_alloc_t *alloc, void **rbm)
216{
217 xlate_gc_t *xgc = (xlate_gc_t *) arg;
218 xlate_gc_bitmap_t *xbm;
219 gfx_bitmap_t *bm = NULL;
220 errno_t rc;
221
222 xbm = calloc(1, sizeof(xlate_gc_bitmap_t));
223 if (xbm == NULL)
224 return ENOMEM;
225
226 rc = gfx_bitmap_create(xgc->bgc, params, alloc, &bm);
227 if (rc != EOK) {
228 free(xbm);
229 return rc;
230 }
231
232 xbm->xgc = xgc;
233 xbm->bm = bm;
234
235 *rbm = (void *)xbm;
236 return EOK;
237}
238
239/** Destroy bitmap in translating GC.
240 *
241 * @param bm Bitmap
242 * @return EOK on success or an error code
243 */
244static errno_t xlate_gc_bitmap_destroy(void *bm)
245{
246 xlate_gc_bitmap_t *xbm = (xlate_gc_bitmap_t *)bm;
247 errno_t rc;
248
249 rc = gfx_bitmap_destroy(xbm->bm);
250 free(xbm);
251 return rc;
252}
253
254/** Render bitmap in translating GC.
255 *
256 * @param bm Bitmap
257 * @param srect0 Source rectangle or @c NULL
258 * @param offs0 Offset or @c NULL
259 * @return EOK on success or an error code
260 */
261static errno_t xlate_gc_bitmap_render(void *bm, gfx_rect_t *srect0,
262 gfx_coord2_t *offs0)
263{
264 xlate_gc_bitmap_t *xbm = (xlate_gc_bitmap_t *)bm;
265 gfx_coord2_t offs;
266
267 if (offs0 != NULL)
268 gfx_coord2_add(offs0, &xbm->xgc->off, &offs);
269 else
270 offs = xbm->xgc->off;
271
272 return gfx_bitmap_render(xbm->bm, srect0, &offs);
273}
274
275/** Get allocation info for bitmap in translating GC.
276 *
277 * @param bm Bitmap
278 * @param alloc Place to store allocation info
279 * @return EOK on success or an error code
280 */
281static errno_t xlate_gc_bitmap_get_alloc(void *bm, gfx_bitmap_alloc_t *alloc)
282{
283 xlate_gc_bitmap_t *xbm = (xlate_gc_bitmap_t *)bm;
284 return gfx_bitmap_get_alloc(xbm->bm, alloc);
285}
286
287/** Get cursor position on translating GC.
288 *
289 * @param arg Translating GC
290 * @param pos Place to store position
291 *
292 * @return EOK on success or an error code
293 */
294static errno_t xlate_gc_cursor_get_pos(void *arg, gfx_coord2_t *pos)
295{
296 xlate_gc_t *xgc = (xlate_gc_t *) arg;
297 gfx_coord2_t cpos;
298 errno_t rc;
299
300 rc = gfx_cursor_get_pos(xgc->bgc, &cpos);
301 if (rc != EOK)
302 return rc;
303
304 gfx_coord2_subtract(&cpos, &xgc->off, pos);
305 return EOK;
306}
307
308/** Set cursor position on translating GC.
309 *
310 * @param arg Translating GC
311 * @param pos New position
312 *
313 * @return EOK on success or an error code
314 */
315static errno_t xlate_gc_cursor_set_pos(void *arg, gfx_coord2_t *pos)
316{
317 xlate_gc_t *xgc = (xlate_gc_t *) arg;
318 gfx_coord2_t cpos;
319
320 gfx_coord2_add(pos, &xgc->off, &cpos);
321 return gfx_cursor_set_pos(xgc->bgc, &cpos);
322}
323
324/** Set cursor visibility on translating GC.
325 *
326 * @param arg Translating GC
327 * @param visible @c true iff cursor should be made visible
328 *
329 * @return EOK on success or an error code
330 */
331static errno_t xlate_gc_cursor_set_visible(void *arg, bool visible)
332{
333 xlate_gc_t *xgc = (xlate_gc_t *) arg;
334
335 return gfx_cursor_set_visible(xgc->bgc, visible);
336}
337
338/** Set translation offset on translating GC.
339 *
340 * @param xgc Translating GC
341 * @param off Offset
342 */
343void xlate_gc_set_off(xlate_gc_t *xgc, gfx_coord2_t *off)
344{
345 xgc->off = *off;
346}
347
348/** @}
349 */
Note: See TracBrowser for help on using the repository browser.