Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.       void *map;
  446.  
  447.       map = pipe_transfer_map(pipe, strb->texture,  0, 0,
  448.                               PIPE_TRANSFER_READ,
  449.                               0, 0, sx + width, stfb->height - sy,
  450.                               &transfer);
  451.  
  452.       /* Do a row at a time to flip image data vertically */
  453.       for (i = 0; i < height; i++) {
  454. #if 0
  455.          debug_printf("%d-%d  == %d\n", sy, height, y);
  456. #endif
  457.          pipe_get_tile_rgba(transfer, map, sx, y, width, 1, df);
  458.          y += yStep;
  459.          _vega_pack_rgba_span_float(ctx, width, temp, dataFormat,
  460.                                     dst + yoffset + xoffset);
  461.          dst += dataStride;
  462.       }
  463.  
  464.       pipe->transfer_unmap(pipe, transfer);
  465.    }
  466. }
  467.  
  468. void vegaCopyPixels(VGint dx, VGint dy,
  469.                     VGint sx, VGint sy,
  470.                     VGint width, VGint height)
  471. {
  472.    struct vg_context *ctx = vg_current_context();
  473.    struct st_framebuffer *stfb = ctx->draw_buffer;
  474.    struct st_renderbuffer *strb = stfb->strb;
  475.  
  476.    if (width <= 0 || height <= 0) {
  477.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  478.       return;
  479.    }
  480.  
  481.    /* do nothing if we copy from outside the fb */
  482.    if (dx >= (VGint)stfb->width || dy >= (VGint)stfb->height ||
  483.        sx >= (VGint)stfb->width || sy >= (VGint)stfb->height)
  484.       return;
  485.  
  486.    vg_validate_state(ctx);
  487.    /* make sure rendering has completed */
  488.    vegaFinish();
  489.  
  490.    vg_copy_surface(ctx, strb->surface, dx, dy,
  491.                    strb->surface, sx, sy, width, height);
  492. }
  493.