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"
37 #include "pipe/p_context.h"
38 #include "pipe/p_screen.h"
39 #include "util/u_inlines.h"
40 #include "util/u_tile.h"
41 #include "util/u_math.h"
43 static INLINE VGboolean
supported_image_format(VGImageFormat format
)
48 case VG_sRGBA_8888_PRE
:
55 case VG_lRGBA_8888_PRE
:
59 #ifdef OPENVG_VERSION_1_1
65 case VG_sARGB_8888_PRE
:
70 case VG_lARGB_8888_PRE
:
73 case VG_sBGRA_8888_PRE
:
79 case VG_lBGRA_8888_PRE
:
82 case VG_sABGR_8888_PRE
:
87 case VG_lABGR_8888_PRE
:
95 VGImage
vegaCreateImage(VGImageFormat format
,
96 VGint width
, VGint height
,
97 VGbitfield allowedQuality
)
99 struct vg_context
*ctx
= vg_current_context();
101 if (!supported_image_format(format
)) {
102 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
103 return VG_INVALID_HANDLE
;
105 if (width
<= 0 || height
<= 0) {
106 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
107 return VG_INVALID_HANDLE
;
109 if (width
> vegaGeti(VG_MAX_IMAGE_WIDTH
) ||
110 height
> vegaGeti(VG_MAX_IMAGE_HEIGHT
)) {
111 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
112 return VG_INVALID_HANDLE
;
114 if (width
* height
> vegaGeti(VG_MAX_IMAGE_PIXELS
)) {
115 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
116 return VG_INVALID_HANDLE
;
119 if (!(allowedQuality
& ((VG_IMAGE_QUALITY_NONANTIALIASED
|
120 VG_IMAGE_QUALITY_FASTER
|
121 VG_IMAGE_QUALITY_BETTER
)))) {
122 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
123 return VG_INVALID_HANDLE
;
126 return image_to_handle(image_create(format
, width
, height
));
129 void vegaDestroyImage(VGImage image
)
131 struct vg_context
*ctx
= vg_current_context();
132 struct vg_image
*img
= handle_to_image(image
);
134 if (image
== VG_INVALID_HANDLE
) {
135 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
138 if (!vg_object_is_valid(image
, VG_OBJECT_IMAGE
)) {
139 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
145 void vegaClearImage(VGImage image
,
147 VGint width
, VGint height
)
149 struct vg_context
*ctx
= vg_current_context();
150 struct vg_image
*img
;
152 if (image
== VG_INVALID_HANDLE
) {
153 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
156 if (width
<= 0 || height
<= 0) {
157 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
161 img
= handle_to_image(image
);
163 if (x
+ width
< 0 || y
+ height
< 0)
166 image_clear(img
, x
, y
, width
, height
);
170 void vegaImageSubData(VGImage image
,
173 VGImageFormat dataFormat
,
175 VGint width
, VGint height
)
177 struct vg_context
*ctx
= vg_current_context();
178 struct vg_image
*img
;
180 if (image
== VG_INVALID_HANDLE
) {
181 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
184 if (!supported_image_format(dataFormat
)) {
185 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
188 if (width
<= 0 || height
<= 0 || !data
|| !is_aligned(data
)) {
189 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
193 img
= handle_to_image(image
);
194 image_sub_data(img
, data
, dataStride
, dataFormat
,
195 x
, y
, width
, height
);
198 void vegaGetImageSubData(VGImage image
,
201 VGImageFormat dataFormat
,
203 VGint width
, VGint height
)
205 struct vg_context
*ctx
= vg_current_context();
206 struct vg_image
*img
;
208 if (image
== VG_INVALID_HANDLE
) {
209 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
212 if (!supported_image_format(dataFormat
)) {
213 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
216 if (width
<= 0 || height
<= 0 || !data
|| !is_aligned(data
)) {
217 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
220 img
= handle_to_image(image
);
221 image_get_sub_data(img
, data
, dataStride
, dataFormat
,
222 x
, y
, width
, height
);
225 VGImage
vegaChildImage(VGImage parent
,
227 VGint width
, VGint height
)
229 struct vg_context
*ctx
= vg_current_context();
232 if (parent
== VG_INVALID_HANDLE
||
233 !vg_context_is_object_valid(ctx
, VG_OBJECT_IMAGE
, parent
) ||
234 !vg_object_is_valid(parent
, VG_OBJECT_IMAGE
)) {
235 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
236 return VG_INVALID_HANDLE
;
238 if (width
<= 0 || height
<= 0 || x
< 0 || y
< 0) {
239 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
240 return VG_INVALID_HANDLE
;
242 p
= handle_to_image(parent
);
243 if (x
> p
->width
|| y
> p
->height
) {
244 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
245 return VG_INVALID_HANDLE
;
247 if (x
+ width
> p
->width
|| y
+ height
> p
->height
) {
248 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
249 return VG_INVALID_HANDLE
;
252 return image_to_handle(image_child_image(p
, x
, y
, width
, height
));
255 VGImage
vegaGetParent(VGImage image
)
257 struct vg_context
*ctx
= vg_current_context();
258 struct vg_image
*img
;
260 if (image
== VG_INVALID_HANDLE
) {
261 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
262 return VG_INVALID_HANDLE
;
265 img
= handle_to_image(image
);
267 return image_to_handle(img
->parent
);
272 void vegaCopyImage(VGImage dst
, VGint dx
, VGint dy
,
273 VGImage src
, VGint sx
, VGint sy
,
274 VGint width
, VGint height
,
277 struct vg_context
*ctx
= vg_current_context();
279 if (src
== VG_INVALID_HANDLE
|| dst
== VG_INVALID_HANDLE
) {
280 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
284 if (width
<= 0 || height
<= 0) {
285 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
288 vg_validate_state(ctx
);
289 image_copy(handle_to_image(dst
), dx
, dy
,
290 handle_to_image(src
), sx
, sy
,
291 width
, height
, dither
);
294 void vegaDrawImage(VGImage image
)
296 struct vg_context
*ctx
= vg_current_context();
301 if (image
== VG_INVALID_HANDLE
) {
302 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
306 vg_validate_state(ctx
);
307 image_draw(handle_to_image(image
),
308 &ctx
->state
.vg
.image_user_to_surface_matrix
);
311 void vegaSetPixels(VGint dx
, VGint dy
,
312 VGImage src
, VGint sx
, VGint sy
,
313 VGint width
, VGint height
)
315 struct vg_context
*ctx
= vg_current_context();
317 vg_validate_state(ctx
);
319 if (src
== VG_INVALID_HANDLE
) {
320 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
323 if (width
<= 0 || height
<= 0) {
324 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
327 image_set_pixels(dx
, dy
, handle_to_image(src
), sx
, sy
, width
,
331 void vegaGetPixels(VGImage dst
, VGint dx
, VGint dy
,
333 VGint width
, VGint height
)
335 struct vg_context
*ctx
= vg_current_context();
336 struct vg_image
*img
;
338 if (dst
== VG_INVALID_HANDLE
) {
339 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
342 if (width
<= 0 || height
<= 0) {
343 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
347 img
= handle_to_image(dst
);
349 image_get_pixels(img
, dx
, dy
,
350 sx
, sy
, width
, height
);
353 void vegaWritePixels(const void * data
, VGint dataStride
,
354 VGImageFormat dataFormat
,
356 VGint width
, VGint height
)
358 struct vg_context
*ctx
= vg_current_context();
360 if (!supported_image_format(dataFormat
)) {
361 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
364 if (!data
|| !is_aligned(data
)) {
365 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
368 if (width
<= 0 || height
<= 0) {
369 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
373 vg_validate_state(ctx
);
375 struct vg_image
*img
= image_create(dataFormat
, width
, height
);
376 image_sub_data(img
, data
, dataStride
, dataFormat
, 0, 0,
379 struct matrix
*matrix
= &ctx
->state
.vg
.image_user_to_surface_matrix
;
380 matrix_translate(matrix
, dx
, dy
);
382 matrix_translate(matrix
, -dx
, -dy
);
384 /* this looks like a better approach */
385 image_set_pixels(dx
, dy
, img
, 0, 0, width
, height
);
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
;
402 VGfloat temp
[VEGA_MAX_IMAGE_WIDTH
][4];
403 VGfloat
*df
= (VGfloat
*)temp
;
405 VGubyte
*dst
= (VGubyte
*)data
;
406 VGint xoffset
= 0, yoffset
= 0;
408 if (!supported_image_format(dataFormat
)) {
409 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
412 if (!data
|| !is_aligned(data
)) {
413 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
416 if (width
<= 0 || height
<= 0) {
417 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
423 xoffset
*= _vega_size_for_format(dataFormat
);
429 yoffset
*= dataStride
;
434 if (sx
+ width
> stfb
->width
|| sy
+ height
> stfb
->height
) {
435 width
= stfb
->width
- sx
;
436 height
= stfb
->height
- sy
;
437 /* nothing to read */
438 if (width
<= 0 || height
<= 0)
443 VGint y
= (stfb
->height
- sy
) - 1, yStep
= -1;
444 struct pipe_transfer
*transfer
;
446 transfer
= pipe_get_transfer(pipe
, strb
->texture
, 0, 0,
448 0, 0, sx
+ width
, stfb
->height
- sy
);
450 /* Do a row at a time to flip image data vertically */
451 for (i
= 0; i
< height
; i
++) {
453 debug_printf("%d-%d == %d\n", sy
, height
, y
);
455 pipe_get_tile_rgba(pipe
, transfer
, sx
, y
, width
, 1, df
);
457 _vega_pack_rgba_span_float(ctx
, width
, temp
, dataFormat
,
458 dst
+ yoffset
+ xoffset
);
462 pipe
->transfer_destroy(pipe
, transfer
);
466 void vegaCopyPixels(VGint dx
, VGint dy
,
468 VGint width
, VGint height
)
470 struct vg_context
*ctx
= vg_current_context();
471 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
472 struct st_renderbuffer
*strb
= stfb
->strb
;
474 if (width
<= 0 || height
<= 0) {
475 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
479 /* do nothing if we copy from outside the fb */
480 if (dx
>= (VGint
)stfb
->width
|| dy
>= (VGint
)stfb
->height
||
481 sx
>= (VGint
)stfb
->width
|| sy
>= (VGint
)stfb
->height
)
484 vg_validate_state(ctx
);
485 /* make sure rendering has completed */
488 vg_copy_surface(ctx
, strb
->surface
, dx
, dy
,
489 strb
->surface
, sx
, sy
, width
, height
);