api_images.c revision 75143ef05576ee9f25ee176bc28c3c4d03705bf5
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 "image.h" 35#include "api.h" 36 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" 43 44static INLINE VGboolean supported_image_format(VGImageFormat format) 45{ 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; 92 } 93 return VG_FALSE; 94} 95 96VGImage vegaCreateImage(VGImageFormat format, 97 VGint width, VGint height, 98 VGbitfield allowedQuality) 99{ 100 struct vg_context *ctx = vg_current_context(); 101 102 if (!supported_image_format(format)) { 103 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 104 return VG_INVALID_HANDLE; 105 } 106 if (width <= 0 || height <= 0) { 107 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 108 return VG_INVALID_HANDLE; 109 } 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; 114 } 115 if (width * height > vgGeti(VG_MAX_IMAGE_PIXELS)) { 116 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 117 return VG_INVALID_HANDLE; 118 } 119 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; 125 } 126 127 return (VGImage)image_create(format, width, height); 128} 129 130void vegaDestroyImage(VGImage image) 131{ 132 struct vg_context *ctx = vg_current_context(); 133 struct vg_image *img = (struct vg_image *)image; 134 135 if (image == VG_INVALID_HANDLE) { 136 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 137 return; 138 } 139 if (!vg_object_is_valid((void*)image, VG_OBJECT_IMAGE)) { 140 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 141 return; 142 } 143 image_destroy(img); 144} 145 146void vegaClearImage(VGImage image, 147 VGint x, VGint y, 148 VGint width, VGint height) 149{ 150 struct vg_context *ctx = vg_current_context(); 151 struct vg_image *img; 152 153 if (image == VG_INVALID_HANDLE) { 154 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 155 return; 156 } 157 if (width <= 0 || height <= 0) { 158 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 159 return; 160 } 161 162 img = (struct vg_image*)image; 163 164 if (x + width < 0 || y + height < 0) 165 return; 166 167 image_clear(img, x, y, width, height); 168 169} 170 171void vegaImageSubData(VGImage image, 172 const void * data, 173 VGint dataStride, 174 VGImageFormat dataFormat, 175 VGint x, VGint y, 176 VGint width, VGint height) 177{ 178 struct vg_context *ctx = vg_current_context(); 179 struct vg_image *img; 180 181 if (image == VG_INVALID_HANDLE) { 182 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 183 return; 184 } 185 if (!supported_image_format(dataFormat)) { 186 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 187 return; 188 } 189 if (width <= 0 || height <= 0 || !data || !is_aligned(data)) { 190 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 191 return; 192 } 193 194 img = (struct vg_image*)(image); 195 image_sub_data(img, data, dataStride, dataFormat, 196 x, y, width, height); 197} 198 199void vegaGetImageSubData(VGImage image, 200 void * data, 201 VGint dataStride, 202 VGImageFormat dataFormat, 203 VGint x, VGint y, 204 VGint width, VGint height) 205{ 206 struct vg_context *ctx = vg_current_context(); 207 struct vg_image *img; 208 209 if (image == VG_INVALID_HANDLE) { 210 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 211 return; 212 } 213 if (!supported_image_format(dataFormat)) { 214 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 215 return; 216 } 217 if (width <= 0 || height <= 0 || !data || !is_aligned(data)) { 218 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 219 return; 220 } 221 img = (struct vg_image*)image; 222 image_get_sub_data(img, data, dataStride, dataFormat, 223 x, y, width, height); 224} 225 226VGImage vegaChildImage(VGImage parent, 227 VGint x, VGint y, 228 VGint width, VGint height) 229{ 230 struct vg_context *ctx = vg_current_context(); 231 struct vg_image *p; 232 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; 238 } 239 if (width <= 0 || height <= 0 || x < 0 || y < 0) { 240 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 241 return VG_INVALID_HANDLE; 242 } 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; 247 } 248 if (x + width > p->width || y + height > p->height) { 249 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 250 return VG_INVALID_HANDLE; 251 } 252 253 return (VGImage)image_child_image(p, x, y, width, height); 254} 255 256VGImage vegaGetParent(VGImage image) 257{ 258 struct vg_context *ctx = vg_current_context(); 259 struct vg_image *img; 260 261 if (image == VG_INVALID_HANDLE) { 262 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 263 return VG_INVALID_HANDLE; 264 } 265 266 img = (struct vg_image*)image; 267 if (img->parent) 268 return (VGImage)img->parent; 269 else 270 return image; 271} 272 273void vegaCopyImage(VGImage dst, VGint dx, VGint dy, 274 VGImage src, VGint sx, VGint sy, 275 VGint width, VGint height, 276 VGboolean dither) 277{ 278 struct vg_context *ctx = vg_current_context(); 279 280 if (src == VG_INVALID_HANDLE || dst == VG_INVALID_HANDLE) { 281 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 282 return; 283 } 284 285 if (width <= 0 || height <= 0) { 286 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 287 return; 288 } 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); 293} 294 295void vegaDrawImage(VGImage image) 296{ 297 struct vg_context *ctx = vg_current_context(); 298 299 if (!ctx) 300 return; 301 302 if (image == VG_INVALID_HANDLE) { 303 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 304 return; 305 } 306 307 vg_validate_state(ctx); 308 image_draw((struct vg_image*)image); 309} 310 311void 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, (struct vg_image*)src, sx, sy, width, 328 height); 329} 330 331void 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 = (struct vg_image*)dst; 348 349 image_get_pixels(img, dx, dy, 350 sx, sy, width, height); 351} 352 353void 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 struct pipe_context *pipe = ctx->pipe; 360 361 if (!supported_image_format(dataFormat)) { 362 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 363 return; 364 } 365 if (!data || !is_aligned(data)) { 366 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 367 return; 368 } 369 if (width <= 0 || height <= 0) { 370 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 371 return; 372 } 373 374 vg_validate_state(ctx); 375 { 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); 389 } 390 /* make sure rendering has completed */ 391 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 392} 393 394void vegaReadPixels(void * data, VGint dataStride, 395 VGImageFormat dataFormat, 396 VGint sx, VGint sy, 397 VGint width, VGint height) 398{ 399 struct vg_context *ctx = vg_current_context(); 400 struct pipe_context *pipe = ctx->pipe; 401 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; 405 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; 412 413 if (!supported_image_format(dataFormat)) { 414 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 415 return; 416 } 417 if (!data || !is_aligned(data)) { 418 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 419 return; 420 } 421 if (width <= 0 || height <= 0) { 422 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 423 return; 424 } 425 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; 433 } 434 if (sy < 0) { 435 yoffset = -sy; 436 height += sy; 437 sy = 0; 438 y = (fb->height - sy) - 1; 439 yoffset *= dataStride; 440 } 441 442 { 443 struct pipe_transfer *transfer; 444 445 transfer = pipe_get_transfer(pipe, strb->texture, 0, 0, 0, 446 PIPE_TRANSFER_READ, 447 0, 0, width, height); 448 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; 459 } 460 461 pipe->transfer_destroy(pipe, transfer); 462 } 463} 464 465void vegaCopyPixels(VGint dx, VGint dy, 466 VGint sx, VGint sy, 467 VGint width, VGint height) 468{ 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; 472 473 if (width <= 0 || height <= 0) { 474 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 475 return; 476 } 477 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; 482 483 vg_validate_state(ctx); 484 /* make sure rendering has completed */ 485 vgFinish(); 486 487 vg_copy_surface(ctx, strb->surface, dx, dy, 488 strb->surface, sx, sy, width, height); 489} 490