Squashed commit of the following:
[profile/ivi/mesa.git] / src / gallium / state_trackers / vega / image.c
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_translate.h"
30 #include "vg_context.h"
31 #include "matrix.h"
32 #include "renderer.h"
33 #include "util_array.h"
34 #include "api_consts.h"
35 #include "shaders_cache.h"
36 #include "shader.h"
37
38 #include "pipe/p_context.h"
39 #include "pipe/p_screen.h"
40 #include "util/u_inlines.h"
41 #include "util/u_blit.h"
42 #include "util/u_format.h"
43 #include "util/u_tile.h"
44 #include "util/u_memory.h"
45 #include "util/u_math.h"
46 #include "util/u_sampler.h"
47
48 static enum pipe_format vg_format_to_pipe(VGImageFormat format)
49 {
50    switch(format) {
51    case VG_sRGB_565:
52       return PIPE_FORMAT_B5G6R5_UNORM;
53    case VG_sRGBA_5551:
54       return PIPE_FORMAT_B5G5R5A1_UNORM;
55    case VG_sRGBA_4444:
56       return PIPE_FORMAT_B4G4R4A4_UNORM;
57    case VG_sL_8:
58    case VG_lL_8:
59       return PIPE_FORMAT_L8_UNORM;
60    case VG_BW_1:
61       return PIPE_FORMAT_B8G8R8A8_UNORM;
62    case VG_A_8:
63       return PIPE_FORMAT_A8_UNORM;
64 #ifdef OPENVG_VERSION_1_1
65    case VG_A_1:
66    case VG_A_4:
67       return PIPE_FORMAT_A8_UNORM;
68 #endif
69    default:
70       return PIPE_FORMAT_B8G8R8A8_UNORM;
71    }
72 }
73
74 static INLINE void vg_sync_size(VGfloat *src_loc, VGfloat *dst_loc)
75 {
76    src_loc[2] = MIN2(src_loc[2], dst_loc[2]);
77    src_loc[3] = MIN2(src_loc[3], dst_loc[3]);
78    dst_loc[2] = src_loc[2];
79    dst_loc[3] = src_loc[3];
80 }
81
82
83 static void vg_copy_texture(struct vg_context *ctx,
84                             struct pipe_resource *dst, VGint dx, VGint dy,
85                             struct pipe_sampler_view *src, VGint sx, VGint sy,
86                             VGint width, VGint height)
87 {
88    VGfloat dst_loc[4], src_loc[4];
89    VGfloat dst_bounds[4], src_bounds[4];
90    VGfloat src_shift[4], dst_shift[4], shift[4];
91
92    dst_loc[0] = dx;
93    dst_loc[1] = dy;
94    dst_loc[2] = width;
95    dst_loc[3] = height;
96    dst_bounds[0] = 0.f;
97    dst_bounds[1] = 0.f;
98    dst_bounds[2] = dst->width0;
99    dst_bounds[3] = dst->height0;
100
101    src_loc[0] = sx;
102    src_loc[1] = sy;
103    src_loc[2] = width;
104    src_loc[3] = height;
105    src_bounds[0] = 0.f;
106    src_bounds[1] = 0.f;
107    src_bounds[2] = src->texture->width0;
108    src_bounds[3] = src->texture->height0;
109
110    vg_bound_rect(src_loc, src_bounds, src_shift);
111    vg_bound_rect(dst_loc, dst_bounds, dst_shift);
112    shift[0] = src_shift[0] - dst_shift[0];
113    shift[1] = src_shift[1] - dst_shift[1];
114
115    if (shift[0] < 0)
116       vg_shift_rectx(src_loc, src_bounds, -shift[0]);
117    else
118       vg_shift_rectx(dst_loc, dst_bounds, shift[0]);
119
120    if (shift[1] < 0)
121       vg_shift_recty(src_loc, src_bounds, -shift[1]);
122    else
123       vg_shift_recty(dst_loc, dst_bounds, shift[1]);
124
125    vg_sync_size(src_loc, dst_loc);
126
127    if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
128        dst_loc[2] >= 0 && dst_loc[3] >= 0) {
129       renderer_copy_texture(ctx->renderer,
130                             src,
131                             src_loc[0],
132                             src_loc[1] + src_loc[3],
133                             src_loc[0] + src_loc[2],
134                             src_loc[1],
135                             dst,
136                             dst_loc[0],
137                             dst_loc[1] + dst_loc[3],
138                             dst_loc[0] + dst_loc[2],
139                             dst_loc[1]);
140    }
141
142 }
143
144 void vg_copy_surface(struct vg_context *ctx,
145                      struct pipe_surface *dst, VGint dx, VGint dy,
146                      struct pipe_surface *src, VGint sx, VGint sy,
147                      VGint width, VGint height)
148 {
149    VGfloat dst_loc[4], src_loc[4];
150    VGfloat dst_bounds[4], src_bounds[4];
151    VGfloat src_shift[4], dst_shift[4], shift[4];
152
153    dst_loc[0] = dx;
154    dst_loc[1] = dy;
155    dst_loc[2] = width;
156    dst_loc[3] = height;
157    dst_bounds[0] = 0.f;
158    dst_bounds[1] = 0.f;
159    dst_bounds[2] = dst->width;
160    dst_bounds[3] = dst->height;
161
162    src_loc[0] = sx;
163    src_loc[1] = sy;
164    src_loc[2] = width;
165    src_loc[3] = height;
166    src_bounds[0] = 0.f;
167    src_bounds[1] = 0.f;
168    src_bounds[2] = src->width;
169    src_bounds[3] = src->height;
170
171    vg_bound_rect(src_loc, src_bounds, src_shift);
172    vg_bound_rect(dst_loc, dst_bounds, dst_shift);
173    shift[0] = src_shift[0] - dst_shift[0];
174    shift[1] = src_shift[1] - dst_shift[1];
175
176    if (shift[0] < 0)
177       vg_shift_rectx(src_loc, src_bounds, -shift[0]);
178    else
179       vg_shift_rectx(dst_loc, dst_bounds, shift[0]);
180
181    if (shift[1] < 0)
182       vg_shift_recty(src_loc, src_bounds, -shift[1]);
183    else
184       vg_shift_recty(dst_loc, dst_bounds, shift[1]);
185
186    vg_sync_size(src_loc, dst_loc);
187
188    if (src_loc[2] > 0 && src_loc[3] > 0 &&
189        dst_loc[2] > 0 && dst_loc[3] > 0) {
190       if (src == dst)
191          renderer_copy_surface(ctx->renderer,
192                                src,
193                                src_loc[0],
194                                src->height - (src_loc[1] + src_loc[3]),
195                                src_loc[0] + src_loc[2],
196                                src->height - src_loc[1],
197                                dst,
198                                dst_loc[0],
199                                dst->height - (dst_loc[1] + dst_loc[3]),
200                                dst_loc[0] + dst_loc[2],
201                                dst->height - dst_loc[1],
202                                0, 0);
203       else
204          renderer_copy_surface(ctx->renderer,
205                                src,
206                                src_loc[0],
207                                src->height - src_loc[1],
208                                src_loc[0] + src_loc[2],
209                                src->height - (src_loc[1] + src_loc[3]),
210                                dst,
211                                dst_loc[0],
212                                dst->height - (dst_loc[1] + dst_loc[3]),
213                                dst_loc[0] + dst_loc[2],
214                                dst->height - dst_loc[1],
215                                0, 0);
216    }
217
218 }
219
220 static struct pipe_resource *image_texture(struct vg_image *img)
221 {
222    struct pipe_resource *tex = img->sampler_view->texture;
223    return tex;
224 }
225
226
227 static void image_cleari(struct vg_image *img, VGint clear_colori,
228                          VGint x, VGint y, VGint width, VGint height)
229 {
230    VGint *clearbuf;
231    VGint i;
232    VGfloat dwidth, dheight;
233
234    clearbuf = malloc(sizeof(VGint)*width*height);
235    for (i = 0; i < width*height; ++i)
236       clearbuf[i] = clear_colori;
237
238    dwidth = MIN2(width, img->width);
239    dheight = MIN2(height, img->height);
240
241    image_sub_data(img, clearbuf, width * sizeof(VGint),
242                   VG_sRGBA_8888,
243                   x, y, dwidth, dheight);
244    free(clearbuf);
245 }
246
247 struct vg_image * image_create(VGImageFormat format,
248                                VGint width, VGint height)
249 {
250    struct vg_context *ctx = vg_current_context();
251    struct pipe_context *pipe = ctx->pipe;
252    struct vg_image *image = CALLOC_STRUCT(vg_image);
253    enum pipe_format pformat = vg_format_to_pipe(format);
254    struct pipe_resource pt, *newtex;
255    struct pipe_sampler_view view_templ;
256    struct pipe_sampler_view *view;
257    struct pipe_screen *screen = ctx->pipe->screen;
258
259    vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE);
260
261    image->format = format;
262    image->width = width;
263    image->height = height;
264
265    image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
266    image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
267    image->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
268    image->sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
269    image->sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
270    image->sampler.normalized_coords = 1;
271
272    assert(screen->is_format_supported(screen, pformat, PIPE_TEXTURE_2D,
273                                       PIPE_BIND_SAMPLER_VIEW, 0));
274
275    memset(&pt, 0, sizeof(pt));
276    pt.target = PIPE_TEXTURE_2D;
277    pt.format = pformat;
278    pt.last_level = 0;
279    pt.width0 = width;
280    pt.height0 = height;
281    pt.depth0 = 1;
282    pt.bind = PIPE_BIND_SAMPLER_VIEW;
283
284    newtex = screen->resource_create(screen, &pt);
285
286    debug_assert(newtex);
287
288    u_sampler_view_default_template(&view_templ, newtex, newtex->format);
289    view = pipe->create_sampler_view(pipe, newtex, &view_templ);
290    /* want the texture to go away if the view is freed */
291    pipe_resource_reference(&newtex, NULL);
292
293    image->sampler_view = view;
294
295    vg_context_add_object(ctx, VG_OBJECT_IMAGE, image);
296
297    image_cleari(image, 0, 0, 0, image->width, image->height);
298    return image;
299 }
300
301 void image_destroy(struct vg_image *img)
302 {
303    struct vg_context *ctx = vg_current_context();
304    vg_context_remove_object(ctx, VG_OBJECT_IMAGE, img);
305
306
307    if (img->parent) {
308       /* remove img from the parent child array */
309       int idx;
310       struct vg_image **array =
311          (struct vg_image **)img->parent->children_array->data;
312
313       for (idx = 0; idx < img->parent->children_array->num_elements; ++idx) {
314          struct vg_image *child = array[idx];
315          if (child == img) {
316             break;
317          }
318       }
319       debug_assert(idx < img->parent->children_array->num_elements);
320       array_remove_element(img->parent->children_array, idx);
321    }
322
323    if (img->children_array && img->children_array->num_elements) {
324       /* reparent the children */
325       VGint i;
326       struct vg_image *parent = img->parent;
327       struct vg_image **children =
328          (struct vg_image **)img->children_array->data;
329       if (!parent) {
330          VGint min_x = children[0]->x;
331          parent = children[0];
332
333          for (i = 1; i < img->children_array->num_elements; ++i) {
334             struct vg_image *child = children[i];
335             if (child->x < min_x) {
336                parent = child;
337             }
338          }
339       }
340
341       for (i = 0; i < img->children_array->num_elements; ++i) {
342          struct vg_image *child = children[i];
343          if (child != parent) {
344             child->parent = parent;
345             if (!parent->children_array) {
346                parent->children_array = array_create(
347                   sizeof(struct vg_image*));
348             }
349             array_append_data(parent->children_array,
350                               &child, 1);
351          } else
352             child->parent = NULL;
353       }
354       array_destroy(img->children_array);
355    }
356
357    pipe_sampler_view_reference(&img->sampler_view, NULL);
358    free(img);
359 }
360
361 void image_clear(struct vg_image *img,
362                  VGint x, VGint y, VGint width, VGint height)
363 {
364    struct vg_context *ctx = vg_current_context();
365    VGfloat *clear_colorf = ctx->state.vg.clear_color;
366    VGubyte r, g, b ,a;
367    VGint clear_colori;
368    /* FIXME: this is very nasty */
369    r = float_to_ubyte(clear_colorf[0]);
370    g = float_to_ubyte(clear_colorf[1]);
371    b = float_to_ubyte(clear_colorf[2]);
372    a = float_to_ubyte(clear_colorf[3]);
373    clear_colori = r << 24 | g << 16 | b << 8 | a;
374    image_cleari(img, clear_colori, x, y, width, height);
375 }
376
377 void image_sub_data(struct vg_image *image,
378                     const void * data,
379                     VGint dataStride,
380                     VGImageFormat dataFormat,
381                     VGint x, VGint y,
382                     VGint width, VGint height)
383 {
384    const VGint yStep = 1;
385    VGubyte *src = (VGubyte *)data;
386    VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
387    VGfloat *df = (VGfloat*)temp;
388    VGint i;
389    struct vg_context *ctx = vg_current_context();
390    struct pipe_context *pipe = ctx->pipe;
391    struct pipe_resource *texture = image_texture(image);
392    VGint xoffset = 0, yoffset = 0;
393
394    if (x < 0) {
395       xoffset -= x;
396       width += x;
397       x = 0;
398    }
399    if (y < 0) {
400       yoffset -= y;
401       height += y;
402       y = 0;
403    }
404
405    if (width <= 0 || height <= 0) {
406       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
407       return;
408    }
409
410    if (x > image->width || y > image->width) {
411       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
412       return;
413    }
414
415    if (x + width > image->width) {
416       width = image->width - x;
417    }
418
419    if (y + height > image->height) {
420       height = image->height - y;
421    }
422
423    { /* upload color_data */
424       struct pipe_transfer *transfer = pipe_get_transfer(
425          pipe, texture, 0, 0, 0,
426          PIPE_TRANSFER_WRITE, 0, 0, texture->width0, texture->height0);
427       src += (dataStride * yoffset);
428       for (i = 0; i < height; i++) {
429          _vega_unpack_float_span_rgba(ctx, width, xoffset, src, dataFormat, temp);
430          pipe_put_tile_rgba(pipe, transfer, x+image->x, y+image->y, width, 1, df);
431          y += yStep;
432          src += dataStride;
433       }
434       pipe->transfer_destroy(pipe, transfer);
435    }
436 }
437
438 void image_get_sub_data(struct vg_image * image,
439                         void * data,
440                         VGint dataStride,
441                         VGImageFormat dataFormat,
442                         VGint sx, VGint sy,
443                         VGint width, VGint height)
444 {
445    struct vg_context *ctx = vg_current_context();
446    struct pipe_context *pipe = ctx->pipe;
447    VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
448    VGfloat *df = (VGfloat*)temp;
449    VGint y = 0, yStep = 1;
450    VGint i;
451    VGubyte *dst = (VGubyte *)data;
452
453    {
454       struct pipe_transfer *transfer =
455          pipe_get_transfer(pipe,
456                                   image->sampler_view->texture,  0, 0, 0,
457                                   PIPE_TRANSFER_READ,
458                                   0, 0,
459                                   image->x + image->width,
460                                   image->y + image->height);
461       /* Do a row at a time to flip image data vertically */
462       for (i = 0; i < height; i++) {
463 #if 0
464          debug_printf("%d-%d  == %d\n", sy, height, y);
465 #endif
466          pipe_get_tile_rgba(pipe, transfer, sx+image->x, y, width, 1, df);
467          y += yStep;
468          _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst);
469          dst += dataStride;
470       }
471
472       pipe->transfer_destroy(pipe, transfer);
473    }
474 }
475
476 struct vg_image * image_child_image(struct vg_image *parent,
477                                     VGint x, VGint y,
478                                     VGint width, VGint height)
479 {
480    struct vg_context *ctx = vg_current_context();
481    struct vg_image *image = CALLOC_STRUCT(vg_image);
482
483    vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE);
484
485    image->x = parent->x + x;
486    image->y = parent->y + y;
487    image->width = width;
488    image->height = height;
489    image->parent = parent;
490    image->sampler_view = NULL;
491    pipe_sampler_view_reference(&image->sampler_view,
492                                parent->sampler_view);
493
494    image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
495    image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
496    image->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
497    image->sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
498    image->sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
499    image->sampler.normalized_coords = 1;
500
501    if (!parent->children_array)
502       parent->children_array = array_create(
503          sizeof(struct vg_image*));
504
505    array_append_data(parent->children_array,
506                      &image, 1);
507
508    vg_context_add_object(ctx, VG_OBJECT_IMAGE, image);
509
510    return image;
511 }
512
513 void image_copy(struct vg_image *dst, VGint dx, VGint dy,
514                 struct vg_image *src, VGint sx, VGint sy,
515                 VGint width, VGint height,
516                 VGboolean dither)
517 {
518    struct vg_context *ctx = vg_current_context();
519
520    if (width <= 0 || height <= 0) {
521       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
522       return;
523    }
524    /* make sure rendering has completed */
525    ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
526    vg_copy_texture(ctx, dst->sampler_view->texture, dst->x + dx, dst->y + dy,
527                    src->sampler_view, src->x + sx, src->y + sy, width, height);
528 }
529
530 void image_draw(struct vg_image *img)
531 {
532    struct vg_context *ctx = vg_current_context();
533    VGfloat x1, y1;
534    VGfloat x2, y2;
535    VGfloat x3, y3;
536    VGfloat x4, y4;
537    struct matrix *matrix;
538
539    x1 = 0;
540    y1 = 0;
541    x2 = img->width;
542    y2 = 0;
543    x3 = img->width;
544    y3 = img->height;
545    x4 = 0;
546    y4 = img->height;
547
548    matrix = &ctx->state.vg.image_user_to_surface_matrix;
549
550    matrix_map_point(matrix, x1, y1, &x1, &y1);
551    matrix_map_point(matrix, x2, y2, &x2, &y2);
552    matrix_map_point(matrix, x3, y3, &x3, &y3);
553    matrix_map_point(matrix, x4, y4, &x4, &y4);
554
555    shader_set_drawing_image(ctx->shader, VG_TRUE);
556    shader_set_paint(ctx->shader, ctx->state.vg.fill_paint);
557    shader_set_image(ctx->shader, img);
558    shader_bind(ctx->shader);
559
560    renderer_texture_quad(ctx->renderer, image_texture(img),
561                          img->x, img->y, img->x + img->width, img->y + img->height,
562                          x1, y1, x2, y2, x3, y3, x4, y4);
563 }
564
565 void image_set_pixels(VGint dx, VGint dy,
566                       struct vg_image *src, VGint sx, VGint sy,
567                       VGint width, VGint height)
568 {
569    struct vg_context *ctx = vg_current_context();
570    struct pipe_context *pipe = ctx->pipe;
571    struct pipe_screen *screen = pipe->screen;
572    struct pipe_surface *surf;
573    struct st_renderbuffer *strb = ctx->draw_buffer->strb;
574
575    /* make sure rendering has completed */
576    pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
577
578    surf = screen->get_tex_surface(screen, image_texture(src),  0, 0, 0,
579                                   PIPE_BIND_BLIT_SOURCE);
580
581    vg_copy_surface(ctx, strb->surface, dx, dy,
582                    surf, sx+src->x, sy+src->y, width, height);
583
584    screen->tex_surface_destroy(surf);
585 }
586
587 void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy,
588                       VGint sx, VGint sy,
589                       VGint width, VGint height)
590 {
591    struct vg_context *ctx = vg_current_context();
592    struct pipe_context *pipe = ctx->pipe;
593    struct pipe_screen *screen = pipe->screen;
594    struct pipe_surface *surf;
595    struct st_renderbuffer *strb = ctx->draw_buffer->strb;
596
597    /* flip the y coordinates */
598    /*dy = dst->height - dy - height;*/
599
600    /* make sure rendering has completed */
601    pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
602
603    surf = screen->get_tex_surface(screen, image_texture(dst),  0, 0, 0,
604                                   PIPE_BIND_BLIT_SOURCE);
605
606    vg_copy_surface(ctx, surf, dst->x + dx, dst->y + dy,
607                    strb->surface, sx, sy, width, height);
608
609    pipe_surface_reference(&surf, NULL);
610 }
611
612
613 VGboolean vg_image_overlaps(struct vg_image *dst,
614                             struct vg_image *src)
615 {
616    if (dst == src || dst->parent == src ||
617        dst == src->parent)
618       return VG_TRUE;
619    if (dst->parent && dst->parent == src->parent) {
620       VGfloat left1 = dst->x;
621       VGfloat left2 = src->x;
622       VGfloat right1 = dst->x + dst->width;
623       VGfloat right2 = src->x + src->width;
624       VGfloat bottom1 = dst->y;
625       VGfloat bottom2 = src->y;
626       VGfloat top1 = dst->y + dst->height;
627       VGfloat top2 = src->y + src->height;
628
629       return !(left2 > right1 || right2 < left1 ||
630                top2 > bottom1 || bottom2 < top1);
631    }
632    return VG_FALSE;
633 }
634
635 VGint image_bind_samplers(struct vg_image *img, struct pipe_sampler_state **samplers,
636                           struct pipe_sampler_view **sampler_views)
637 {
638    img->sampler.min_img_filter = image_sampler_filter(img->base.ctx);
639    img->sampler.mag_img_filter = image_sampler_filter(img->base.ctx);
640    samplers[3] = &img->sampler;
641    sampler_views[3] = img->sampler_view;
642    return 1;
643 }
644
645 VGint image_sampler_filter(struct vg_context *ctx)
646 {
647     switch(ctx->state.vg.image_quality) {
648     case VG_IMAGE_QUALITY_NONANTIALIASED:
649        return PIPE_TEX_FILTER_NEAREST;
650        break;
651     case VG_IMAGE_QUALITY_FASTER:
652        return PIPE_TEX_FILTER_NEAREST;
653        break;
654     case VG_IMAGE_QUALITY_BETTER:
655        /* possibly use anisotropic filtering */
656        return PIPE_TEX_FILTER_LINEAR;
657        break;
658     default:
659        debug_printf("Unknown image quality");
660     }
661     return PIPE_TEX_FILTER_NEAREST;
662 }