gallium: fix more statetrackers/drivers for not using texture width/height/depth...
[mesa.git] / src / gallium / state_trackers / vega / renderer.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 "renderer.h"
28
29 #include "vg_context.h"
30
31 #include "pipe/p_context.h"
32 #include "pipe/p_state.h"
33 #include "pipe/p_inlines.h"
34 #include "pipe/p_screen.h"
35 #include "pipe/p_shader_tokens.h"
36
37 #include "util/u_draw_quad.h"
38 #include "util/u_simple_shaders.h"
39 #include "util/u_memory.h"
40 #include "util/u_rect.h"
41
42 #include "cso_cache/cso_context.h"
43
44 struct renderer {
45 struct pipe_context *pipe;
46 struct vg_context *owner;
47
48 struct cso_context *cso;
49
50 void *fs;
51
52 VGfloat vertices[4][2][4];
53 };
54
55 static void setup_shaders(struct renderer *ctx)
56 {
57 struct pipe_context *pipe = ctx->pipe;
58 /* fragment shader */
59 ctx->fs = util_make_fragment_tex_shader(pipe);
60 }
61
62 static struct pipe_buffer *
63 setup_vertex_data(struct renderer *ctx,
64 float x0, float y0, float x1, float y1, float z)
65 {
66 ctx->vertices[0][0][0] = x0;
67 ctx->vertices[0][0][1] = y0;
68 ctx->vertices[0][0][2] = z;
69 ctx->vertices[0][1][0] = 0.0f; /*s*/
70 ctx->vertices[0][1][1] = 0.0f; /*t*/
71
72 ctx->vertices[1][0][0] = x1;
73 ctx->vertices[1][0][1] = y0;
74 ctx->vertices[1][0][2] = z;
75 ctx->vertices[1][1][0] = 1.0f; /*s*/
76 ctx->vertices[1][1][1] = 0.0f; /*t*/
77
78 ctx->vertices[2][0][0] = x1;
79 ctx->vertices[2][0][1] = y1;
80 ctx->vertices[2][0][2] = z;
81 ctx->vertices[2][1][0] = 1.0f;
82 ctx->vertices[2][1][1] = 1.0f;
83
84 ctx->vertices[3][0][0] = x0;
85 ctx->vertices[3][0][1] = y1;
86 ctx->vertices[3][0][2] = z;
87 ctx->vertices[3][1][0] = 0.0f;
88 ctx->vertices[3][1][1] = 1.0f;
89
90 return pipe_user_buffer_create( ctx->pipe->screen,
91 ctx->vertices,
92 sizeof(ctx->vertices) );
93 }
94
95 static struct pipe_buffer *
96 setup_vertex_data_tex(struct renderer *ctx,
97 float x0, float y0, float x1, float y1,
98 float s0, float t0, float s1, float t1,
99 float z)
100 {
101 ctx->vertices[0][0][0] = x0;
102 ctx->vertices[0][0][1] = y0;
103 ctx->vertices[0][0][2] = z;
104 ctx->vertices[0][1][0] = s0; /*s*/
105 ctx->vertices[0][1][1] = t0; /*t*/
106
107 ctx->vertices[1][0][0] = x1;
108 ctx->vertices[1][0][1] = y0;
109 ctx->vertices[1][0][2] = z;
110 ctx->vertices[1][1][0] = s1; /*s*/
111 ctx->vertices[1][1][1] = t0; /*t*/
112
113 ctx->vertices[2][0][0] = x1;
114 ctx->vertices[2][0][1] = y1;
115 ctx->vertices[2][0][2] = z;
116 ctx->vertices[2][1][0] = s1;
117 ctx->vertices[2][1][1] = t1;
118
119 ctx->vertices[3][0][0] = x0;
120 ctx->vertices[3][0][1] = y1;
121 ctx->vertices[3][0][2] = z;
122 ctx->vertices[3][1][0] = s0;
123 ctx->vertices[3][1][1] = t1;
124
125 return pipe_user_buffer_create( ctx->pipe->screen,
126 ctx->vertices,
127 sizeof(ctx->vertices) );
128 }
129
130
131 static struct pipe_buffer *
132 setup_vertex_data_qtex(struct renderer *ctx,
133 float x0, float y0, float x1, float y1,
134 float x2, float y2, float x3, float y3,
135 float s0, float t0, float s1, float t1,
136 float z)
137 {
138 ctx->vertices[0][0][0] = x0;
139 ctx->vertices[0][0][1] = y0;
140 ctx->vertices[0][0][2] = z;
141 ctx->vertices[0][1][0] = s0; /*s*/
142 ctx->vertices[0][1][1] = t0; /*t*/
143
144 ctx->vertices[1][0][0] = x1;
145 ctx->vertices[1][0][1] = y1;
146 ctx->vertices[1][0][2] = z;
147 ctx->vertices[1][1][0] = s1; /*s*/
148 ctx->vertices[1][1][1] = t0; /*t*/
149
150 ctx->vertices[2][0][0] = x2;
151 ctx->vertices[2][0][1] = y2;
152 ctx->vertices[2][0][2] = z;
153 ctx->vertices[2][1][0] = s1;
154 ctx->vertices[2][1][1] = t1;
155
156 ctx->vertices[3][0][0] = x3;
157 ctx->vertices[3][0][1] = y3;
158 ctx->vertices[3][0][2] = z;
159 ctx->vertices[3][1][0] = s0;
160 ctx->vertices[3][1][1] = t1;
161
162 return pipe_user_buffer_create( ctx->pipe->screen,
163 ctx->vertices,
164 sizeof(ctx->vertices) );
165 }
166
167 struct renderer * renderer_create(struct vg_context *owner)
168 {
169 VGint i;
170 struct renderer *renderer = CALLOC_STRUCT(renderer);
171
172 if (!renderer)
173 return NULL;
174
175 renderer->owner = owner;
176 renderer->pipe = owner->pipe;
177 renderer->cso = owner->cso_context;
178
179 setup_shaders(renderer);
180
181 /* init vertex data that doesn't change */
182 for (i = 0; i < 4; i++) {
183 renderer->vertices[i][0][3] = 1.0f; /* w */
184 renderer->vertices[i][1][2] = 0.0f; /* r */
185 renderer->vertices[i][1][3] = 1.0f; /* q */
186 }
187
188 return renderer;
189 }
190
191 void renderer_destroy(struct renderer *ctx)
192 {
193 #if 0
194 if (ctx->fs) {
195 cso_delete_fragment_shader(ctx->cso, ctx->fs);
196 ctx->fs = NULL;
197 }
198 #endif
199 free(ctx);
200 }
201
202 void renderer_draw_quad(struct renderer *r,
203 VGfloat x1, VGfloat y1,
204 VGfloat x2, VGfloat y2,
205 VGfloat depth)
206 {
207 struct pipe_buffer *buf;
208
209 buf = setup_vertex_data(r, x1, y1, x2, y2, depth);
210
211 if (buf) {
212 util_draw_vertex_buffer(r->pipe, buf, 0,
213 PIPE_PRIM_TRIANGLE_FAN,
214 4, /* verts */
215 2); /* attribs/vert */
216
217 pipe_buffer_reference( &buf,
218 NULL );
219 }
220 }
221
222 void renderer_draw_texture(struct renderer *r,
223 struct pipe_texture *tex,
224 VGfloat x1offset, VGfloat y1offset,
225 VGfloat x2offset, VGfloat y2offset,
226 VGfloat x1, VGfloat y1,
227 VGfloat x2, VGfloat y2)
228 {
229 struct pipe_context *pipe = r->pipe;
230 struct pipe_buffer *buf;
231 VGfloat s0, t0, s1, t1;
232
233 assert(tex->width0 != 0);
234 assert(tex->height0 != 0);
235
236 s0 = x1offset / tex->width0;
237 s1 = x2offset / tex->width0;
238 t0 = y1offset / tex->height0;
239 t1 = y2offset / tex->height0;
240
241 cso_save_vertex_shader(r->cso);
242 /* shaders */
243 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
244
245 /* draw quad */
246 buf = setup_vertex_data_tex(r, x1, y1, x2, y2,
247 s0, t0, s1, t1, 0.0f);
248
249 if (buf) {
250 util_draw_vertex_buffer(pipe, buf, 0,
251 PIPE_PRIM_TRIANGLE_FAN,
252 4, /* verts */
253 2); /* attribs/vert */
254
255 pipe_buffer_reference( &buf,
256 NULL );
257 }
258
259 cso_restore_vertex_shader(r->cso);
260 }
261
262 void renderer_copy_texture(struct renderer *ctx,
263 struct pipe_texture *src,
264 VGfloat sx1, VGfloat sy1,
265 VGfloat sx2, VGfloat sy2,
266 struct pipe_texture *dst,
267 VGfloat dx1, VGfloat dy1,
268 VGfloat dx2, VGfloat dy2)
269 {
270 struct pipe_context *pipe = ctx->pipe;
271 struct pipe_screen *screen = pipe->screen;
272 struct pipe_buffer *buf;
273 struct pipe_surface *dst_surf = screen->get_tex_surface(
274 screen, dst, 0, 0, 0,
275 PIPE_BUFFER_USAGE_GPU_WRITE);
276 struct pipe_framebuffer_state fb;
277 float s0, t0, s1, t1;
278
279 assert(src->width0 != 0);
280 assert(src->height0 != 0);
281 assert(dst->width0 != 0);
282 assert(dst->height0 != 0);
283
284 #if 0
285 debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n",
286 sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
287 #endif
288
289 #if 1
290 s0 = sx1 / src->width0;
291 s1 = sx2 / src->width0;
292 t0 = sy1 / src->height0;
293 t1 = sy2 / src->height0;
294 #else
295 s0 = 0;
296 s1 = 1;
297 t0 = 0;
298 t1 = 1;
299 #endif
300
301 assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D,
302 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
303
304 /* save state (restored below) */
305 cso_save_blend(ctx->cso);
306 cso_save_samplers(ctx->cso);
307 cso_save_sampler_textures(ctx->cso);
308 cso_save_framebuffer(ctx->cso);
309 cso_save_fragment_shader(ctx->cso);
310 cso_save_vertex_shader(ctx->cso);
311
312 cso_save_viewport(ctx->cso);
313
314
315 /* set misc state we care about */
316 {
317 struct pipe_blend_state blend;
318 memset(&blend, 0, sizeof(blend));
319 blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
320 blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
321 blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
322 blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
323 blend.colormask = PIPE_MASK_RGBA;
324 cso_set_blend(ctx->cso, &blend);
325 }
326
327 /* sampler */
328 {
329 struct pipe_sampler_state sampler;
330 memset(&sampler, 0, sizeof(sampler));
331 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
332 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
333 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
334 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
335 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
336 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
337 sampler.normalized_coords = 1;
338 cso_single_sampler(ctx->cso, 0, &sampler);
339 cso_single_sampler_done(ctx->cso);
340 }
341
342 vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
343
344 /* texture */
345 cso_set_sampler_textures(ctx->cso, 1, &src);
346
347 /* shaders */
348 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
349 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
350
351 /* drawing dest */
352 memset(&fb, 0, sizeof(fb));
353 fb.width = dst_surf->width;
354 fb.height = dst_surf->height;
355 fb.nr_cbufs = 1;
356 fb.cbufs[0] = dst_surf;
357 {
358 VGint i;
359 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
360 fb.cbufs[i] = 0;
361 }
362 cso_set_framebuffer(ctx->cso, &fb);
363
364 /* draw quad */
365 buf = setup_vertex_data_tex(ctx,
366 dx1, dy1,
367 dx2, dy2,
368 s0, t0, s1, t1,
369 0.0f);
370
371 if (buf) {
372 util_draw_vertex_buffer(ctx->pipe, buf, 0,
373 PIPE_PRIM_TRIANGLE_FAN,
374 4, /* verts */
375 2); /* attribs/vert */
376
377 pipe_buffer_reference( &buf,
378 NULL );
379 }
380
381 /* restore state we changed */
382 cso_restore_blend(ctx->cso);
383 cso_restore_samplers(ctx->cso);
384 cso_restore_sampler_textures(ctx->cso);
385 cso_restore_framebuffer(ctx->cso);
386 cso_restore_vertex_shader(ctx->cso);
387 cso_restore_fragment_shader(ctx->cso);
388 cso_restore_viewport(ctx->cso);
389
390 pipe_surface_reference(&dst_surf, NULL);
391 }
392
393 void renderer_copy_surface(struct renderer *ctx,
394 struct pipe_surface *src,
395 int srcX0, int srcY0,
396 int srcX1, int srcY1,
397 struct pipe_surface *dst,
398 int dstX0, int dstY0,
399 int dstX1, int dstY1,
400 float z, unsigned filter)
401 {
402 struct pipe_context *pipe = ctx->pipe;
403 struct pipe_screen *screen = pipe->screen;
404 struct pipe_buffer *buf;
405 struct pipe_texture texTemp, *tex;
406 struct pipe_surface *texSurf;
407 struct pipe_framebuffer_state fb;
408 struct st_framebuffer *stfb = ctx->owner->draw_buffer;
409 const int srcW = abs(srcX1 - srcX0);
410 const int srcH = abs(srcY1 - srcY0);
411 const int srcLeft = MIN2(srcX0, srcX1);
412 const int srcTop = MIN2(srcY0, srcY1);
413
414 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
415 filter == PIPE_TEX_MIPFILTER_LINEAR);
416
417 if (srcLeft != srcX0) {
418 /* left-right flip */
419 int tmp = dstX0;
420 dstX0 = dstX1;
421 dstX1 = tmp;
422 }
423
424 if (srcTop != srcY0) {
425 /* up-down flip */
426 int tmp = dstY0;
427 dstY0 = dstY1;
428 dstY1 = tmp;
429 }
430
431 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
432 PIPE_TEXTURE_USAGE_SAMPLER, 0));
433 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
434 PIPE_TEXTURE_USAGE_SAMPLER, 0));
435 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
436 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
437
438 /*
439 * XXX for now we're always creating a temporary texture.
440 * Strictly speaking that's not always needed.
441 */
442
443 /* create temp texture */
444 memset(&texTemp, 0, sizeof(texTemp));
445 texTemp.target = PIPE_TEXTURE_2D;
446 texTemp.format = src->format;
447 texTemp.last_level = 0;
448 texTemp.width0 = srcW;
449 texTemp.height0 = srcH;
450 texTemp.depth0 = 1;
451 pf_get_block(src->format, &texTemp.block);
452
453 tex = screen->texture_create(screen, &texTemp);
454 if (!tex)
455 return;
456
457 texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0,
458 PIPE_BUFFER_USAGE_GPU_WRITE);
459
460 /* load temp texture */
461 if (pipe->surface_copy) {
462 pipe->surface_copy(pipe,
463 texSurf, 0, 0, /* dest */
464 src, srcLeft, srcTop, /* src */
465 srcW, srcH); /* size */
466 } else {
467 util_surface_copy(pipe, FALSE,
468 texSurf, 0, 0, /* dest */
469 src, srcLeft, srcTop, /* src */
470 srcW, srcH); /* size */
471 }
472
473 /* free the surface, update the texture if necessary.*/
474 screen->tex_surface_destroy(texSurf);
475
476 /* save state (restored below) */
477 cso_save_blend(ctx->cso);
478 cso_save_samplers(ctx->cso);
479 cso_save_sampler_textures(ctx->cso);
480 cso_save_framebuffer(ctx->cso);
481 cso_save_fragment_shader(ctx->cso);
482 cso_save_vertex_shader(ctx->cso);
483 cso_save_viewport(ctx->cso);
484
485 /* set misc state we care about */
486 {
487 struct pipe_blend_state blend;
488 memset(&blend, 0, sizeof(blend));
489 blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
490 blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
491 blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
492 blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
493 blend.colormask = PIPE_MASK_RGBA;
494 cso_set_blend(ctx->cso, &blend);
495 }
496
497 vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
498
499 /* sampler */
500 {
501 struct pipe_sampler_state sampler;
502 memset(&sampler, 0, sizeof(sampler));
503 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
504 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
505 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
506 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
507 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
508 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
509 sampler.normalized_coords = 1;
510 cso_single_sampler(ctx->cso, 0, &sampler);
511 cso_single_sampler_done(ctx->cso);
512 }
513
514 /* texture */
515 cso_set_sampler_textures(ctx->cso, 1, &tex);
516
517 /* shaders */
518 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
519 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
520
521 /* drawing dest */
522 if (stfb->strb->surface != dst) {
523 memset(&fb, 0, sizeof(fb));
524 fb.width = dst->width;
525 fb.height = dst->height;
526 fb.nr_cbufs = 1;
527 fb.cbufs[0] = dst;
528 fb.zsbuf = stfb->dsrb->surface;
529 cso_set_framebuffer(ctx->cso, &fb);
530 }
531
532 /* draw quad */
533 buf = setup_vertex_data(ctx,
534 (float) dstX0, (float) dstY0,
535 (float) dstX1, (float) dstY1, z);
536
537 if (buf) {
538 util_draw_vertex_buffer(ctx->pipe, buf, 0,
539 PIPE_PRIM_TRIANGLE_FAN,
540 4, /* verts */
541 2); /* attribs/vert */
542
543 pipe_buffer_reference( &buf,
544 NULL );
545 }
546
547
548 /* restore state we changed */
549 cso_restore_blend(ctx->cso);
550 cso_restore_samplers(ctx->cso);
551 cso_restore_sampler_textures(ctx->cso);
552 cso_restore_framebuffer(ctx->cso);
553 cso_restore_fragment_shader(ctx->cso);
554 cso_restore_vertex_shader(ctx->cso);
555 cso_restore_viewport(ctx->cso);
556
557 pipe_texture_reference(&tex, NULL);
558 }
559
560 void renderer_texture_quad(struct renderer *r,
561 struct pipe_texture *tex,
562 VGfloat x1offset, VGfloat y1offset,
563 VGfloat x2offset, VGfloat y2offset,
564 VGfloat x1, VGfloat y1,
565 VGfloat x2, VGfloat y2,
566 VGfloat x3, VGfloat y3,
567 VGfloat x4, VGfloat y4)
568 {
569 struct pipe_context *pipe = r->pipe;
570 struct pipe_buffer *buf;
571 VGfloat s0, t0, s1, t1;
572
573 assert(tex->width0 != 0);
574 assert(tex->height0 != 0);
575
576 s0 = x1offset / tex->width0;
577 s1 = x2offset / tex->width0;
578 t0 = y1offset / tex->height0;
579 t1 = y2offset / tex->height0;
580
581 cso_save_vertex_shader(r->cso);
582 /* shaders */
583 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
584
585 /* draw quad */
586 buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4,
587 s0, t0, s1, t1, 0.0f);
588
589 if (buf) {
590 util_draw_vertex_buffer(pipe, buf, 0,
591 PIPE_PRIM_TRIANGLE_FAN,
592 4, /* verts */
593 2); /* attribs/vert */
594
595 pipe_buffer_reference(&buf,
596 NULL);
597 }
598
599 cso_restore_vertex_shader(r->cso);
600 }