1 /**************************************************************************
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 **************************************************************************/
29 #include "VG/openvg.h"
31 #include "vg_context.h"
32 #include "vg_translate.h"
33 #include "api_consts.h"
36 #include "pipe/p_context.h"
37 #include "pipe/p_screen.h"
38 #include "util/u_inlines.h"
39 #include "util/u_tile.h"
40 #include "util/u_math.h"
42 static INLINE VGboolean
supported_image_format(VGImageFormat format
)
47 case VG_sRGBA_8888_PRE
:
54 case VG_lRGBA_8888_PRE
:
58 #ifdef OPENVG_VERSION_1_1
64 case VG_sARGB_8888_PRE
:
69 case VG_lARGB_8888_PRE
:
72 case VG_sBGRA_8888_PRE
:
78 case VG_lBGRA_8888_PRE
:
81 case VG_sABGR_8888_PRE
:
86 case VG_lABGR_8888_PRE
:
94 VGImage
vegaCreateImage(VGImageFormat format
,
95 VGint width
, VGint height
,
96 VGbitfield allowedQuality
)
98 struct vg_context
*ctx
= vg_current_context();
100 if (!supported_image_format(format
)) {
101 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
102 return VG_INVALID_HANDLE
;
104 if (width
<= 0 || height
<= 0) {
105 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
106 return VG_INVALID_HANDLE
;
108 if (width
> vgGeti(VG_MAX_IMAGE_WIDTH
) ||
109 height
> vgGeti(VG_MAX_IMAGE_HEIGHT
)) {
110 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
111 return VG_INVALID_HANDLE
;
113 if (width
* height
> vgGeti(VG_MAX_IMAGE_PIXELS
)) {
114 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
115 return VG_INVALID_HANDLE
;
118 if (!(allowedQuality
& ((VG_IMAGE_QUALITY_NONANTIALIASED
|
119 VG_IMAGE_QUALITY_FASTER
|
120 VG_IMAGE_QUALITY_BETTER
)))) {
121 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
122 return VG_INVALID_HANDLE
;
125 return (VGImage
)image_create(format
, width
, height
);
128 void vegaDestroyImage(VGImage image
)
130 struct vg_context
*ctx
= vg_current_context();
131 struct vg_image
*img
= (struct vg_image
*)image
;
133 if (image
== VG_INVALID_HANDLE
) {
134 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
137 if (!vg_object_is_valid((void*)image
, VG_OBJECT_IMAGE
)) {
138 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
144 void vegaClearImage(VGImage image
,
146 VGint width
, VGint height
)
148 struct vg_context
*ctx
= vg_current_context();
149 struct vg_image
*img
;
151 if (image
== VG_INVALID_HANDLE
) {
152 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
155 if (width
<= 0 || height
<= 0) {
156 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
160 img
= (struct vg_image
*)image
;
162 if (x
+ width
< 0 || y
+ height
< 0)
165 image_clear(img
, x
, y
, width
, height
);
169 void vegaImageSubData(VGImage image
,
172 VGImageFormat dataFormat
,
174 VGint width
, VGint height
)
176 struct vg_context
*ctx
= vg_current_context();
177 struct vg_image
*img
;
179 if (image
== VG_INVALID_HANDLE
) {
180 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
183 if (!supported_image_format(dataFormat
)) {
184 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
187 if (width
<= 0 || height
<= 0 || !data
|| !is_aligned(data
)) {
188 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
192 img
= (struct vg_image
*)(image
);
193 image_sub_data(img
, data
, dataStride
, dataFormat
,
194 x
, y
, width
, height
);
197 void vegaGetImageSubData(VGImage image
,
200 VGImageFormat dataFormat
,
202 VGint width
, VGint height
)
204 struct vg_context
*ctx
= vg_current_context();
205 struct vg_image
*img
;
207 if (image
== VG_INVALID_HANDLE
) {
208 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
211 if (!supported_image_format(dataFormat
)) {
212 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
215 if (width
<= 0 || height
<= 0 || !data
|| !is_aligned(data
)) {
216 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
219 img
= (struct vg_image
*)image
;
220 image_get_sub_data(img
, data
, dataStride
, dataFormat
,
221 x
, y
, width
, height
);
224 VGImage
vegaChildImage(VGImage parent
,
226 VGint width
, VGint height
)
228 struct vg_context
*ctx
= vg_current_context();
231 if (parent
== VG_INVALID_HANDLE
||
232 !vg_context_is_object_valid(ctx
, VG_OBJECT_IMAGE
, (void*)parent
) ||
233 !vg_object_is_valid((void*)parent
, VG_OBJECT_IMAGE
)) {
234 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
235 return VG_INVALID_HANDLE
;
237 if (width
<= 0 || height
<= 0 || x
< 0 || y
< 0) {
238 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
239 return VG_INVALID_HANDLE
;
241 p
= (struct vg_image
*)parent
;
242 if (x
> p
->width
|| y
> p
->height
) {
243 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
244 return VG_INVALID_HANDLE
;
246 if (x
+ width
> p
->width
|| y
+ height
> p
->height
) {
247 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
248 return VG_INVALID_HANDLE
;
251 return (VGImage
)image_child_image(p
, x
, y
, width
, height
);
254 VGImage
vegaGetParent(VGImage image
)
256 struct vg_context
*ctx
= vg_current_context();
257 struct vg_image
*img
;
259 if (image
== VG_INVALID_HANDLE
) {
260 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
261 return VG_INVALID_HANDLE
;
264 img
= (struct vg_image
*)image
;
266 return (VGImage
)img
->parent
;
271 void vegaCopyImage(VGImage dst
, VGint dx
, VGint dy
,
272 VGImage src
, VGint sx
, VGint sy
,
273 VGint width
, VGint height
,
276 struct vg_context
*ctx
= vg_current_context();
278 if (src
== VG_INVALID_HANDLE
|| dst
== VG_INVALID_HANDLE
) {
279 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
283 if (width
<= 0 || height
<= 0) {
284 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
287 vg_validate_state(ctx
);
288 image_copy((struct vg_image
*)dst
, dx
, dy
,
289 (struct vg_image
*)src
, sx
, sy
,
290 width
, height
, dither
);
293 void vegaDrawImage(VGImage image
)
295 struct vg_context
*ctx
= vg_current_context();
300 if (image
== VG_INVALID_HANDLE
) {
301 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
305 vg_validate_state(ctx
);
306 image_draw((struct vg_image
*)image
);
309 void vegaSetPixels(VGint dx
, VGint dy
,
310 VGImage src
, VGint sx
, VGint sy
,
311 VGint width
, VGint height
)
313 struct vg_context
*ctx
= vg_current_context();
315 vg_validate_state(ctx
);
317 if (src
== VG_INVALID_HANDLE
) {
318 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
321 if (width
<= 0 || height
<= 0) {
322 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
325 image_set_pixels(dx
, dy
, (struct vg_image
*)src
, sx
, sy
, width
,
329 void vegaGetPixels(VGImage dst
, VGint dx
, VGint dy
,
331 VGint width
, VGint height
)
333 struct vg_context
*ctx
= vg_current_context();
334 struct vg_image
*img
;
336 if (dst
== VG_INVALID_HANDLE
) {
337 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
340 if (width
<= 0 || height
<= 0) {
341 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
345 img
= (struct vg_image
*)dst
;
347 image_get_pixels(img
, dx
, dy
,
348 sx
, sy
, width
, height
);
351 void vegaWritePixels(const void * data
, VGint dataStride
,
352 VGImageFormat dataFormat
,
354 VGint width
, VGint height
)
356 struct vg_context
*ctx
= vg_current_context();
357 struct pipe_context
*pipe
= ctx
->pipe
;
359 if (!supported_image_format(dataFormat
)) {
360 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
363 if (!data
|| !is_aligned(data
)) {
364 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
367 if (width
<= 0 || height
<= 0) {
368 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
372 vg_validate_state(ctx
);
374 struct vg_image
*img
= image_create(dataFormat
, width
, height
);
375 image_sub_data(img
, data
, dataStride
, dataFormat
, 0, 0,
378 struct matrix
*matrix
= &ctx
->state
.vg
.image_user_to_surface_matrix
;
379 matrix_translate(matrix
, dx
, dy
);
381 matrix_translate(matrix
, -dx
, -dy
);
383 /* this looks like a better approach */
384 image_set_pixels(dx
, dy
, img
, 0, 0, width
, height
);
388 /* make sure rendering has completed */
389 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
392 void vegaReadPixels(void * data
, VGint dataStride
,
393 VGImageFormat dataFormat
,
395 VGint width
, VGint height
)
397 struct vg_context
*ctx
= vg_current_context();
398 struct pipe_context
*pipe
= ctx
->pipe
;
400 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
401 struct st_renderbuffer
*strb
= stfb
->strb
;
402 struct pipe_framebuffer_state
*fb
= &ctx
->state
.g3d
.fb
;
404 VGfloat temp
[VEGA_MAX_IMAGE_WIDTH
][4];
405 VGfloat
*df
= (VGfloat
*)temp
;
407 VGubyte
*dst
= (VGubyte
*)data
;
408 VGint xoffset
= 0, yoffset
= 0;
410 if (!supported_image_format(dataFormat
)) {
411 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
414 if (!data
|| !is_aligned(data
)) {
415 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
418 if (width
<= 0 || height
<= 0) {
419 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
423 /* make sure rendering has completed */
424 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
427 xoffset
*= _vega_size_for_format(dataFormat
);
433 yoffset
*= dataStride
;
438 if (sx
+ width
> fb
->width
|| sy
+ height
> fb
->height
) {
439 width
= fb
->width
- sx
;
440 height
= fb
->height
- sy
;
441 /* nothing to read */
442 if (width
<= 0 || height
<= 0)
447 VGint y
= (fb
->height
- sy
) - 1, yStep
= -1;
448 struct pipe_transfer
*transfer
;
450 transfer
= pipe_get_transfer(pipe
, strb
->texture
, 0, 0, 0,
452 0, 0, sx
+ width
, fb
->height
- sy
);
454 /* Do a row at a time to flip image data vertically */
455 for (i
= 0; i
< height
; i
++) {
457 debug_printf("%d-%d == %d\n", sy
, height
, y
);
459 pipe_get_tile_rgba(pipe
, transfer
, sx
, y
, width
, 1, df
);
461 _vega_pack_rgba_span_float(ctx
, width
, temp
, dataFormat
,
462 dst
+ yoffset
+ xoffset
);
466 pipe
->transfer_destroy(pipe
, transfer
);
470 void vegaCopyPixels(VGint dx
, VGint dy
,
472 VGint width
, VGint height
)
474 struct vg_context
*ctx
= vg_current_context();
475 struct pipe_framebuffer_state
*fb
= &ctx
->state
.g3d
.fb
;
476 struct st_renderbuffer
*strb
= ctx
->draw_buffer
->strb
;
478 if (width
<= 0 || height
<= 0) {
479 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
483 /* do nothing if we copy from outside the fb */
484 if (dx
>= (VGint
)fb
->width
|| dy
>= (VGint
)fb
->height
||
485 sx
>= (VGint
)fb
->width
|| sy
>= (VGint
)fb
->height
)
488 vg_validate_state(ctx
);
489 /* make sure rendering has completed */
492 vg_copy_surface(ctx
, strb
->surface
, dx
, dy
,
493 strb
->surface
, sx
, sy
, width
, height
);