~ubuntu-branches/ubuntu/precise/mesa-lts-quantal/precise-updates

« back to all changes in this revision

Viewing changes to src/gallium/state_trackers/vega/renderer.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2012-11-30 20:58:34 UTC
  • Revision ID: package-import@ubuntu.com-20121130205834-gazuvne3fpwlf012
Tags: upstream-9.0
ImportĀ upstreamĀ versionĀ 9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**************************************************************************
 
2
 *
 
3
 * Copyright 2009 VMware, Inc.  All Rights Reserved.
 
4
 * Copyright 2010 LunarG, Inc.  All Rights Reserved.
 
5
 *
 
6
 * Permission is hereby granted, free of charge, to any person obtaining a
 
7
 * copy of this software and associated documentation files (the
 
8
 * "Software"), to deal in the Software without restriction, including
 
9
 * without limitation the rights to use, copy, modify, merge, publish,
 
10
 * distribute, sub license, and/or sell copies of the Software, and to
 
11
 * permit persons to whom the Software is furnished to do so, subject to
 
12
 * the following conditions:
 
13
 *
 
14
 * The above copyright notice and this permission notice (including the
 
15
 * next paragraph) shall be included in all copies or substantial portions
 
16
 * of the Software.
 
17
 *
 
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
19
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 
21
 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
 
22
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 
23
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 
24
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
25
 *
 
26
 **************************************************************************/
 
27
 
 
28
#include "renderer.h"
 
29
 
 
30
#include "vg_context.h"
 
31
 
 
32
#include "pipe/p_context.h"
 
33
#include "pipe/p_state.h"
 
34
#include "util/u_inlines.h"
 
35
#include "pipe/p_screen.h"
 
36
#include "pipe/p_shader_tokens.h"
 
37
 
 
38
#include "util/u_draw_quad.h"
 
39
#include "util/u_simple_shaders.h"
 
40
#include "util/u_memory.h"
 
41
#include "util/u_sampler.h"
 
42
#include "util/u_surface.h"
 
43
#include "util/u_math.h"
 
44
#include "util/u_format.h"
 
45
 
 
46
#include "cso_cache/cso_context.h"
 
47
#include "tgsi/tgsi_ureg.h"
 
48
 
 
49
typedef enum {
 
50
   RENDERER_STATE_INIT,
 
51
   RENDERER_STATE_COPY,
 
52
   RENDERER_STATE_DRAWTEX,
 
53
   RENDERER_STATE_SCISSOR,
 
54
   RENDERER_STATE_CLEAR,
 
55
   RENDERER_STATE_FILTER,
 
56
   RENDERER_STATE_POLYGON_STENCIL,
 
57
   RENDERER_STATE_POLYGON_FILL,
 
58
   NUM_RENDERER_STATES
 
59
} RendererState;
 
60
 
 
61
typedef enum {
 
62
   RENDERER_VS_PLAIN,
 
63
   RENDERER_VS_COLOR,
 
64
   RENDERER_VS_TEXTURE,
 
65
   NUM_RENDERER_VS
 
66
} RendererVs;
 
67
 
 
68
typedef enum {
 
69
   RENDERER_FS_COLOR,
 
70
   RENDERER_FS_TEXTURE,
 
71
   RENDERER_FS_SCISSOR,
 
72
   RENDERER_FS_WHITE,
 
73
   NUM_RENDERER_FS
 
74
} RendererFs;
 
75
 
 
76
struct renderer {
 
77
   struct pipe_context *pipe;
 
78
   struct cso_context *cso;
 
79
 
 
80
   VGbitfield dirty;
 
81
   struct {
 
82
      struct pipe_rasterizer_state rasterizer;
 
83
      struct pipe_depth_stencil_alpha_state dsa;
 
84
      struct pipe_framebuffer_state fb;
 
85
   } g3d;
 
86
   struct matrix projection;
 
87
 
 
88
   struct matrix mvp;
 
89
   struct pipe_resource *vs_cbuf;
 
90
 
 
91
   struct pipe_resource *fs_cbuf;
 
92
   VGfloat fs_cbuf_data[32];
 
93
   VGint fs_cbuf_len;
 
94
 
 
95
   struct pipe_vertex_element velems[2];
 
96
   VGfloat vertices[4][2][4];
 
97
 
 
98
   void *cached_vs[NUM_RENDERER_VS];
 
99
   void *cached_fs[NUM_RENDERER_FS];
 
100
 
 
101
   RendererState state;
 
102
 
 
103
   /* state data */
 
104
   union {
 
105
      struct {
 
106
         VGint tex_width;
 
107
         VGint tex_height;
 
108
      } copy;
 
109
 
 
110
      struct {
 
111
         VGint tex_width;
 
112
         VGint tex_height;
 
113
      } drawtex;
 
114
 
 
115
      struct {
 
116
         VGboolean restore_dsa;
 
117
      } scissor;
 
118
 
 
119
      struct {
 
120
         VGboolean use_sampler;
 
121
         VGint tex_width, tex_height;
 
122
      } filter;
 
123
 
 
124
      struct {
 
125
         struct pipe_depth_stencil_alpha_state dsa;
 
126
         VGboolean manual_two_sides;
 
127
         VGboolean restore_dsa;
 
128
      } polygon_stencil;
 
129
   } u;
 
130
};
 
131
 
 
132
/**
 
133
 * Return VG_TRUE if the renderer can use the resource as the asked bindings.
 
134
 */
 
135
static VGboolean renderer_can_support(struct renderer *renderer,
 
136
                                      struct pipe_resource *res,
 
137
                                      unsigned bindings)
 
138
{
 
139
   struct pipe_screen *screen = renderer->pipe->screen;
 
140
 
 
141
   return screen->is_format_supported(screen,
 
142
         res->format, res->target, 0, bindings);
 
143
}
 
144
 
 
145
/**
 
146
 * Set the model-view-projection matrix used by vertex shaders.
 
147
 */
 
148
static void renderer_set_mvp(struct renderer *renderer,
 
149
                             const struct matrix *mvp)
 
150
{
 
151
   struct matrix *cur = &renderer->mvp;
 
152
   struct pipe_resource *cbuf;
 
153
   VGfloat consts[3][4];
 
154
   VGint i;
 
155
 
 
156
   /* projection only */
 
157
   if (!mvp)
 
158
      mvp = &renderer->projection;
 
159
 
 
160
   /* re-upload only if necessary */
 
161
   if (memcmp(cur, mvp, sizeof(*mvp)) == 0)
 
162
      return;
 
163
 
 
164
   /* 3x3 matrix to 3 constant vectors (no Z) */
 
165
   for (i = 0; i < 3; i++) {
 
166
      consts[i][0] = mvp->m[i + 0];
 
167
      consts[i][1] = mvp->m[i + 3];
 
168
      consts[i][2] = 0.0f;
 
169
      consts[i][3] = mvp->m[i + 6];
 
170
   }
 
171
 
 
172
   cbuf = renderer->vs_cbuf;
 
173
   pipe_resource_reference(&cbuf, NULL);
 
174
   cbuf = pipe_buffer_create(renderer->pipe->screen,
 
175
                             PIPE_BIND_CONSTANT_BUFFER,
 
176
                             PIPE_USAGE_STATIC,
 
177
                             sizeof(consts));
 
178
   if (cbuf) {
 
179
      pipe_buffer_write(renderer->pipe, cbuf,
 
180
            0, sizeof(consts), consts);
 
181
   }
 
182
   pipe_set_constant_buffer(renderer->pipe,
 
183
         PIPE_SHADER_VERTEX, 0, cbuf);
 
184
 
 
185
   memcpy(cur, mvp, sizeof(*mvp));
 
186
   renderer->vs_cbuf = cbuf;
 
187
}
 
188
 
 
189
/**
 
190
 * Create a simple vertex shader that passes through position and the given
 
191
 * attribute.
 
192
 */
 
193
static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
 
194
{
 
195
   struct ureg_program *ureg;
 
196
   struct ureg_src src[2], constants[3];
 
197
   struct ureg_dst dst[2], tmp;
 
198
   int i;
 
199
 
 
200
   ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
 
201
   if (!ureg)
 
202
      return NULL;
 
203
 
 
204
   /* position is in user coordinates */
 
205
   src[0] = ureg_DECL_vs_input(ureg, 0);
 
206
   dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
 
207
   tmp = ureg_DECL_temporary(ureg);
 
208
   for (i = 0; i < Elements(constants); i++)
 
209
      constants[i] = ureg_DECL_constant(ureg, i);
 
210
 
 
211
   /* transform to clipped coordinates */
 
212
   ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), src[0], constants[0]);
 
213
   ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), src[0], constants[1]);
 
214
   ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), src[0]);
 
215
   ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), src[0], constants[2]);
 
216
   ureg_MOV(ureg, dst[0], ureg_src(tmp));
 
217
 
 
218
   if (semantic_name >= 0) {
 
219
      src[1] = ureg_DECL_vs_input(ureg, 1);
 
220
      dst[1] = ureg_DECL_output(ureg, semantic_name, 0);
 
221
      ureg_MOV(ureg, dst[1], src[1]);
 
222
   }
 
223
 
 
224
   ureg_END(ureg);
 
225
 
 
226
   return ureg_create_shader_and_destroy(ureg, pipe);
 
227
}
 
228
 
 
229
/**
 
230
 * Set renderer vertex shader.
 
231
 *
 
232
 * This function modifies vertex_shader state.
 
233
 */
 
234
static void renderer_set_vs(struct renderer *r, RendererVs id)
 
235
{
 
236
   /* create as needed */
 
237
   if (!r->cached_vs[id]) {
 
238
      int semantic_name = -1;
 
239
 
 
240
      switch (id) {
 
241
      case RENDERER_VS_PLAIN:
 
242
         break;
 
243
      case RENDERER_VS_COLOR:
 
244
         semantic_name = TGSI_SEMANTIC_COLOR;
 
245
         break;
 
246
      case RENDERER_VS_TEXTURE:
 
247
         semantic_name = TGSI_SEMANTIC_GENERIC;
 
248
         break;
 
249
      default:
 
250
         assert(!"Unknown renderer vs id");
 
251
         break;
 
252
      }
 
253
 
 
254
      r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name);
 
255
   }
 
256
 
 
257
   cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]);
 
258
}
 
259
 
 
260
/**
 
261
 * Create a simple fragment shader that sets the depth to 0.0f.
 
262
 */
 
263
static void *create_scissor_fs(struct pipe_context *pipe)
 
264
{
 
265
   struct ureg_program *ureg;
 
266
   struct ureg_dst out;
 
267
   struct ureg_src imm;
 
268
 
 
269
   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
 
270
   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
 
271
   imm = ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f);
 
272
 
 
273
   ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm);
 
274
   ureg_END(ureg);
 
275
 
 
276
   return ureg_create_shader_and_destroy(ureg, pipe);
 
277
}
 
278
 
 
279
/**
 
280
 * Create a simple fragment shader that sets the color to white.
 
281
 */
 
282
static void *create_white_fs(struct pipe_context *pipe)
 
283
{
 
284
   struct ureg_program *ureg;
 
285
   struct ureg_dst out;
 
286
   struct ureg_src imm;
 
287
 
 
288
   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
 
289
   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
 
290
   imm = ureg_imm4f(ureg, 1.0f, 1.0f, 1.0f, 1.0f);
 
291
 
 
292
   ureg_MOV(ureg, out, imm);
 
293
   ureg_END(ureg);
 
294
 
 
295
   return ureg_create_shader_and_destroy(ureg, pipe);
 
296
}
 
297
 
 
298
/**
 
299
 * Set renderer fragment shader.
 
300
 *
 
301
 * This function modifies fragment_shader state.
 
302
 */
 
303
static void renderer_set_fs(struct renderer *r, RendererFs id)
 
304
{
 
305
   /* create as needed */
 
306
   if (!r->cached_fs[id]) {
 
307
      void *fs = NULL;
 
308
 
 
309
      switch (id) {
 
310
      case RENDERER_FS_COLOR:
 
311
         fs = util_make_fragment_passthrough_shader(r->pipe);
 
312
         break;
 
313
      case RENDERER_FS_TEXTURE:
 
314
         fs = util_make_fragment_tex_shader(r->pipe,
 
315
               TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR);
 
316
         break;
 
317
      case RENDERER_FS_SCISSOR:
 
318
         fs = create_scissor_fs(r->pipe);
 
319
         break;
 
320
      case RENDERER_FS_WHITE:
 
321
         fs = create_white_fs(r->pipe);
 
322
         break;
 
323
      default:
 
324
         assert(!"Unknown renderer fs id");
 
325
         break;
 
326
      }
 
327
 
 
328
      r->cached_fs[id] = fs;
 
329
   }
 
330
 
 
331
   cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]);
 
332
}
 
333
 
 
334
typedef enum {
 
335
   VEGA_Y0_TOP,
 
336
   VEGA_Y0_BOTTOM
 
337
} VegaOrientation;
 
338
 
 
339
static void vg_set_viewport(struct renderer *r,
 
340
                            VegaOrientation orientation)
 
341
{
 
342
   const struct pipe_framebuffer_state *fb = &r->g3d.fb;
 
343
   struct pipe_viewport_state viewport;
 
344
   VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
 
345
 
 
346
   viewport.scale[0] =  fb->width / 2.f;
 
347
   viewport.scale[1] =  fb->height / y_scale;
 
348
   viewport.scale[2] =  1.0;
 
349
   viewport.scale[3] =  1.0;
 
350
   viewport.translate[0] = fb->width / 2.f;
 
351
   viewport.translate[1] = fb->height / 2.f;
 
352
   viewport.translate[2] = 0.0;
 
353
   viewport.translate[3] = 0.0;
 
354
 
 
355
   cso_set_viewport(r->cso, &viewport);
 
356
}
 
357
 
 
358
/**
 
359
 * Set renderer target.
 
360
 *
 
361
 * This function modifies framebuffer and viewport states.
 
362
 */
 
363
static void renderer_set_target(struct renderer *r,
 
364
                                struct pipe_surface *cbuf,
 
365
                                struct pipe_surface *zsbuf,
 
366
                                VGboolean y0_top)
 
367
{
 
368
   struct pipe_framebuffer_state fb;
 
369
 
 
370
   memset(&fb, 0, sizeof(fb));
 
371
   fb.width = cbuf->width;
 
372
   fb.height = cbuf->height;
 
373
   fb.cbufs[0] = cbuf;
 
374
   fb.nr_cbufs = 1;
 
375
   fb.zsbuf = zsbuf;
 
376
   cso_set_framebuffer(r->cso, &fb);
 
377
 
 
378
   vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM);
 
379
}
 
380
 
 
381
/**
 
382
 * Set renderer blend state.  Blending is disabled.
 
383
 *
 
384
 * This function modifies blend state.
 
385
 */
 
386
static void renderer_set_blend(struct renderer *r,
 
387
                               VGbitfield channel_mask)
 
388
{
 
389
   struct pipe_blend_state blend;
 
390
 
 
391
   memset(&blend, 0, sizeof(blend));
 
392
 
 
393
   blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
 
394
   blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
 
395
   blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
 
396
   blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
 
397
 
 
398
   if (channel_mask & VG_RED)
 
399
      blend.rt[0].colormask |= PIPE_MASK_R;
 
400
   if (channel_mask & VG_GREEN)
 
401
      blend.rt[0].colormask |= PIPE_MASK_G;
 
402
   if (channel_mask & VG_BLUE)
 
403
      blend.rt[0].colormask |= PIPE_MASK_B;
 
404
   if (channel_mask & VG_ALPHA)
 
405
      blend.rt[0].colormask |= PIPE_MASK_A;
 
406
 
 
407
   cso_set_blend(r->cso, &blend);
 
408
}
 
409
 
 
410
/**
 
411
 * Set renderer sampler and view states.
 
412
 *
 
413
 * This function modifies samplers and fragment_sampler_views states.
 
414
 */
 
415
static void renderer_set_samplers(struct renderer *r,
 
416
                                  uint num_views,
 
417
                                  struct pipe_sampler_view **views)
 
418
{
 
419
   struct pipe_sampler_state sampler;
 
420
   unsigned tex_filter = PIPE_TEX_FILTER_NEAREST;
 
421
   unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
 
422
   uint i;
 
423
 
 
424
   memset(&sampler, 0, sizeof(sampler));
 
425
 
 
426
   sampler.min_img_filter = tex_filter;
 
427
   sampler.mag_img_filter = tex_filter;
 
428
   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
 
429
 
 
430
   sampler.wrap_s = tex_wrap;
 
431
   sampler.wrap_t = tex_wrap;
 
432
   sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
 
433
 
 
434
   sampler.normalized_coords = 1;
 
435
 
 
436
   /* set samplers */
 
437
   for (i = 0; i < num_views; i++)
 
438
      cso_single_sampler(r->cso, PIPE_SHADER_FRAGMENT, i, &sampler);
 
439
   cso_single_sampler_done(r->cso, PIPE_SHADER_FRAGMENT);
 
440
 
 
441
   /* set views */
 
442
   cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, num_views, views);
 
443
}
 
444
 
 
445
/**
 
446
 * Set custom renderer fragment shader, and optionally set samplers and views
 
447
 * and upload the fragment constant buffer.
 
448
 *
 
449
 * This function modifies fragment_shader, samplers and fragment_sampler_views
 
450
 * states.
 
451
 */
 
452
static void renderer_set_custom_fs(struct renderer *renderer,
 
453
                                   void *fs,
 
454
                                   const struct pipe_sampler_state **samplers,
 
455
                                   struct pipe_sampler_view **views,
 
456
                                   VGint num_samplers,
 
457
                                   const void *const_buffer,
 
458
                                   VGint const_buffer_len)
 
459
{
 
460
   cso_set_fragment_shader_handle(renderer->cso, fs);
 
461
 
 
462
   /* set samplers and views */
 
463
   if (num_samplers) {
 
464
      cso_set_samplers(renderer->cso, PIPE_SHADER_FRAGMENT, num_samplers, samplers);
 
465
      cso_set_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT, num_samplers, views);
 
466
   }
 
467
 
 
468
   /* upload fs constant buffer */
 
469
   if (const_buffer_len) {
 
470
      struct pipe_resource *cbuf = renderer->fs_cbuf;
 
471
 
 
472
      if (!cbuf || renderer->fs_cbuf_len != const_buffer_len ||
 
473
          memcmp(renderer->fs_cbuf_data, const_buffer, const_buffer_len)) {
 
474
         pipe_resource_reference(&cbuf, NULL);
 
475
 
 
476
         cbuf = pipe_buffer_create(renderer->pipe->screen,
 
477
               PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC,
 
478
               const_buffer_len);
 
479
         pipe_buffer_write(renderer->pipe, cbuf, 0,
 
480
               const_buffer_len, const_buffer);
 
481
         pipe_set_constant_buffer(renderer->pipe,
 
482
               PIPE_SHADER_FRAGMENT, 0, cbuf);
 
483
 
 
484
         renderer->fs_cbuf = cbuf;
 
485
         if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) {
 
486
            memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len);
 
487
            renderer->fs_cbuf_len = const_buffer_len;
 
488
         }
 
489
         else {
 
490
            renderer->fs_cbuf_len = 0;
 
491
         }
 
492
      }
 
493
   }
 
494
}
 
495
 
 
496
/**
 
497
 * Setup renderer quad position.
 
498
 */
 
499
static void renderer_quad_pos(struct renderer *r,
 
500
                              VGfloat x0, VGfloat y0,
 
501
                              VGfloat x1, VGfloat y1,
 
502
                              VGboolean scissor)
 
503
{
 
504
   VGfloat z;
 
505
 
 
506
   /* the depth test is used for scissoring */
 
507
   z = (scissor) ? 0.0f : 1.0f;
 
508
 
 
509
   /* positions */
 
510
   r->vertices[0][0][0] = x0;
 
511
   r->vertices[0][0][1] = y0;
 
512
   r->vertices[0][0][2] = z;
 
513
 
 
514
   r->vertices[1][0][0] = x1;
 
515
   r->vertices[1][0][1] = y0;
 
516
   r->vertices[1][0][2] = z;
 
517
 
 
518
   r->vertices[2][0][0] = x1;
 
519
   r->vertices[2][0][1] = y1;
 
520
   r->vertices[2][0][2] = z;
 
521
 
 
522
   r->vertices[3][0][0] = x0;
 
523
   r->vertices[3][0][1] = y1;
 
524
   r->vertices[3][0][2] = z;
 
525
}
 
526
 
 
527
/**
 
528
 * Setup renderer quad texture coordinates.
 
529
 */
 
530
static void renderer_quad_texcoord(struct renderer *r,
 
531
                                   VGfloat x0, VGfloat y0,
 
532
                                   VGfloat x1, VGfloat y1,
 
533
                                   VGint tex_width, VGint tex_height)
 
534
{
 
535
   VGfloat s0, t0, s1, t1, r0, q0;
 
536
   VGint i;
 
537
 
 
538
   s0 = x0 / tex_width;
 
539
   s1 = x1 / tex_width;
 
540
   t0 = y0 / tex_height;
 
541
   t1 = y1 / tex_height;
 
542
   r0 = 0.0f;
 
543
   q0 = 1.0f;
 
544
 
 
545
   /* texcoords */
 
546
   r->vertices[0][1][0] = s0;
 
547
   r->vertices[0][1][1] = t0;
 
548
 
 
549
   r->vertices[1][1][0] = s1;
 
550
   r->vertices[1][1][1] = t0;
 
551
 
 
552
   r->vertices[2][1][0] = s1;
 
553
   r->vertices[2][1][1] = t1;
 
554
 
 
555
   r->vertices[3][1][0] = s0;
 
556
   r->vertices[3][1][1] = t1;
 
557
 
 
558
   for (i = 0; i < 4; i++) {
 
559
      r->vertices[i][1][2] = r0;
 
560
      r->vertices[i][1][3] = q0;
 
561
   }
 
562
}
 
563
 
 
564
/**
 
565
 * Draw renderer quad.
 
566
 */
 
567
static void renderer_quad_draw(struct renderer *r)
 
568
{
 
569
   util_draw_user_vertex_buffer(r->cso, r->vertices, PIPE_PRIM_TRIANGLE_FAN,
 
570
                                Elements(r->vertices),     /* verts */
 
571
                                Elements(r->vertices[0])); /* attribs/vert */
 
572
}
 
573
 
 
574
/**
 
575
 * Prepare the renderer for copying.
 
576
 */
 
577
VGboolean renderer_copy_begin(struct renderer *renderer,
 
578
                              struct pipe_surface *dst,
 
579
                              VGboolean y0_top,
 
580
                              struct pipe_sampler_view *src)
 
581
{
 
582
   assert(renderer->state == RENDERER_STATE_INIT);
 
583
 
 
584
   /* sanity check */
 
585
   if (!renderer_can_support(renderer,
 
586
            dst->texture, PIPE_BIND_RENDER_TARGET) ||
 
587
       !renderer_can_support(renderer,
 
588
          src->texture, PIPE_BIND_SAMPLER_VIEW))
 
589
      return VG_FALSE;
 
590
 
 
591
   cso_save_framebuffer(renderer->cso);
 
592
   cso_save_viewport(renderer->cso);
 
593
   cso_save_blend(renderer->cso);
 
594
   cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
 
595
   cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
 
596
   cso_save_fragment_shader(renderer->cso);
 
597
   cso_save_vertex_shader(renderer->cso);
 
598
 
 
599
   renderer_set_target(renderer, dst, NULL, y0_top);
 
600
 
 
601
   renderer_set_blend(renderer, ~0);
 
602
   renderer_set_samplers(renderer, 1, &src);
 
603
 
 
604
   renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
 
605
   renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
 
606
 
 
607
   renderer_set_mvp(renderer, NULL);
 
608
 
 
609
   /* remember the texture size */
 
610
   renderer->u.copy.tex_width = src->texture->width0;
 
611
   renderer->u.copy.tex_height = src->texture->height0;
 
612
   renderer->state = RENDERER_STATE_COPY;
 
613
 
 
614
   return VG_TRUE;
 
615
}
 
616
 
 
617
/**
 
618
 * Draw into the destination rectangle given by (x, y, w, h).  The texture is
 
619
 * sampled from within the rectangle given by (sx, sy, sw, sh).
 
620
 *
 
621
 * The coordinates are in surface coordinates.
 
622
 */
 
623
void renderer_copy(struct renderer *renderer,
 
624
                   VGint x, VGint y, VGint w, VGint h,
 
625
                   VGint sx, VGint sy, VGint sw, VGint sh)
 
626
{
 
627
   assert(renderer->state == RENDERER_STATE_COPY);
 
628
 
 
629
   /* there is no depth buffer for scissoring anyway */
 
630
   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
 
631
   renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
 
632
         renderer->u.copy.tex_width,
 
633
         renderer->u.copy.tex_height);
 
634
 
 
635
   renderer_quad_draw(renderer);
 
636
}
 
637
 
 
638
/**
 
639
 * End copying and restore the states.
 
640
 */
 
641
void renderer_copy_end(struct renderer *renderer)
 
642
{
 
643
   assert(renderer->state == RENDERER_STATE_COPY);
 
644
 
 
645
   cso_restore_framebuffer(renderer->cso);
 
646
   cso_restore_viewport(renderer->cso);
 
647
   cso_restore_blend(renderer->cso);
 
648
   cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
 
649
   cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
 
650
   cso_restore_fragment_shader(renderer->cso);
 
651
   cso_restore_vertex_shader(renderer->cso);
 
652
 
 
653
   renderer->state = RENDERER_STATE_INIT;
 
654
}
 
655
 
 
656
/**
 
657
 * Prepare the renderer for textured drawing.
 
658
 */
 
659
VGboolean renderer_drawtex_begin(struct renderer *renderer,
 
660
                                 struct pipe_sampler_view *src)
 
661
{
 
662
   assert(renderer->state == RENDERER_STATE_INIT);
 
663
 
 
664
   if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
 
665
      return VG_FALSE;
 
666
 
 
667
   cso_save_blend(renderer->cso);
 
668
   cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
 
669
   cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
 
670
   cso_save_fragment_shader(renderer->cso);
 
671
   cso_save_vertex_shader(renderer->cso);
 
672
 
 
673
   renderer_set_blend(renderer, ~0);
 
674
 
 
675
   renderer_set_samplers(renderer, 1, &src);
 
676
 
 
677
   renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
 
678
   renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
 
679
 
 
680
   renderer_set_mvp(renderer, NULL);
 
681
 
 
682
   /* remember the texture size */
 
683
   renderer->u.drawtex.tex_width = src->texture->width0;
 
684
   renderer->u.drawtex.tex_height = src->texture->height0;
 
685
   renderer->state = RENDERER_STATE_DRAWTEX;
 
686
 
 
687
   return VG_TRUE;
 
688
}
 
689
 
 
690
/**
 
691
 * Draw into the destination rectangle given by (x, y, w, h).  The texture is
 
692
 * sampled from within the rectangle given by (sx, sy, sw, sh).
 
693
 *
 
694
 * The coordinates are in surface coordinates.
 
695
 */
 
696
void renderer_drawtex(struct renderer *renderer,
 
697
                      VGint x, VGint y, VGint w, VGint h,
 
698
                      VGint sx, VGint sy, VGint sw, VGint sh)
 
699
{
 
700
   assert(renderer->state == RENDERER_STATE_DRAWTEX);
 
701
 
 
702
   /* with scissoring */
 
703
   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
 
704
   renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
 
705
         renderer->u.drawtex.tex_width,
 
706
         renderer->u.drawtex.tex_height);
 
707
 
 
708
   renderer_quad_draw(renderer);
 
709
}
 
710
 
 
711
/**
 
712
 * End textured drawing and restore the states.
 
713
 */
 
714
void renderer_drawtex_end(struct renderer *renderer)
 
715
{
 
716
   assert(renderer->state == RENDERER_STATE_DRAWTEX);
 
717
 
 
718
   cso_restore_blend(renderer->cso);
 
719
   cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
 
720
   cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
 
721
   cso_restore_fragment_shader(renderer->cso);
 
722
   cso_restore_vertex_shader(renderer->cso);
 
723
 
 
724
   renderer->state = RENDERER_STATE_INIT;
 
725
}
 
726
 
 
727
/**
 
728
 * Prepare the renderer for scissor update.  This will reset the depth buffer
 
729
 * to 1.0f.
 
730
 */
 
731
VGboolean renderer_scissor_begin(struct renderer *renderer,
 
732
                                 VGboolean restore_dsa)
 
733
{
 
734
   struct pipe_depth_stencil_alpha_state dsa;
 
735
 
 
736
   assert(renderer->state == RENDERER_STATE_INIT);
 
737
 
 
738
   if (restore_dsa)
 
739
      cso_save_depth_stencil_alpha(renderer->cso);
 
740
   cso_save_blend(renderer->cso);
 
741
   cso_save_fragment_shader(renderer->cso);
 
742
 
 
743
   /* enable depth writes */
 
744
   memset(&dsa, 0, sizeof(dsa));
 
745
   dsa.depth.enabled = 1;
 
746
   dsa.depth.writemask = 1;
 
747
   dsa.depth.func = PIPE_FUNC_ALWAYS;
 
748
   cso_set_depth_stencil_alpha(renderer->cso, &dsa);
 
749
 
 
750
   /* disable color writes */
 
751
   renderer_set_blend(renderer, 0);
 
752
   renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
 
753
 
 
754
   renderer_set_mvp(renderer, NULL);
 
755
 
 
756
   renderer->u.scissor.restore_dsa = restore_dsa;
 
757
   renderer->state = RENDERER_STATE_SCISSOR;
 
758
 
 
759
   /* clear the depth buffer to 1.0f */
 
760
   renderer->pipe->clear(renderer->pipe,
 
761
         PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
 
762
 
 
763
   return VG_TRUE;
 
764
}
 
765
 
 
766
/**
 
767
 * Add a scissor rectangle.  Depth values inside the rectangle will be set to
 
768
 * 0.0f.
 
769
 */
 
770
void renderer_scissor(struct renderer *renderer,
 
771
                      VGint x, VGint y, VGint width, VGint height)
 
772
{
 
773
   assert(renderer->state == RENDERER_STATE_SCISSOR);
 
774
 
 
775
   renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
 
776
   renderer_quad_draw(renderer);
 
777
}
 
778
 
 
779
/**
 
780
 * End scissor update and restore the states.
 
781
 */
 
782
void renderer_scissor_end(struct renderer *renderer)
 
783
{
 
784
   assert(renderer->state == RENDERER_STATE_SCISSOR);
 
785
 
 
786
   if (renderer->u.scissor.restore_dsa)
 
787
      cso_restore_depth_stencil_alpha(renderer->cso);
 
788
   cso_restore_blend(renderer->cso);
 
789
   cso_restore_fragment_shader(renderer->cso);
 
790
 
 
791
   renderer->state = RENDERER_STATE_INIT;
 
792
}
 
793
 
 
794
/**
 
795
 * Prepare the renderer for clearing.
 
796
 */
 
797
VGboolean renderer_clear_begin(struct renderer *renderer)
 
798
{
 
799
   assert(renderer->state == RENDERER_STATE_INIT);
 
800
 
 
801
   cso_save_blend(renderer->cso);
 
802
   cso_save_fragment_shader(renderer->cso);
 
803
   cso_save_vertex_shader(renderer->cso);
 
804
 
 
805
   renderer_set_blend(renderer, ~0);
 
806
   renderer_set_fs(renderer, RENDERER_FS_COLOR);
 
807
   renderer_set_vs(renderer, RENDERER_VS_COLOR);
 
808
 
 
809
   renderer_set_mvp(renderer, NULL);
 
810
 
 
811
   renderer->state = RENDERER_STATE_CLEAR;
 
812
 
 
813
   return VG_TRUE;
 
814
}
 
815
 
 
816
/**
 
817
 * Clear the framebuffer with the specified region and color.
 
818
 *
 
819
 * The coordinates are in surface coordinates.
 
820
 */
 
821
void renderer_clear(struct renderer *renderer,
 
822
                    VGint x, VGint y, VGint width, VGint height,
 
823
                    const VGfloat color[4])
 
824
{
 
825
   VGuint i;
 
826
 
 
827
   assert(renderer->state == RENDERER_STATE_CLEAR);
 
828
 
 
829
   renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
 
830
   for (i = 0; i < 4; i++)
 
831
      memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
 
832
 
 
833
   renderer_quad_draw(renderer);
 
834
}
 
835
 
 
836
/**
 
837
 * End clearing and retore the states.
 
838
 */
 
839
void renderer_clear_end(struct renderer *renderer)
 
840
{
 
841
   assert(renderer->state == RENDERER_STATE_CLEAR);
 
842
 
 
843
   cso_restore_blend(renderer->cso);
 
844
   cso_restore_fragment_shader(renderer->cso);
 
845
   cso_restore_vertex_shader(renderer->cso);
 
846
 
 
847
   renderer->state = RENDERER_STATE_INIT;
 
848
}
 
849
 
 
850
/**
 
851
 * Prepare the renderer for image filtering.
 
852
 */
 
853
VGboolean renderer_filter_begin(struct renderer *renderer,
 
854
                                struct pipe_resource *dst,
 
855
                                VGboolean y0_top,
 
856
                                VGbitfield channel_mask,
 
857
                                const struct pipe_sampler_state **samplers,
 
858
                                struct pipe_sampler_view **views,
 
859
                                VGint num_samplers,
 
860
                                void *fs,
 
861
                                const void *const_buffer,
 
862
                                VGint const_buffer_len)
 
863
{
 
864
   struct pipe_surface *surf, surf_tmpl;
 
865
 
 
866
   assert(renderer->state == RENDERER_STATE_INIT);
 
867
 
 
868
   if (!fs)
 
869
      return VG_FALSE;
 
870
   if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
 
871
      return VG_FALSE;
 
872
 
 
873
   u_surface_default_template(&surf_tmpl, dst,
 
874
                              PIPE_BIND_RENDER_TARGET);
 
875
   surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
 
876
   if (!surf)
 
877
      return VG_FALSE;
 
878
 
 
879
   cso_save_framebuffer(renderer->cso);
 
880
   cso_save_viewport(renderer->cso);
 
881
   cso_save_blend(renderer->cso);
 
882
 
 
883
   /* set the image as the target */
 
884
   renderer_set_target(renderer, surf, NULL, y0_top);
 
885
   pipe_surface_reference(&surf, NULL);
 
886
 
 
887
   renderer_set_blend(renderer, channel_mask);
 
888
 
 
889
   if (num_samplers) {
 
890
      struct pipe_resource *tex;
 
891
 
 
892
      cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
 
893
      cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
 
894
      cso_save_fragment_shader(renderer->cso);
 
895
      cso_save_vertex_shader(renderer->cso);
 
896
 
 
897
      renderer_set_custom_fs(renderer, fs,
 
898
                             samplers, views, num_samplers,
 
899
                             const_buffer, const_buffer_len);
 
900
      renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
 
901
 
 
902
      tex = views[0]->texture;
 
903
      renderer->u.filter.tex_width = tex->width0;
 
904
      renderer->u.filter.tex_height = tex->height0;
 
905
      renderer->u.filter.use_sampler = VG_TRUE;
 
906
   }
 
907
   else {
 
908
      cso_save_fragment_shader(renderer->cso);
 
909
 
 
910
      renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
 
911
                             const_buffer, const_buffer_len);
 
912
 
 
913
      renderer->u.filter.use_sampler = VG_FALSE;
 
914
   }
 
915
 
 
916
   renderer_set_mvp(renderer, NULL);
 
917
 
 
918
   renderer->state = RENDERER_STATE_FILTER;
 
919
 
 
920
   return VG_TRUE;
 
921
}
 
922
 
 
923
/**
 
924
 * Draw into a rectangle of the destination with the specified region of the
 
925
 * texture(s).
 
926
 *
 
927
 * The coordinates are in surface coordinates.
 
928
 */
 
929
void renderer_filter(struct renderer *renderer,
 
930
                    VGint x, VGint y, VGint w, VGint h,
 
931
                    VGint sx, VGint sy, VGint sw, VGint sh)
 
932
{
 
933
   assert(renderer->state == RENDERER_STATE_FILTER);
 
934
 
 
935
   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
 
936
   if (renderer->u.filter.use_sampler) {
 
937
      renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
 
938
            renderer->u.filter.tex_width,
 
939
            renderer->u.filter.tex_height);
 
940
   }
 
941
 
 
942
   renderer_quad_draw(renderer);
 
943
}
 
944
 
 
945
/**
 
946
 * End image filtering and restore the states.
 
947
 */
 
948
void renderer_filter_end(struct renderer *renderer)
 
949
{
 
950
   assert(renderer->state == RENDERER_STATE_FILTER);
 
951
 
 
952
   if (renderer->u.filter.use_sampler) {
 
953
      cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
 
954
      cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
 
955
      cso_restore_vertex_shader(renderer->cso);
 
956
   }
 
957
 
 
958
   cso_restore_framebuffer(renderer->cso);
 
959
   cso_restore_viewport(renderer->cso);
 
960
   cso_restore_blend(renderer->cso);
 
961
   cso_restore_fragment_shader(renderer->cso);
 
962
 
 
963
   renderer->state = RENDERER_STATE_INIT;
 
964
}
 
965
 
 
966
/**
 
967
 * Prepare the renderer for polygon silhouette rendering.
 
968
 */
 
969
VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
 
970
                                         struct pipe_vertex_element *velem,
 
971
                                         VGFillRule rule,
 
972
                                         VGboolean restore_dsa)
 
973
{
 
974
   struct pipe_depth_stencil_alpha_state *dsa;
 
975
   VGboolean manual_two_sides;
 
976
 
 
977
   assert(renderer->state == RENDERER_STATE_INIT);
 
978
 
 
979
   cso_save_vertex_elements(renderer->cso);
 
980
   cso_save_blend(renderer->cso);
 
981
   cso_save_depth_stencil_alpha(renderer->cso);
 
982
 
 
983
   cso_set_vertex_elements(renderer->cso, 1, velem);
 
984
 
 
985
   /* disable color writes */
 
986
   renderer_set_blend(renderer, 0);
 
987
 
 
988
   manual_two_sides = VG_FALSE;
 
989
   dsa = &renderer->u.polygon_stencil.dsa;
 
990
   memset(dsa, 0, sizeof(*dsa));
 
991
   if (rule == VG_EVEN_ODD) {
 
992
      dsa->stencil[0].enabled = 1;
 
993
      dsa->stencil[0].writemask = 1;
 
994
      dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
 
995
      dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
 
996
      dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
 
997
      dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
 
998
      dsa->stencil[0].valuemask = ~0;
 
999
   }
 
1000
   else {
 
1001
      assert(rule == VG_NON_ZERO);
 
1002
 
 
1003
      /* front face */
 
1004
      dsa->stencil[0].enabled = 1;
 
1005
      dsa->stencil[0].writemask = ~0;
 
1006
      dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
 
1007
      dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
 
1008
      dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
 
1009
      dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
 
1010
      dsa->stencil[0].valuemask = ~0;
 
1011
 
 
1012
      if (renderer->pipe->screen->get_param(renderer->pipe->screen,
 
1013
                                            PIPE_CAP_TWO_SIDED_STENCIL)) {
 
1014
         /* back face */
 
1015
         dsa->stencil[1] = dsa->stencil[0];
 
1016
         dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
 
1017
      }
 
1018
      else {
 
1019
         manual_two_sides = VG_TRUE;
 
1020
      }
 
1021
   }
 
1022
   cso_set_depth_stencil_alpha(renderer->cso, dsa);
 
1023
 
 
1024
   if (manual_two_sides)
 
1025
      cso_save_rasterizer(renderer->cso);
 
1026
 
 
1027
   renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
 
1028
   renderer->u.polygon_stencil.restore_dsa = restore_dsa;
 
1029
   renderer->state = RENDERER_STATE_POLYGON_STENCIL;
 
1030
 
 
1031
   return VG_TRUE;
 
1032
}
 
1033
 
 
1034
/**
 
1035
 * Render a polygon silhouette to stencil buffer.
 
1036
 */
 
1037
void renderer_polygon_stencil(struct renderer *renderer,
 
1038
                              struct pipe_vertex_buffer *vbuf,
 
1039
                              VGuint mode, VGuint start, VGuint count)
 
1040
{
 
1041
   assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
 
1042
 
 
1043
   cso_set_vertex_buffers(renderer->cso, 1, vbuf);
 
1044
 
 
1045
   if (!renderer->u.polygon_stencil.manual_two_sides) {
 
1046
      cso_draw_arrays(renderer->cso, mode, start, count);
 
1047
   }
 
1048
   else {
 
1049
      struct pipe_rasterizer_state raster;
 
1050
      struct pipe_depth_stencil_alpha_state dsa;
 
1051
 
 
1052
      raster = renderer->g3d.rasterizer;
 
1053
      dsa = renderer->u.polygon_stencil.dsa;
 
1054
 
 
1055
      /* front */
 
1056
      raster.cull_face = PIPE_FACE_BACK;
 
1057
      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
 
1058
 
 
1059
      cso_set_rasterizer(renderer->cso, &raster);
 
1060
      cso_set_depth_stencil_alpha(renderer->cso, &dsa);
 
1061
      cso_draw_arrays(renderer->cso, mode, start, count);
 
1062
 
 
1063
      /* back */
 
1064
      raster.cull_face = PIPE_FACE_FRONT;
 
1065
      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
 
1066
 
 
1067
      cso_set_rasterizer(renderer->cso, &raster);
 
1068
      cso_set_depth_stencil_alpha(renderer->cso, &dsa);
 
1069
      cso_draw_arrays(renderer->cso, mode, start, count);
 
1070
   }
 
1071
}
 
1072
 
 
1073
/**
 
1074
 * End polygon silhouette rendering.
 
1075
 */
 
1076
void renderer_polygon_stencil_end(struct renderer *renderer)
 
1077
{
 
1078
   assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
 
1079
 
 
1080
   if (renderer->u.polygon_stencil.manual_two_sides)
 
1081
      cso_restore_rasterizer(renderer->cso);
 
1082
 
 
1083
   cso_restore_vertex_elements(renderer->cso);
 
1084
 
 
1085
   /* restore color writes */
 
1086
   cso_restore_blend(renderer->cso);
 
1087
 
 
1088
   if (renderer->u.polygon_stencil.restore_dsa)
 
1089
      cso_restore_depth_stencil_alpha(renderer->cso);
 
1090
 
 
1091
   renderer->state = RENDERER_STATE_INIT;
 
1092
}
 
1093
 
 
1094
/**
 
1095
 * Prepare the renderer for polygon filling.
 
1096
 */
 
1097
VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
 
1098
                                      VGboolean save_dsa)
 
1099
{
 
1100
   struct pipe_depth_stencil_alpha_state dsa;
 
1101
 
 
1102
   assert(renderer->state == RENDERER_STATE_INIT);
 
1103
 
 
1104
   if (save_dsa)
 
1105
      cso_save_depth_stencil_alpha(renderer->cso);
 
1106
 
 
1107
   /* setup stencil ops */
 
1108
   memset(&dsa, 0, sizeof(dsa));
 
1109
   dsa.stencil[0].enabled = 1;
 
1110
   dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
 
1111
   dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
 
1112
   dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
 
1113
   dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
 
1114
   dsa.stencil[0].valuemask = ~0;
 
1115
   dsa.stencil[0].writemask = ~0;
 
1116
   dsa.depth = renderer->g3d.dsa.depth;
 
1117
   cso_set_depth_stencil_alpha(renderer->cso, &dsa);
 
1118
 
 
1119
   renderer->state = RENDERER_STATE_POLYGON_FILL;
 
1120
 
 
1121
   return VG_TRUE;
 
1122
}
 
1123
 
 
1124
/**
 
1125
 * Fill a polygon.
 
1126
 */
 
1127
void renderer_polygon_fill(struct renderer *renderer,
 
1128
                           VGfloat min_x, VGfloat min_y,
 
1129
                           VGfloat max_x, VGfloat max_y)
 
1130
{
 
1131
   assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
 
1132
 
 
1133
   renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
 
1134
   renderer_quad_draw(renderer);
 
1135
}
 
1136
 
 
1137
/**
 
1138
 * End polygon filling.
 
1139
 */
 
1140
void renderer_polygon_fill_end(struct renderer *renderer)
 
1141
{
 
1142
   assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
 
1143
 
 
1144
   cso_restore_depth_stencil_alpha(renderer->cso);
 
1145
 
 
1146
   renderer->state = RENDERER_STATE_INIT;
 
1147
}
 
1148
 
 
1149
struct renderer * renderer_create(struct vg_context *owner)
 
1150
{
 
1151
   struct renderer *renderer;
 
1152
   struct pipe_rasterizer_state *raster;
 
1153
   struct pipe_stencil_ref sr;
 
1154
   VGint i;
 
1155
 
 
1156
   renderer = CALLOC_STRUCT(renderer);
 
1157
   if (!renderer)
 
1158
      return NULL;
 
1159
 
 
1160
   renderer->pipe = owner->pipe;
 
1161
   renderer->cso = owner->cso_context;
 
1162
 
 
1163
   /* init vertex data that doesn't change */
 
1164
   for (i = 0; i < 4; i++)
 
1165
      renderer->vertices[i][0][3] = 1.0f; /* w */
 
1166
 
 
1167
   for (i = 0; i < 2; i++) {
 
1168
      renderer->velems[i].src_offset = i * 4 * sizeof(float);
 
1169
      renderer->velems[i].instance_divisor = 0;
 
1170
      renderer->velems[i].vertex_buffer_index = 0;
 
1171
      renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
 
1172
   }
 
1173
   cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
 
1174
 
 
1175
   /* GL rasterization rules */
 
1176
   raster = &renderer->g3d.rasterizer;
 
1177
   memset(raster, 0, sizeof(*raster));
 
1178
   raster->gl_rasterization_rules = 1;
 
1179
   raster->depth_clip = 1;
 
1180
   cso_set_rasterizer(renderer->cso, raster);
 
1181
 
 
1182
   /* fixed at 0 */
 
1183
   memset(&sr, 0, sizeof(sr));
 
1184
   cso_set_stencil_ref(renderer->cso, &sr);
 
1185
 
 
1186
   renderer_set_vs(renderer, RENDERER_VS_PLAIN);
 
1187
 
 
1188
   renderer->state = RENDERER_STATE_INIT;
 
1189
 
 
1190
   return renderer;
 
1191
}
 
1192
 
 
1193
void renderer_destroy(struct renderer *ctx)
 
1194
{
 
1195
   int i;
 
1196
 
 
1197
   for (i = 0; i < NUM_RENDERER_VS; i++) {
 
1198
      if (ctx->cached_vs[i])
 
1199
         cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
 
1200
   }
 
1201
   for (i = 0; i < NUM_RENDERER_FS; i++) {
 
1202
      if (ctx->cached_fs[i])
 
1203
         cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
 
1204
   }
 
1205
 
 
1206
   pipe_resource_reference(&ctx->vs_cbuf, NULL);
 
1207
   pipe_resource_reference(&ctx->fs_cbuf, NULL);
 
1208
 
 
1209
   FREE(ctx);
 
1210
}
 
1211
 
 
1212
static void update_clip_state(struct renderer *renderer,
 
1213
                              const struct vg_state *state)
 
1214
{
 
1215
   struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
 
1216
 
 
1217
   memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
 
1218
 
 
1219
   if (state->scissoring) {
 
1220
      struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
 
1221
      int i;
 
1222
 
 
1223
      renderer_scissor_begin(renderer, VG_FALSE);
 
1224
 
 
1225
      for (i = 0; i < state->scissor_rects_num; ++i) {
 
1226
         const float x      = state->scissor_rects[i * 4 + 0].f;
 
1227
         const float y      = state->scissor_rects[i * 4 + 1].f;
 
1228
         const float width  = state->scissor_rects[i * 4 + 2].f;
 
1229
         const float height = state->scissor_rects[i * 4 + 3].f;
 
1230
         VGint x0, y0, x1, y1, iw, ih;
 
1231
 
 
1232
         x0 = (VGint) x;
 
1233
         y0 = (VGint) y;
 
1234
         if (x0 < 0)
 
1235
            x0 = 0;
 
1236
         if (y0 < 0)
 
1237
            y0 = 0;
 
1238
 
 
1239
         /* note that x1 and y1 are exclusive */
 
1240
         x1 = (VGint) ceilf(x + width);
 
1241
         y1 = (VGint) ceilf(y + height);
 
1242
         if (x1 > fb->width)
 
1243
            x1 = fb->width;
 
1244
         if (y1 > fb->height)
 
1245
            y1 = fb->height;
 
1246
 
 
1247
         iw = x1 - x0;
 
1248
         ih = y1 - y0;
 
1249
         if (iw > 0 && ih> 0 )
 
1250
            renderer_scissor(renderer, x0, y0, iw, ih);
 
1251
      }
 
1252
 
 
1253
      renderer_scissor_end(renderer);
 
1254
 
 
1255
      dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
 
1256
      dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
 
1257
      dsa->depth.func = PIPE_FUNC_GEQUAL;
 
1258
   }
 
1259
}
 
1260
 
 
1261
static void renderer_validate_blend(struct renderer *renderer,
 
1262
                                     const struct vg_state *state,
 
1263
                                     enum pipe_format fb_format)
 
1264
{
 
1265
   struct pipe_blend_state blend;
 
1266
 
 
1267
   memset(&blend, 0, sizeof(blend));
 
1268
   blend.rt[0].colormask = PIPE_MASK_RGBA;
 
1269
   blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
 
1270
   blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
 
1271
   blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
 
1272
   blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
 
1273
 
 
1274
   /* TODO alpha masking happens after blending? */
 
1275
 
 
1276
   switch (state->blend_mode) {
 
1277
   case VG_BLEND_SRC:
 
1278
      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
 
1279
      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
 
1280
      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
 
1281
      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
 
1282
      break;
 
1283
   case VG_BLEND_SRC_OVER:
 
1284
      /* use the blend state only when there is no alpha channel */
 
1285
      if (!util_format_has_alpha(fb_format)) {
 
1286
         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
 
1287
         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
 
1288
         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
 
1289
         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
 
1290
         blend.rt[0].blend_enable = 1;
 
1291
      }
 
1292
      break;
 
1293
   case VG_BLEND_SRC_IN:
 
1294
      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
 
1295
      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
 
1296
      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
 
1297
      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
 
1298
      blend.rt[0].blend_enable = 1;
 
1299
      break;
 
1300
   case VG_BLEND_DST_IN:
 
1301
      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ZERO;
 
1302
      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
 
1303
      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ONE;
 
1304
      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
 
1305
      blend.rt[0].blend_enable = 1;
 
1306
      break;
 
1307
   case VG_BLEND_DST_OVER:
 
1308
   case VG_BLEND_MULTIPLY:
 
1309
   case VG_BLEND_SCREEN:
 
1310
   case VG_BLEND_DARKEN:
 
1311
   case VG_BLEND_LIGHTEN:
 
1312
   case VG_BLEND_ADDITIVE:
 
1313
      /* need a shader */
 
1314
      break;
 
1315
   default:
 
1316
      assert(!"not implemented blend mode");
 
1317
      break;
 
1318
   }
 
1319
 
 
1320
   cso_set_blend(renderer->cso, &blend);
 
1321
}
 
1322
 
 
1323
/**
 
1324
 * Propogate OpenVG state changes to the renderer.  Only framebuffer, blending
 
1325
 * and scissoring states are relevant here.
 
1326
 */
 
1327
void renderer_validate(struct renderer *renderer,
 
1328
                       VGbitfield dirty,
 
1329
                       const struct st_framebuffer *stfb,
 
1330
                       const struct vg_state *state)
 
1331
{
 
1332
   assert(renderer->state == RENDERER_STATE_INIT);
 
1333
 
 
1334
   dirty |= renderer->dirty;
 
1335
   renderer->dirty = 0;
 
1336
 
 
1337
   if (dirty & FRAMEBUFFER_DIRTY) {
 
1338
      struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
 
1339
      struct matrix *proj = &renderer->projection;
 
1340
 
 
1341
      memset(fb, 0, sizeof(struct pipe_framebuffer_state));
 
1342
      fb->width  = stfb->width;
 
1343
      fb->height = stfb->height;
 
1344
      fb->nr_cbufs = 1;
 
1345
      fb->cbufs[0] = stfb->strb->surface;
 
1346
      fb->zsbuf = stfb->dsrb->surface;
 
1347
 
 
1348
      cso_set_framebuffer(renderer->cso, fb);
 
1349
      vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
 
1350
 
 
1351
      matrix_load_identity(proj);
 
1352
      matrix_translate(proj, -1.0f, -1.0f);
 
1353
      matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
 
1354
 
 
1355
      /* we also got a new depth buffer */
 
1356
      if (dirty & DEPTH_STENCIL_DIRTY) {
 
1357
         renderer->pipe->clear(renderer->pipe,
 
1358
               PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
 
1359
      }
 
1360
   }
 
1361
 
 
1362
   /* must be last because it renders to the depth buffer*/
 
1363
   if (dirty & DEPTH_STENCIL_DIRTY) {
 
1364
      update_clip_state(renderer, state);
 
1365
      cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
 
1366
   }
 
1367
 
 
1368
   if (dirty & BLEND_DIRTY)
 
1369
      renderer_validate_blend(renderer, state, stfb->strb->format);
 
1370
}
 
1371
 
 
1372
/**
 
1373
 * Prepare the renderer for OpenVG pipeline.
 
1374
 */
 
1375
void renderer_validate_for_shader(struct renderer *renderer,
 
1376
                                  const struct pipe_sampler_state **samplers,
 
1377
                                  struct pipe_sampler_view **views,
 
1378
                                  VGint num_samplers,
 
1379
                                  const struct matrix *modelview,
 
1380
                                  void *fs,
 
1381
                                  const void *const_buffer,
 
1382
                                  VGint const_buffer_len)
 
1383
{
 
1384
   struct matrix mvp = renderer->projection;
 
1385
 
 
1386
   /* will be used in POLYGON_STENCIL and POLYGON_FILL */
 
1387
   matrix_mult(&mvp, modelview);
 
1388
   renderer_set_mvp(renderer, &mvp);
 
1389
 
 
1390
   renderer_set_custom_fs(renderer, fs,
 
1391
                          samplers, views, num_samplers,
 
1392
                          const_buffer, const_buffer_len);
 
1393
}
 
1394
 
 
1395
void renderer_validate_for_mask_rendering(struct renderer *renderer,
 
1396
                                          struct pipe_surface *dst,
 
1397
                                          const struct matrix *modelview)
 
1398
{
 
1399
   struct matrix mvp = renderer->projection;
 
1400
 
 
1401
   /* will be used in POLYGON_STENCIL and POLYGON_FILL */
 
1402
   matrix_mult(&mvp, modelview);
 
1403
   renderer_set_mvp(renderer, &mvp);
 
1404
 
 
1405
   renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
 
1406
   renderer_set_blend(renderer, ~0);
 
1407
   renderer_set_fs(renderer, RENDERER_FS_WHITE);
 
1408
 
 
1409
   /* set internal dirty flags (hacky!) */
 
1410
   renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
 
1411
}
 
1412
 
 
1413
void renderer_copy_surface(struct renderer *ctx,
 
1414
                           struct pipe_surface *src,
 
1415
                           int srcX0, int srcY0,
 
1416
                           int srcX1, int srcY1,
 
1417
                           struct pipe_surface *dst,
 
1418
                           int dstX0, int dstY0,
 
1419
                           int dstX1, int dstY1,
 
1420
                           float z, unsigned filter)
 
1421
{
 
1422
   struct pipe_context *pipe = ctx->pipe;
 
1423
   struct pipe_screen *screen = pipe->screen;
 
1424
   struct pipe_sampler_view view_templ;
 
1425
   struct pipe_sampler_view *view;
 
1426
   struct pipe_box src_box;
 
1427
   struct pipe_resource texTemp, *tex;
 
1428
   const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
 
1429
   const int srcW = abs(srcX1 - srcX0);
 
1430
   const int srcH = abs(srcY1 - srcY0);
 
1431
   const int srcLeft = MIN2(srcX0, srcX1);
 
1432
   const int srcTop = MIN2(srcY0, srcY1);
 
1433
 
 
1434
   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
 
1435
          filter == PIPE_TEX_MIPFILTER_LINEAR);
 
1436
 
 
1437
   if (srcLeft != srcX0) {
 
1438
      /* left-right flip */
 
1439
      int tmp = dstX0;
 
1440
      dstX0 = dstX1;
 
1441
      dstX1 = tmp;
 
1442
   }
 
1443
 
 
1444
   if (srcTop != srcY0) {
 
1445
      /* up-down flip */
 
1446
      int tmp = dstY0;
 
1447
      dstY0 = dstY1;
 
1448
      dstY1 = tmp;
 
1449
   }
 
1450
 
 
1451
   assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
 
1452
                                      0, PIPE_BIND_SAMPLER_VIEW));
 
1453
   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
 
1454
                                      0, PIPE_BIND_SAMPLER_VIEW));
 
1455
   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
 
1456
                                      0, PIPE_BIND_RENDER_TARGET));
 
1457
 
 
1458
   /*
 
1459
    * XXX for now we're always creating a temporary texture.
 
1460
    * Strictly speaking that's not always needed.
 
1461
    */
 
1462
 
 
1463
   /* create temp texture */
 
1464
   memset(&texTemp, 0, sizeof(texTemp));
 
1465
   texTemp.target = PIPE_TEXTURE_2D;
 
1466
   texTemp.format = src->format;
 
1467
   texTemp.last_level = 0;
 
1468
   texTemp.width0 = srcW;
 
1469
   texTemp.height0 = srcH;
 
1470
   texTemp.depth0 = 1;
 
1471
   texTemp.array_size = 1;
 
1472
   texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
 
1473
 
 
1474
   tex = screen->resource_create(screen, &texTemp);
 
1475
   if (!tex)
 
1476
      return;
 
1477
 
 
1478
   u_sampler_view_default_template(&view_templ, tex, tex->format);
 
1479
   view = pipe->create_sampler_view(pipe, tex, &view_templ);
 
1480
 
 
1481
   if (!view)
 
1482
      return;
 
1483
 
 
1484
   u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
 
1485
 
 
1486
   pipe->resource_copy_region(pipe,
 
1487
                              tex, 0, 0, 0, 0,  /* dest */
 
1488
                              src->texture, 0, &src_box);
 
1489
 
 
1490
   assert(floatsEqual(z, 0.0f));
 
1491
 
 
1492
   /* draw */
 
1493
   if (fb->cbufs[0] == dst) {
 
1494
      /* transform back to surface coordinates */
 
1495
      dstY0 = dst->height - dstY0;
 
1496
      dstY1 = dst->height - dstY1;
 
1497
 
 
1498
      if (renderer_drawtex_begin(ctx, view)) {
 
1499
         renderer_drawtex(ctx,
 
1500
               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
 
1501
               0, 0, view->texture->width0, view->texture->height0);
 
1502
         renderer_drawtex_end(ctx);
 
1503
      }
 
1504
   }
 
1505
   else {
 
1506
      if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
 
1507
         renderer_copy(ctx,
 
1508
               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
 
1509
               0, 0, view->texture->width0, view->texture->height0);
 
1510
         renderer_copy_end(ctx);
 
1511
      }
 
1512
   }
 
1513
}
 
1514
 
 
1515
void renderer_texture_quad(struct renderer *r,
 
1516
                           struct pipe_resource *tex,
 
1517
                           VGfloat x1offset, VGfloat y1offset,
 
1518
                           VGfloat x2offset, VGfloat y2offset,
 
1519
                           VGfloat x1, VGfloat y1,
 
1520
                           VGfloat x2, VGfloat y2,
 
1521
                           VGfloat x3, VGfloat y3,
 
1522
                           VGfloat x4, VGfloat y4)
 
1523
{
 
1524
   const VGfloat z = 0.0f;
 
1525
 
 
1526
   assert(r->state == RENDERER_STATE_INIT);
 
1527
   assert(tex->width0 != 0);
 
1528
   assert(tex->height0 != 0);
 
1529
 
 
1530
   cso_save_vertex_shader(r->cso);
 
1531
 
 
1532
   renderer_set_vs(r, RENDERER_VS_TEXTURE);
 
1533
 
 
1534
   /* manually set up positions */
 
1535
   r->vertices[0][0][0] = x1;
 
1536
   r->vertices[0][0][1] = y1;
 
1537
   r->vertices[0][0][2] = z;
 
1538
 
 
1539
   r->vertices[1][0][0] = x2;
 
1540
   r->vertices[1][0][1] = y2;
 
1541
   r->vertices[1][0][2] = z;
 
1542
 
 
1543
   r->vertices[2][0][0] = x3;
 
1544
   r->vertices[2][0][1] = y3;
 
1545
   r->vertices[2][0][2] = z;
 
1546
 
 
1547
   r->vertices[3][0][0] = x4;
 
1548
   r->vertices[3][0][1] = y4;
 
1549
   r->vertices[3][0][2] = z;
 
1550
 
 
1551
   /* texcoords */
 
1552
   renderer_quad_texcoord(r, x1offset, y1offset,
 
1553
         x2offset, y2offset, tex->width0, tex->height0);
 
1554
 
 
1555
   renderer_quad_draw(r);
 
1556
 
 
1557
   cso_restore_vertex_shader(r->cso);
 
1558
}