glsl2: Add and use new variable mode ir_var_temporary
[mesa/nouveau-pmpeg.git] / src / gallium / state_trackers / vega / api_images.c
blob547508f815a334488b5ffb38e76c250eea085632
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
15 * of the Software.
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 **************************************************************************/
27 #include "image.h"
29 #include "VG/openvg.h"
31 #include "vg_context.h"
32 #include "vg_translate.h"
33 #include "api_consts.h"
34 #include "image.h"
35 #include "api.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)
46 switch(format) {
47 case VG_sRGBX_8888:
48 case VG_sRGBA_8888:
49 case VG_sRGBA_8888_PRE:
50 case VG_sRGB_565:
51 case VG_sRGBA_5551:
52 case VG_sRGBA_4444:
53 case VG_sL_8:
54 case VG_lRGBX_8888:
55 case VG_lRGBA_8888:
56 case VG_lRGBA_8888_PRE:
57 case VG_lL_8:
58 case VG_A_8:
59 case VG_BW_1:
60 #ifdef OPENVG_VERSION_1_1
61 case VG_A_1:
62 case VG_A_4:
63 #endif
64 case VG_sXRGB_8888:
65 case VG_sARGB_8888:
66 case VG_sARGB_8888_PRE:
67 case VG_sARGB_1555:
68 case VG_sARGB_4444:
69 case VG_lXRGB_8888:
70 case VG_lARGB_8888:
71 case VG_lARGB_8888_PRE:
72 case VG_sBGRX_8888:
73 case VG_sBGRA_8888:
74 case VG_sBGRA_8888_PRE:
75 case VG_sBGR_565:
76 case VG_sBGRA_5551:
77 case VG_sBGRA_4444:
78 case VG_lBGRX_8888:
79 case VG_lBGRA_8888:
80 case VG_lBGRA_8888_PRE:
81 case VG_sXBGR_8888:
82 case VG_sABGR_8888:
83 case VG_sABGR_8888_PRE:
84 case VG_sABGR_1555:
85 case VG_sABGR_4444:
86 case VG_lXBGR_8888:
87 case VG_lABGR_8888:
88 case VG_lABGR_8888_PRE:
89 return VG_TRUE;
90 default:
91 return VG_FALSE;
93 return VG_FALSE;
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);
137 return;
139 if (!vg_object_is_valid((void*)image, VG_OBJECT_IMAGE)) {
140 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
141 return;
143 image_destroy(img);
146 void vegaClearImage(VGImage image,
147 VGint x, VGint y,
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);
155 return;
157 if (width <= 0 || height <= 0) {
158 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
159 return;
162 img = (struct vg_image*)image;
164 if (x + width < 0 || y + height < 0)
165 return;
167 image_clear(img, x, y, width, height);
171 void vegaImageSubData(VGImage image,
172 const void * data,
173 VGint dataStride,
174 VGImageFormat dataFormat,
175 VGint x, VGint y,
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);
183 return;
185 if (!supported_image_format(dataFormat)) {
186 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
187 return;
189 if (width <= 0 || height <= 0 || !data || !is_aligned(data)) {
190 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
191 return;
194 img = (struct vg_image*)(image);
195 image_sub_data(img, data, dataStride, dataFormat,
196 x, y, width, height);
199 void vegaGetImageSubData(VGImage image,
200 void * data,
201 VGint dataStride,
202 VGImageFormat dataFormat,
203 VGint x, VGint y,
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);
211 return;
213 if (!supported_image_format(dataFormat)) {
214 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR);
215 return;
217 if (width <= 0 || height <= 0 || !data || !is_aligned(data)) {
218 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
219 return;
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,
227 VGint x, VGint y,
228 VGint width, VGint height)
230 struct vg_context *ctx = vg_current_context();
231 struct vg_image *p;
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;
267 if (img->parent)
268 return (VGImage)img->parent;
269 else
270 return image;
273 void vegaCopyImage(VGImage dst, VGint dx, VGint dy,
274 VGImage src, VGint sx, VGint sy,
275 VGint width, VGint height,
276 VGboolean dither)
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);
282 return;
285 if (width <= 0 || height <= 0) {
286 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
287 return;
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();
299 if (!ctx)
300 return;
302 if (image == VG_INVALID_HANDLE) {
303 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
304 return;
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);
321 return;
323 if (width <= 0 || height <= 0) {
324 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
325 return;
327 image_set_pixels(dx, dy, (struct vg_image*)src, sx, sy, width,
328 height);
331 void vegaGetPixels(VGImage dst, VGint dx, VGint dy,
332 VGint sx, VGint sy,
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);
340 return;
342 if (width <= 0 || height <= 0) {
343 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
344 return;
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,
355 VGint dx, VGint dy,
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);
363 return;
365 if (!data || !is_aligned(data)) {
366 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
367 return;
369 if (width <= 0 || height <= 0) {
370 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
371 return;
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,
378 width, height);
379 #if 0
380 struct matrix *matrix = &ctx->state.vg.image_user_to_surface_matrix;
381 matrix_translate(matrix, dx, dy);
382 image_draw(img);
383 matrix_translate(matrix, -dx, -dy);
384 #else
385 /* this looks like a better approach */
386 image_set_pixels(dx, dy, img, 0, 0, width, height);
387 #endif
388 image_destroy(img);
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,
396 VGint sx, VGint sy,
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;
409 VGint i;
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);
415 return;
417 if (!data || !is_aligned(data)) {
418 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
419 return;
421 if (width <= 0 || height <= 0) {
422 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
423 return;
426 /* make sure rendering has completed */
427 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
428 if (sx < 0) {
429 xoffset = -sx;
430 xoffset *= _vega_size_for_format(dataFormat);
431 width += sx;
432 sx = 0;
434 if (sy < 0) {
435 yoffset = -sy;
436 height += sy;
437 sy = 0;
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,
446 PIPE_TRANSFER_READ,
447 0, 0, width, height);
449 /* Do a row at a time to flip image data vertically */
450 for (i = 0; i < height; i++) {
451 #if 0
452 debug_printf("%d-%d == %d\n", sy, height, y);
453 #endif
454 pipe_get_tile_rgba(pipe, transfer, sx, y, width, 1, df);
455 y += yStep;
456 _vega_pack_rgba_span_float(ctx, width, temp, dataFormat,
457 dst + yoffset + xoffset);
458 dst += dataStride;
461 pipe->transfer_destroy(pipe, transfer);
465 void vegaCopyPixels(VGint dx, VGint dy,
466 VGint sx, VGint sy,
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);
475 return;
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)
481 return;
483 vg_validate_state(ctx);
484 /* make sure rendering has completed */
485 vgFinish();
487 vg_copy_surface(ctx, strb->surface, dx, dy,
488 strb->surface, sx, sy, width, height);