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_blit.h"
41 #include "util/u_tile.h"
42 #include "util/u_memory.h"
44 static INLINE VGboolean
supported_image_format(VGImageFormat format
)
49 case VG_sRGBA_8888_PRE
:
56 case VG_lRGBA_8888_PRE
:
60 #ifdef OPENVG_VERSION_1_1
66 case VG_sARGB_8888_PRE
:
71 case VG_lARGB_8888_PRE
:
74 case VG_sBGRA_8888_PRE
:
80 case VG_lBGRA_8888_PRE
:
83 case VG_sABGR_8888_PRE
:
88 case VG_lABGR_8888_PRE
:
96 VGImage
vegaCreateImage(VGImageFormat format
,
97 VGint width
, VGint height
,
98 VGbitfield allowedQuality
)
100 struct vg_context
*ctx
= vg_current_context();
102 if (!supported_image_format(format
)) {
103 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
104 return VG_INVALID_HANDLE
;
106 if (width
<= 0 || height
<= 0) {
107 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
108 return VG_INVALID_HANDLE
;
110 if (width
> vgGeti(VG_MAX_IMAGE_WIDTH
) ||
111 height
> vgGeti(VG_MAX_IMAGE_HEIGHT
)) {
112 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
113 return VG_INVALID_HANDLE
;
115 if (width
* height
> vgGeti(VG_MAX_IMAGE_PIXELS
)) {
116 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
117 return VG_INVALID_HANDLE
;
120 if (!(allowedQuality
& ((VG_IMAGE_QUALITY_NONANTIALIASED
|
121 VG_IMAGE_QUALITY_FASTER
|
122 VG_IMAGE_QUALITY_BETTER
)))) {
123 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
124 return VG_INVALID_HANDLE
;
127 return (VGImage
)image_create(format
, width
, height
);
130 void vegaDestroyImage(VGImage image
)
132 struct vg_context
*ctx
= vg_current_context();
133 struct vg_image
*img
= (struct vg_image
*)image
;
135 if (image
== VG_INVALID_HANDLE
) {
136 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
139 if (!vg_object_is_valid((void*)image
, VG_OBJECT_IMAGE
)) {
140 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
146 void vegaClearImage(VGImage image
,
148 VGint width
, VGint height
)
150 struct vg_context
*ctx
= vg_current_context();
151 struct vg_image
*img
;
153 if (image
== VG_INVALID_HANDLE
) {
154 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
157 if (width
<= 0 || height
<= 0) {
158 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
162 img
= (struct vg_image
*)image
;
164 if (x
+ width
< 0 || y
+ height
< 0)
167 image_clear(img
, x
, y
, width
, height
);
171 void vegaImageSubData(VGImage image
,
174 VGImageFormat dataFormat
,
176 VGint width
, VGint height
)
178 struct vg_context
*ctx
= vg_current_context();
179 struct vg_image
*img
;
181 if (image
== VG_INVALID_HANDLE
) {
182 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
185 if (!supported_image_format(dataFormat
)) {
186 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
189 if (width
<= 0 || height
<= 0 || !data
|| !is_aligned(data
)) {
190 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
194 img
= (struct vg_image
*)(image
);
195 image_sub_data(img
, data
, dataStride
, dataFormat
,
196 x
, y
, width
, height
);
199 void vegaGetImageSubData(VGImage image
,
202 VGImageFormat dataFormat
,
204 VGint width
, VGint height
)
206 struct vg_context
*ctx
= vg_current_context();
207 struct vg_image
*img
;
209 if (image
== VG_INVALID_HANDLE
) {
210 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
213 if (!supported_image_format(dataFormat
)) {
214 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
217 if (width
<= 0 || height
<= 0 || !data
|| !is_aligned(data
)) {
218 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
221 img
= (struct vg_image
*)image
;
222 image_get_sub_data(img
, data
, dataStride
, dataFormat
,
223 x
, y
, width
, height
);
226 VGImage
vegaChildImage(VGImage parent
,
228 VGint width
, VGint height
)
230 struct vg_context
*ctx
= vg_current_context();
233 if (parent
== VG_INVALID_HANDLE
||
234 !vg_context_is_object_valid(ctx
, VG_OBJECT_IMAGE
, (void*)parent
) ||
235 !vg_object_is_valid((void*)parent
, VG_OBJECT_IMAGE
)) {
236 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
237 return VG_INVALID_HANDLE
;
239 if (width
<= 0 || height
<= 0 || x
< 0 || y
< 0) {
240 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
241 return VG_INVALID_HANDLE
;
243 p
= (struct vg_image
*)parent
;
244 if (x
> p
->width
|| y
> p
->height
) {
245 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
246 return VG_INVALID_HANDLE
;
248 if (x
+ width
> p
->width
|| y
+ height
> p
->height
) {
249 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
250 return VG_INVALID_HANDLE
;
253 return (VGImage
)image_child_image(p
, x
, y
, width
, height
);
256 VGImage
vegaGetParent(VGImage image
)
258 struct vg_context
*ctx
= vg_current_context();
259 struct vg_image
*img
;
261 if (image
== VG_INVALID_HANDLE
) {
262 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
263 return VG_INVALID_HANDLE
;
266 img
= (struct vg_image
*)image
;
268 return (VGImage
)img
->parent
;
273 void vegaCopyImage(VGImage dst
, VGint dx
, VGint dy
,
274 VGImage src
, VGint sx
, VGint sy
,
275 VGint width
, VGint height
,
278 struct vg_context
*ctx
= vg_current_context();
280 if (src
== VG_INVALID_HANDLE
|| dst
== VG_INVALID_HANDLE
) {
281 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
285 if (width
<= 0 || height
<= 0) {
286 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
289 vg_validate_state(ctx
);
290 image_copy((struct vg_image
*)dst
, dx
, dy
,
291 (struct vg_image
*)src
, sx
, sy
,
292 width
, height
, dither
);
295 void vegaDrawImage(VGImage image
)
297 struct vg_context
*ctx
= vg_current_context();
302 if (image
== VG_INVALID_HANDLE
) {
303 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
307 vg_validate_state(ctx
);
308 image_draw((struct vg_image
*)image
);
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
, (struct vg_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
= (struct vg_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();
359 struct pipe_context
*pipe
= ctx
->pipe
;
361 if (!supported_image_format(dataFormat
)) {
362 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
365 if (!data
|| !is_aligned(data
)) {
366 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
369 if (width
<= 0 || height
<= 0) {
370 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
374 vg_validate_state(ctx
);
376 struct vg_image
*img
= image_create(dataFormat
, width
, height
);
377 image_sub_data(img
, data
, dataStride
, dataFormat
, 0, 0,
380 struct matrix
*matrix
= &ctx
->state
.vg
.image_user_to_surface_matrix
;
381 matrix_translate(matrix
, dx
, dy
);
383 matrix_translate(matrix
, -dx
, -dy
);
385 /* this looks like a better approach */
386 image_set_pixels(dx
, dy
, img
, 0, 0, width
, height
);
390 /* make sure rendering has completed */
391 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
394 void vegaReadPixels(void * data
, VGint dataStride
,
395 VGImageFormat dataFormat
,
397 VGint width
, VGint height
)
399 struct vg_context
*ctx
= vg_current_context();
400 struct pipe_context
*pipe
= ctx
->pipe
;
402 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
403 struct st_renderbuffer
*strb
= stfb
->strb
;
404 struct pipe_framebuffer_state
*fb
= &ctx
->state
.g3d
.fb
;
406 VGfloat temp
[VEGA_MAX_IMAGE_WIDTH
][4];
407 VGfloat
*df
= (VGfloat
*)temp
;
408 VGint y
= (fb
->height
- sy
) - 1, yStep
= -1;
410 VGubyte
*dst
= (VGubyte
*)data
;
411 VGint xoffset
= 0, yoffset
= 0;
413 if (!supported_image_format(dataFormat
)) {
414 vg_set_error(ctx
, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR
);
417 if (!data
|| !is_aligned(data
)) {
418 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
421 if (width
<= 0 || height
<= 0) {
422 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
426 /* make sure rendering has completed */
427 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
430 xoffset
*= _vega_size_for_format(dataFormat
);
438 y
= (fb
->height
- sy
) - 1;
439 yoffset
*= dataStride
;
443 struct pipe_transfer
*transfer
;
445 transfer
= pipe_get_transfer(pipe
, strb
->texture
, 0, 0, 0,
447 0, 0, width
, height
);
449 /* Do a row at a time to flip image data vertically */
450 for (i
= 0; i
< height
; i
++) {
452 debug_printf("%d-%d == %d\n", sy
, height
, y
);
454 pipe_get_tile_rgba(pipe
, transfer
, sx
, y
, width
, 1, df
);
456 _vega_pack_rgba_span_float(ctx
, width
, temp
, dataFormat
,
457 dst
+ yoffset
+ xoffset
);
461 pipe
->transfer_destroy(pipe
, transfer
);
465 void vegaCopyPixels(VGint dx
, VGint dy
,
467 VGint width
, VGint height
)
469 struct vg_context
*ctx
= vg_current_context();
470 struct pipe_framebuffer_state
*fb
= &ctx
->state
.g3d
.fb
;
471 struct st_renderbuffer
*strb
= ctx
->draw_buffer
->strb
;
473 if (width
<= 0 || height
<= 0) {
474 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
478 /* do nothing if we copy from outside the fb */
479 if (dx
>= (VGint
)fb
->width
|| dy
>= (VGint
)fb
->height
||
480 sx
>= (VGint
)fb
->width
|| sy
>= (VGint
)fb
->height
)
483 vg_validate_state(ctx
);
484 /* make sure rendering has completed */
487 vg_copy_surface(ctx
, strb
->surface
, dx
, dy
,
488 strb
->surface
, sx
, sy
, width
, height
);