• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2009 VMware, Inc.  All Rights Reserved.
4  *
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:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial portions
15  * of the Software.
16  *
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.
24  *
25  **************************************************************************/
26 
27 #include "image.h"
28 
29 #include "VG/openvg.h"
30 
31 #include "vg_context.h"
32 #include "vg_translate.h"
33 #include "api_consts.h"
34 #include "api.h"
35 #include "handle.h"
36 
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"
42 
supported_image_format(VGImageFormat format)43 static INLINE VGboolean supported_image_format(VGImageFormat format)
44 {
45    switch(format) {
46    case VG_sRGBX_8888:
47    case VG_sRGBA_8888:
48    case VG_sRGBA_8888_PRE:
49    case VG_sRGB_565:
50    case VG_sRGBA_5551:
51    case VG_sRGBA_4444:
52    case VG_sL_8:
53    case VG_lRGBX_8888:
54    case VG_lRGBA_8888:
55    case VG_lRGBA_8888_PRE:
56    case VG_lL_8:
57    case VG_A_8:
58    case VG_BW_1:
59 #ifdef OPENVG_VERSION_1_1
60    case VG_A_1:
61    case VG_A_4:
62 #endif
63    case VG_sXRGB_8888:
64    case VG_sARGB_8888:
65    case VG_sARGB_8888_PRE:
66    case VG_sARGB_1555:
67    case VG_sARGB_4444:
68    case VG_lXRGB_8888:
69    case VG_lARGB_8888:
70    case VG_lARGB_8888_PRE:
71    case VG_sBGRX_8888:
72    case VG_sBGRA_8888:
73    case VG_sBGRA_8888_PRE:
74    case VG_sBGR_565:
75    case VG_sBGRA_5551:
76    case VG_sBGRA_4444:
77    case VG_lBGRX_8888:
78    case VG_lBGRA_8888:
79    case VG_lBGRA_8888_PRE:
80    case VG_sXBGR_8888:
81    case VG_sABGR_8888:
82    case VG_sABGR_8888_PRE:
83    case VG_sABGR_1555:
84    case VG_sABGR_4444:
85    case VG_lXBGR_8888:
86    case VG_lABGR_8888:
87    case VG_lABGR_8888_PRE:
88       return VG_TRUE;
89    default:
90       return VG_FALSE;
91    }
92    return VG_FALSE;
93 }
94 
vegaCreateImage(VGImageFormat format,VGint width,VGint height,VGbitfield allowedQuality)95 VGImage vegaCreateImage(VGImageFormat format,
96                         VGint width, VGint height,
97                         VGbitfield allowedQuality)
98 {
99    struct vg_context *ctx = vg_current_context();
100 
101    if (!supported_image_format(format)) {
102       vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
103       return VG_INVALID_HANDLE;
104    }
105    if (width <= 0 || height <= 0) {
106       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
107       return VG_INVALID_HANDLE;
108    }
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;
113    }
114    if (width * height > vegaGeti(VG_MAX_IMAGE_PIXELS)) {
115       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
116       return VG_INVALID_HANDLE;
117    }
118 
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;
124    }
125 
126    return image_to_handle(image_create(format, width, height));
127 }
128 
vegaDestroyImage(VGImage image)129 void vegaDestroyImage(VGImage image)
130 {
131    struct vg_context *ctx = vg_current_context();
132    struct vg_image *img = handle_to_image(image);
133 
134    if (image == VG_INVALID_HANDLE) {
135       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
136       return;
137    }
138    if (!vg_object_is_valid(image, VG_OBJECT_IMAGE)) {
139       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
140       return;
141    }
142    image_destroy(img);
143 }
144 
vegaClearImage(VGImage image,VGint x,VGint y,VGint width,VGint height)145 void vegaClearImage(VGImage image,
146                     VGint x, VGint y,
147                     VGint width, VGint height)
148 {
149    struct vg_context *ctx = vg_current_context();
150    struct vg_image *img;
151 
152    if (image == VG_INVALID_HANDLE) {
153       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
154       return;
155    }
156    if (width <= 0 || height <= 0) {
157       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
158       return;
159    }
160 
161    img = handle_to_image(image);
162 
163    if (x + width < 0 || y + height < 0)
164       return;
165 
166    image_clear(img, x, y, width, height);
167 
168 }
169 
vegaImageSubData(VGImage image,const void * data,VGint dataStride,VGImageFormat dataFormat,VGint x,VGint y,VGint width,VGint height)170 void vegaImageSubData(VGImage image,
171                       const void * data,
172                       VGint dataStride,
173                       VGImageFormat dataFormat,
174                       VGint x, VGint y,
175                       VGint width, VGint height)
176 {
177    struct vg_context *ctx = vg_current_context();
178    struct vg_image *img;
179 
180    if (image == VG_INVALID_HANDLE) {
181       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
182       return;
183    }
184    if (!supported_image_format(dataFormat)) {
185       vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
186       return;
187    }
188    if (width <= 0 || height <= 0 || !data || !is_aligned(data)) {
189       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
190       return;
191    }
192 
193    img = handle_to_image(image);
194    image_sub_data(img, data, dataStride, dataFormat,
195                   x, y, width, height);
196 }
197 
vegaGetImageSubData(VGImage image,void * data,VGint dataStride,VGImageFormat dataFormat,VGint x,VGint y,VGint width,VGint height)198 void vegaGetImageSubData(VGImage image,
199                          void * data,
200                          VGint dataStride,
201                          VGImageFormat dataFormat,
202                          VGint x, VGint y,
203                          VGint width, VGint height)
204 {
205    struct vg_context *ctx = vg_current_context();
206    struct vg_image *img;
207 
208    if (image == VG_INVALID_HANDLE) {
209       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
210       return;
211    }
212    if (!supported_image_format(dataFormat)) {
213       vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
214       return;
215    }
216    if (width <= 0 || height <= 0 || !data || !is_aligned(data)) {
217       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
218       return;
219    }
220    img = handle_to_image(image);
221    image_get_sub_data(img, data, dataStride, dataFormat,
222                       x, y, width, height);
223 }
224 
vegaChildImage(VGImage parent,VGint x,VGint y,VGint width,VGint height)225 VGImage vegaChildImage(VGImage parent,
226                        VGint x, VGint y,
227                        VGint width, VGint height)
228 {
229    struct vg_context *ctx = vg_current_context();
230    struct vg_image *p;
231 
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;
237    }
238    if (width <= 0 || height <= 0 || x < 0 || y < 0) {
239       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
240       return VG_INVALID_HANDLE;
241    }
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;
246    }
247    if (x + width > p->width  || y + height > p->height) {
248       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
249       return VG_INVALID_HANDLE;
250    }
251 
252    return image_to_handle(image_child_image(p, x, y, width, height));
253 }
254 
vegaGetParent(VGImage image)255 VGImage vegaGetParent(VGImage image)
256 {
257    struct vg_context *ctx = vg_current_context();
258    struct vg_image *img;
259 
260    if (image == VG_INVALID_HANDLE) {
261       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
262       return VG_INVALID_HANDLE;
263    }
264 
265    img = handle_to_image(image);
266    if (img->parent)
267       return image_to_handle(img->parent);
268    else
269       return image;
270 }
271 
vegaCopyImage(VGImage dst,VGint dx,VGint dy,VGImage src,VGint sx,VGint sy,VGint width,VGint height,VGboolean dither)272 void vegaCopyImage(VGImage dst, VGint dx, VGint dy,
273                    VGImage src, VGint sx, VGint sy,
274                    VGint width, VGint height,
275                    VGboolean dither)
276 {
277    struct vg_context *ctx = vg_current_context();
278 
279    if (src == VG_INVALID_HANDLE || dst == VG_INVALID_HANDLE) {
280       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
281       return;
282    }
283 
284    if (width <= 0 || height <= 0) {
285       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
286       return;
287    }
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);
292 }
293 
vegaDrawImage(VGImage image)294 void vegaDrawImage(VGImage image)
295 {
296    struct vg_context *ctx = vg_current_context();
297 
298    if (!ctx)
299       return;
300 
301    if (image == VG_INVALID_HANDLE) {
302       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
303       return;
304    }
305 
306    vg_validate_state(ctx);
307    image_draw(handle_to_image(image),
308          &ctx->state.vg.image_user_to_surface_matrix);
309 }
310 
vegaSetPixels(VGint dx,VGint dy,VGImage src,VGint sx,VGint sy,VGint width,VGint height)311 void vegaSetPixels(VGint dx, VGint dy,
312                    VGImage src, VGint sx, VGint sy,
313                    VGint width, VGint height)
314 {
315    struct vg_context *ctx = vg_current_context();
316 
317    vg_validate_state(ctx);
318 
319    if (src == VG_INVALID_HANDLE) {
320       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
321       return;
322    }
323    if (width <= 0 || height <= 0) {
324       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
325       return;
326    }
327    image_set_pixels(dx, dy, handle_to_image(src), sx, sy, width,
328                     height);
329 }
330 
vegaGetPixels(VGImage dst,VGint dx,VGint dy,VGint sx,VGint sy,VGint width,VGint height)331 void vegaGetPixels(VGImage dst, VGint dx, VGint dy,
332                    VGint sx, VGint sy,
333                    VGint width, VGint height)
334 {
335    struct vg_context *ctx = vg_current_context();
336    struct vg_image *img;
337 
338    if (dst == VG_INVALID_HANDLE) {
339       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
340       return;
341    }
342    if (width <= 0 || height <= 0) {
343       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
344       return;
345    }
346 
347    img = handle_to_image(dst);
348 
349    image_get_pixels(img, dx, dy,
350                     sx, sy, width, height);
351 }
352 
vegaWritePixels(const void * data,VGint dataStride,VGImageFormat dataFormat,VGint dx,VGint dy,VGint width,VGint height)353 void vegaWritePixels(const void * data, VGint dataStride,
354                      VGImageFormat dataFormat,
355                      VGint dx, VGint dy,
356                      VGint width, VGint height)
357 {
358    struct vg_context *ctx = vg_current_context();
359 
360    if (!supported_image_format(dataFormat)) {
361       vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
362       return;
363    }
364    if (!data || !is_aligned(data)) {
365       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
366       return;
367    }
368    if (width <= 0 || height <= 0) {
369       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
370       return;
371    }
372 
373    vg_validate_state(ctx);
374    {
375       struct vg_image *img = image_create(dataFormat, width, height);
376       image_sub_data(img, data, dataStride, dataFormat, 0, 0,
377                      width, height);
378 #if 0
379       struct matrix *matrix = &ctx->state.vg.image_user_to_surface_matrix;
380       matrix_translate(matrix, dx, dy);
381       image_draw(img);
382       matrix_translate(matrix, -dx, -dy);
383 #else
384       /* this looks like a better approach */
385       image_set_pixels(dx, dy, img, 0, 0, width, height);
386 #endif
387       image_destroy(img);
388    }
389 }
390 
vegaReadPixels(void * data,VGint dataStride,VGImageFormat dataFormat,VGint sx,VGint sy,VGint width,VGint height)391 void vegaReadPixels(void * data, VGint dataStride,
392                     VGImageFormat dataFormat,
393                     VGint sx, VGint sy,
394                     VGint width, VGint height)
395 {
396    struct vg_context *ctx = vg_current_context();
397    struct pipe_context *pipe = ctx->pipe;
398 
399    struct st_framebuffer *stfb = ctx->draw_buffer;
400    struct st_renderbuffer *strb = stfb->strb;
401 
402    VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
403    VGfloat *df = (VGfloat*)temp;
404    VGint i;
405    VGubyte *dst = (VGubyte *)data;
406    VGint xoffset = 0, yoffset = 0;
407 
408    if (!supported_image_format(dataFormat)) {
409       vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
410       return;
411    }
412    if (!data || !is_aligned(data)) {
413       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
414       return;
415    }
416    if (width <= 0 || height <= 0) {
417       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
418       return;
419    }
420 
421    if (sx < 0) {
422       xoffset = -sx;
423       xoffset *= _vega_size_for_format(dataFormat);
424       width += sx;
425       sx = 0;
426    }
427    if (sy < 0) {
428       yoffset = -sy;
429       yoffset *= dataStride;
430       height += sy;
431       sy = 0;
432    }
433 
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)
439          return;
440    }
441 
442    {
443       VGint y = (stfb->height - sy) - 1, yStep = -1;
444       struct pipe_transfer *transfer;
445 
446       transfer = pipe_get_transfer(pipe, strb->texture,  0, 0,
447                                    PIPE_TRANSFER_READ,
448                                    0, 0, sx + width, stfb->height - sy);
449 
450       /* Do a row at a time to flip image data vertically */
451       for (i = 0; i < height; i++) {
452 #if 0
453          debug_printf("%d-%d  == %d\n", sy, height, y);
454 #endif
455          pipe_get_tile_rgba(pipe, transfer, sx, y, width, 1, df);
456          y += yStep;
457          _vega_pack_rgba_span_float(ctx, width, temp, dataFormat,
458                                     dst + yoffset + xoffset);
459          dst += dataStride;
460       }
461 
462       pipe->transfer_destroy(pipe, transfer);
463    }
464 }
465 
vegaCopyPixels(VGint dx,VGint dy,VGint sx,VGint sy,VGint width,VGint height)466 void vegaCopyPixels(VGint dx, VGint dy,
467                     VGint sx, VGint sy,
468                     VGint width, VGint height)
469 {
470    struct vg_context *ctx = vg_current_context();
471    struct st_framebuffer *stfb = ctx->draw_buffer;
472    struct st_renderbuffer *strb = stfb->strb;
473 
474    if (width <= 0 || height <= 0) {
475       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
476       return;
477    }
478 
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)
482       return;
483 
484    vg_validate_state(ctx);
485    /* make sure rendering has completed */
486    vegaFinish();
487 
488    vg_copy_surface(ctx, strb->surface, dx, dy,
489                    strb->surface, sx, sy, width, height);
490 }
491