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"
41 static INLINE VGboolean
supported_image_format(VGImageFormat format
)
46 case VG_sRGBA_8888_PRE
:
53 case VG_lRGBA_8888_PRE
:
57 #ifdef OPENVG_VERSION_1_1
63 case VG_sARGB_8888_PRE
:
68 case VG_lARGB_8888_PRE
:
71 case VG_sBGRA_8888_PRE
:
77 case VG_lBGRA_8888_PRE
:
80 case VG_sABGR_8888_PRE
:
85 case VG_lABGR_8888_PRE
:
93 VGImage
vegaCreateImage(VGImageFormat format
,
94 VGint width
, VGint height
,
95 VGbitfield allowedQuality
)
97 struct vg_context
*ctx
= vg_current_context();
99 if (!supported_image_format(format
)) {
100 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
101 return VG_INVALID_HANDLE
;
103 if (width
<= 0 || height
<= 0) {
104 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
105 return VG_INVALID_HANDLE
;
107 if (width
> vgGeti(VG_MAX_IMAGE_WIDTH
) ||
108 height
> vgGeti(VG_MAX_IMAGE_HEIGHT
)) {
109 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
110 return VG_INVALID_HANDLE
;
112 if (width
* height
> vgGeti(VG_MAX_IMAGE_PIXELS
)) {
113 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
114 return VG_INVALID_HANDLE
;
117 if (!(allowedQuality
& ((VG_IMAGE_QUALITY_NONANTIALIASED
|
118 VG_IMAGE_QUALITY_FASTER
|
119 VG_IMAGE_QUALITY_BETTER
)))) {
120 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
121 return VG_INVALID_HANDLE
;
124 return (VGImage
)image_create(format
, width
, height
);
127 void vegaDestroyImage(VGImage image
)
129 struct vg_context
*ctx
= vg_current_context();
130 struct vg_image
*img
= (struct vg_image
*)image
;
132 if (image
== VG_INVALID_HANDLE
) {
133 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
136 if (!vg_object_is_valid((void*)image
, VG_OBJECT_IMAGE
)) {
137 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
143 void vegaClearImage(VGImage image
,
145 VGint width
, VGint height
)
147 struct vg_context
*ctx
= vg_current_context();
148 struct vg_image
*img
;
150 if (image
== VG_INVALID_HANDLE
) {
151 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
154 if (width
<= 0 || height
<= 0) {
155 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
159 img
= (struct vg_image
*)image
;
161 if (x
+ width
< 0 || y
+ height
< 0)
164 image_clear(img
, x
, y
, width
, height
);
168 void vegaImageSubData(VGImage image
,
171 VGImageFormat dataFormat
,
173 VGint width
, VGint height
)
175 struct vg_context
*ctx
= vg_current_context();
176 struct vg_image
*img
;
178 if (image
== VG_INVALID_HANDLE
) {
179 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
182 if (!supported_image_format(dataFormat
)) {
183 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
186 if (width
<= 0 || height
<= 0 || !data
|| !is_aligned(data
)) {
187 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
191 img
= (struct vg_image
*)(image
);
192 image_sub_data(img
, data
, dataStride
, dataFormat
,
193 x
, y
, width
, height
);
196 void vegaGetImageSubData(VGImage image
,
199 VGImageFormat dataFormat
,
201 VGint width
, VGint height
)
203 struct vg_context
*ctx
= vg_current_context();
204 struct vg_image
*img
;
206 if (image
== VG_INVALID_HANDLE
) {
207 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
210 if (!supported_image_format(dataFormat
)) {
211 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
214 if (width
<= 0 || height
<= 0 || !data
|| !is_aligned(data
)) {
215 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
218 img
= (struct vg_image
*)image
;
219 image_get_sub_data(img
, data
, dataStride
, dataFormat
,
220 x
, y
, width
, height
);
223 VGImage
vegaChildImage(VGImage parent
,
225 VGint width
, VGint height
)
227 struct vg_context
*ctx
= vg_current_context();
230 if (parent
== VG_INVALID_HANDLE
||
231 !vg_context_is_object_valid(ctx
, VG_OBJECT_IMAGE
, (void*)parent
) ||
232 !vg_object_is_valid((void*)parent
, VG_OBJECT_IMAGE
)) {
233 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
234 return VG_INVALID_HANDLE
;
236 if (width
<= 0 || height
<= 0 || x
< 0 || y
< 0) {
237 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
238 return VG_INVALID_HANDLE
;
240 p
= (struct vg_image
*)parent
;
241 if (x
> p
->width
|| y
> p
->height
) {
242 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
243 return VG_INVALID_HANDLE
;
245 if (x
+ width
> p
->width
|| y
+ height
> p
->height
) {
246 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
247 return VG_INVALID_HANDLE
;
250 return (VGImage
)image_child_image(p
, x
, y
, width
, height
);
253 VGImage
vegaGetParent(VGImage image
)
255 struct vg_context
*ctx
= vg_current_context();
256 struct vg_image
*img
;
258 if (image
== VG_INVALID_HANDLE
) {
259 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
260 return VG_INVALID_HANDLE
;
263 img
= (struct vg_image
*)image
;
265 return (VGImage
)img
->parent
;
270 void vegaCopyImage(VGImage dst
, VGint dx
, VGint dy
,
271 VGImage src
, VGint sx
, VGint sy
,
272 VGint width
, VGint height
,
275 struct vg_context
*ctx
= vg_current_context();
277 if (src
== VG_INVALID_HANDLE
|| dst
== VG_INVALID_HANDLE
) {
278 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
282 if (width
<= 0 || height
<= 0) {
283 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
286 vg_validate_state(ctx
);
287 image_copy((struct vg_image
*)dst
, dx
, dy
,
288 (struct vg_image
*)src
, sx
, sy
,
289 width
, height
, dither
);
292 void vegaDrawImage(VGImage image
)
294 struct vg_context
*ctx
= vg_current_context();
299 if (image
== VG_INVALID_HANDLE
) {
300 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
304 vg_validate_state(ctx
);
305 image_draw((struct vg_image
*)image
);
308 void vegaSetPixels(VGint dx
, VGint dy
,
309 VGImage src
, VGint sx
, VGint sy
,
310 VGint width
, VGint height
)
312 struct vg_context
*ctx
= vg_current_context();
314 vg_validate_state(ctx
);
316 if (src
== VG_INVALID_HANDLE
) {
317 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
320 if (width
<= 0 || height
<= 0) {
321 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
324 image_set_pixels(dx
, dy
, (struct vg_image
*)src
, sx
, sy
, width
,
328 void vegaGetPixels(VGImage dst
, VGint dx
, VGint dy
,
330 VGint width
, VGint height
)
332 struct vg_context
*ctx
= vg_current_context();
333 struct vg_image
*img
;
335 if (dst
== VG_INVALID_HANDLE
) {
336 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
339 if (width
<= 0 || height
<= 0) {
340 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
344 img
= (struct vg_image
*)dst
;
346 image_get_pixels(img
, dx
, dy
,
347 sx
, sy
, width
, height
);
350 void vegaWritePixels(const void * data
, VGint dataStride
,
351 VGImageFormat dataFormat
,
353 VGint width
, VGint height
)
355 struct vg_context
*ctx
= vg_current_context();
356 struct pipe_context
*pipe
= ctx
->pipe
;
358 if (!supported_image_format(dataFormat
)) {
359 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
362 if (!data
|| !is_aligned(data
)) {
363 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
366 if (width
<= 0 || height
<= 0) {
367 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
371 vg_validate_state(ctx
);
373 struct vg_image
*img
= image_create(dataFormat
, width
, height
);
374 image_sub_data(img
, data
, dataStride
, dataFormat
, 0, 0,
377 struct matrix
*matrix
= &ctx
->state
.vg
.image_user_to_surface_matrix
;
378 matrix_translate(matrix
, dx
, dy
);
380 matrix_translate(matrix
, -dx
, -dy
);
382 /* this looks like a better approach */
383 image_set_pixels(dx
, dy
, img
, 0, 0, width
, height
);
387 /* make sure rendering has completed */
388 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
391 void vegaReadPixels(void * data
, VGint dataStride
,
392 VGImageFormat dataFormat
,
394 VGint width
, VGint height
)
396 struct vg_context
*ctx
= vg_current_context();
397 struct pipe_context
*pipe
= ctx
->pipe
;
399 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
400 struct st_renderbuffer
*strb
= stfb
->strb
;
401 struct pipe_framebuffer_state
*fb
= &ctx
->state
.g3d
.fb
;
403 VGfloat temp
[VEGA_MAX_IMAGE_WIDTH
][4];
404 VGfloat
*df
= (VGfloat
*)temp
;
405 VGint y
= (fb
->height
- sy
) - 1, yStep
= -1;
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
);
435 y
= (fb
->height
- sy
) - 1;
436 yoffset
*= dataStride
;
440 struct pipe_transfer
*transfer
;
442 transfer
= pipe_get_transfer(pipe
, strb
->texture
, 0, 0, 0,
444 0, 0, width
, height
);
446 /* Do a row at a time to flip image data vertically */
447 for (i
= 0; i
< height
; i
++) {
449 debug_printf("%d-%d == %d\n", sy
, height
, y
);
451 pipe_get_tile_rgba(pipe
, transfer
, sx
, y
, width
, 1, df
);
453 _vega_pack_rgba_span_float(ctx
, width
, temp
, dataFormat
,
454 dst
+ yoffset
+ xoffset
);
458 pipe
->transfer_destroy(pipe
, transfer
);
462 void vegaCopyPixels(VGint dx
, VGint dy
,
464 VGint width
, VGint height
)
466 struct vg_context
*ctx
= vg_current_context();
467 struct pipe_framebuffer_state
*fb
= &ctx
->state
.g3d
.fb
;
468 struct st_renderbuffer
*strb
= ctx
->draw_buffer
->strb
;
470 if (width
<= 0 || height
<= 0) {
471 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
475 /* do nothing if we copy from outside the fb */
476 if (dx
>= (VGint
)fb
->width
|| dy
>= (VGint
)fb
->height
||
477 sx
>= (VGint
)fb
->width
|| sy
>= (VGint
)fb
->height
)
480 vg_validate_state(ctx
);
481 /* make sure rendering has completed */
484 vg_copy_surface(ctx
, strb
->surface
, dx
, dy
,
485 strb
->surface
, sx
, sy
, width
, height
);