fixups for interface changes (mostly state trackers)
[mesa.git] / src / gallium / state_trackers / vega / vg_tracker.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 "vg_context.h"
28 #include "vg_tracker.h"
29 #include "mask.h"
30
31 #include "pipe/p_context.h"
32 #include "pipe/p_inlines.h"
33 #include "pipe/p_screen.h"
34 #include "util/u_memory.h"
35 #include "util/u_math.h"
36
37 static struct pipe_texture *
38 create_texture(struct pipe_context *pipe, enum pipe_format format,
39 VGint width, VGint height)
40 {
41 struct pipe_texture templ;
42
43 memset(&templ, 0, sizeof(templ));
44
45 if (format != PIPE_FORMAT_NONE) {
46 templ.format = format;
47 }
48 else {
49 templ.format = PIPE_FORMAT_A8R8G8B8_UNORM;
50 }
51
52 templ.target = PIPE_TEXTURE_2D;
53 templ.width0 = width;
54 templ.height0 = height;
55 templ.depth0 = 1;
56 templ.last_level = 0;
57
58 if (pf_get_component_bits(format, PIPE_FORMAT_COMP_S)) {
59 templ.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
60 } else {
61 templ.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
62 PIPE_TEXTURE_USAGE_RENDER_TARGET |
63 PIPE_TEXTURE_USAGE_SAMPLER);
64 }
65
66 return pipe->screen->texture_create(pipe->screen, &templ);
67 }
68
69 /**
70 * Allocate a renderbuffer for a an on-screen window (not a user-created
71 * renderbuffer). The window system code determines the format.
72 */
73 static struct st_renderbuffer *
74 st_new_renderbuffer_fb(enum pipe_format format)
75 {
76 struct st_renderbuffer *strb;
77
78 strb = CALLOC_STRUCT(st_renderbuffer);
79 if (!strb) {
80 /*_vega_error(NULL, VG_OUT_OF_MEMORY, "creating renderbuffer");*/
81 return NULL;
82 }
83
84 strb->format = format;
85
86 return strb;
87 }
88
89
90 /**
91 * This is called to allocate the original drawing surface, and
92 * during window resize.
93 */
94 static VGboolean
95 st_renderbuffer_alloc_storage(struct vg_context * ctx,
96 struct st_renderbuffer *strb,
97 VGuint width, VGuint height)
98 {
99 struct pipe_context *pipe = ctx->pipe;
100 unsigned surface_usage;
101
102 /* Free the old surface and texture
103 */
104 pipe_surface_reference(&strb->surface, NULL);
105 pipe_texture_reference(&strb->texture, NULL);
106
107
108 /* Probably need dedicated flags for surface usage too:
109 */
110 surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
111 PIPE_BUFFER_USAGE_GPU_WRITE);
112
113 strb->texture = create_texture(pipe, strb->format,
114 width, height);
115
116 if (!strb->texture)
117 return FALSE;
118
119 strb->surface = pipe->screen->get_tex_surface(pipe->screen,
120 strb->texture,
121 0, 0, 0,
122 surface_usage);
123 strb->width = width;
124 strb->height = height;
125
126 assert(strb->surface->width == width);
127 assert(strb->surface->height == height);
128
129 return strb->surface != NULL;
130 }
131
132 struct vg_context * st_create_context(struct pipe_context *pipe,
133 const void *visual,
134 struct vg_context *share)
135 {
136 struct vg_context *ctx = vg_create_context(pipe, visual, share);
137 /*debug_printf("--------- CREATE CONTEXT %p\n", ctx);*/
138 return ctx;
139 }
140
141 void st_destroy_context(struct vg_context *st)
142 {
143 /*debug_printf("--------- DESTROY CONTEXT %p\n", st);*/
144 vg_destroy_context(st);
145 }
146
147 void st_copy_context_state(struct vg_context *dst, struct vg_context *src,
148 uint mask)
149 {
150 fprintf(stderr, "FIXME: %s\n", __FUNCTION__);
151 }
152
153 void st_get_framebuffer_dimensions(struct st_framebuffer *stfb,
154 uint *width,
155 uint *height)
156 {
157 *width = stfb->strb->width;
158 *height = stfb->strb->height;
159 }
160
161 struct st_framebuffer * st_create_framebuffer(const void *visual,
162 enum pipe_format colorFormat,
163 enum pipe_format depthFormat,
164 enum pipe_format stencilFormat,
165 uint width, uint height,
166 void *privateData)
167 {
168 struct st_framebuffer *stfb = CALLOC_STRUCT(st_framebuffer);
169 if (stfb) {
170 struct st_renderbuffer *rb =
171 st_new_renderbuffer_fb(colorFormat);
172 stfb->strb = rb;
173 #if 0
174 if (doubleBuffer) {
175 struct st_renderbuffer *rb =
176 st_new_renderbuffer_fb(colorFormat);
177 }
178 #endif
179
180 /* we want to combine the depth/stencil */
181 if (stencilFormat == depthFormat)
182 stfb->dsrb = st_new_renderbuffer_fb(stencilFormat);
183 else
184 stfb->dsrb = st_new_renderbuffer_fb(PIPE_FORMAT_S8Z24_UNORM);
185
186 /*### currently we always allocate it but it's possible it's
187 not necessary if EGL_ALPHA_MASK_SIZE was 0
188 */
189 stfb->alpha_mask = 0;
190
191 stfb->init_width = width;
192 stfb->init_height = height;
193 stfb->privateData = privateData;
194 }
195
196 return stfb;
197 }
198
199 static void setup_new_alpha_mask(struct vg_context *ctx,
200 struct st_framebuffer *stfb,
201 uint width, uint height)
202 {
203 struct pipe_context *pipe = ctx->pipe;
204 struct pipe_texture *old_texture = stfb->alpha_mask;
205
206 /*
207 we use PIPE_FORMAT_A8R8G8B8_UNORM because we want to render to
208 this texture and use it as a sampler, so while this wastes some
209 space it makes both of those a lot simpler
210 */
211 stfb->alpha_mask =
212 create_texture(pipe, PIPE_FORMAT_A8R8G8B8_UNORM, width, height);
213
214 if (!stfb->alpha_mask) {
215 if (old_texture)
216 pipe_texture_reference(&old_texture, NULL);
217 return;
218 }
219
220 vg_validate_state(ctx);
221
222 /* alpha mask starts with 1.f alpha */
223 mask_fill(0, 0, width, height, 1.f);
224
225 /* if we had an old surface copy it over */
226 if (old_texture) {
227 struct pipe_surface *surface = pipe->screen->get_tex_surface(
228 pipe->screen,
229 stfb->alpha_mask,
230 0, 0, 0,
231 PIPE_BUFFER_USAGE_GPU_WRITE);
232 struct pipe_surface *old_surface = pipe->screen->get_tex_surface(
233 pipe->screen,
234 old_texture,
235 0, 0, 0,
236 PIPE_BUFFER_USAGE_GPU_READ);
237 if (pipe->surface_copy) {
238 pipe->surface_copy(pipe,
239 surface,
240 0, 0,
241 old_surface,
242 0, 0,
243 MIN2(old_surface->width, width),
244 MIN2(old_surface->height, height));
245 } else {
246 util_surface_copy(pipe, FALSE,
247 surface,
248 0, 0,
249 old_surface,
250 0, 0,
251 MIN2(old_surface->width, width),
252 MIN2(old_surface->height, height));
253 }
254 if (surface)
255 pipe_surface_reference(&surface, NULL);
256 if (old_surface)
257 pipe_surface_reference(&old_surface, NULL);
258 }
259
260 /* Free the old texture
261 */
262 if (old_texture)
263 pipe_texture_reference(&old_texture, NULL);
264 }
265
266 void st_resize_framebuffer(struct st_framebuffer *stfb,
267 uint width, uint height)
268 {
269 struct vg_context *ctx = vg_current_context();
270 struct st_renderbuffer *strb = stfb->strb;
271 struct pipe_framebuffer_state *state;
272
273 if (!ctx)
274 return;
275
276 state = &ctx->state.g3d.fb;
277
278 /* If this is a noop, exit early and don't do the clear, etc below.
279 */
280 if (strb->width == width &&
281 strb->height == height &&
282 state->zsbuf)
283 return;
284
285 if (strb->width != width || strb->height != height)
286 st_renderbuffer_alloc_storage(ctx, strb,
287 width, height);
288
289 if (stfb->dsrb->width != width || stfb->dsrb->height != height)
290 st_renderbuffer_alloc_storage(ctx, stfb->dsrb,
291 width, height);
292
293 {
294 VGuint i;
295
296 memset(state, 0, sizeof(struct pipe_framebuffer_state));
297
298 state->width = width;
299 state->height = height;
300
301 state->nr_cbufs = 1;
302 state->cbufs[0] = strb->surface;
303 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
304 state->cbufs[i] = 0;
305
306 state->zsbuf = stfb->dsrb->surface;
307
308 cso_set_framebuffer(ctx->cso_context, state);
309 }
310
311 ctx->state.dirty |= VIEWPORT_DIRTY;
312 ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/
313
314 ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL,
315 NULL, 0.0, 0);
316
317 /* we need all the other state already set */
318
319 setup_new_alpha_mask(ctx, stfb, width, height);
320
321 pipe_texture_reference( &stfb->blend_texture, NULL );
322 stfb->blend_texture = create_texture(ctx->pipe, PIPE_FORMAT_A8R8G8B8_UNORM,
323 width, height);
324 }
325
326 void st_set_framebuffer_surface(struct st_framebuffer *stfb,
327 uint surfIndex, struct pipe_surface *surf)
328 {
329 struct st_renderbuffer *rb = stfb->strb;
330
331 /* unreference existing surfaces */
332 pipe_surface_reference( &rb->surface, NULL );
333 pipe_texture_reference( &rb->texture, NULL );
334
335 /* reference new ones */
336 pipe_surface_reference( &rb->surface, surf );
337 pipe_texture_reference( &rb->texture, surf->texture );
338
339 rb->width = surf->width;
340 rb->height = surf->height;
341 }
342
343 int st_get_framebuffer_surface(struct st_framebuffer *stfb,
344 uint surfIndex, struct pipe_surface **surf)
345 {
346 struct st_renderbuffer *rb = stfb->strb;
347 *surf = rb->surface;
348 return VG_TRUE;
349 }
350
351 int st_get_framebuffer_texture(struct st_framebuffer *stfb,
352 uint surfIndex, struct pipe_texture **tex)
353 {
354 struct st_renderbuffer *rb = stfb->strb;
355 *tex = rb->texture;
356 return VG_TRUE;
357 }
358
359 void * st_framebuffer_private(struct st_framebuffer *stfb)
360 {
361 return stfb->privateData;
362 }
363
364 void st_unreference_framebuffer(struct st_framebuffer *stfb)
365 {
366 /* FIXME */
367 }
368
369 void st_make_current(struct vg_context *st,
370 struct st_framebuffer *draw,
371 struct st_framebuffer *read)
372 {
373 vg_set_current_context(st);
374 if (st) {
375 st->draw_buffer = draw;
376 }
377 }
378
379 struct vg_context *st_get_current(void)
380 {
381 return vg_current_context();
382 }
383
384 void st_flush(struct vg_context *st, uint pipeFlushFlags,
385 struct pipe_fence_handle **fence)
386 {
387 st->pipe->flush(st->pipe, pipeFlushFlags, fence);
388 }
389
390 void st_finish(struct vg_context *st)
391 {
392 struct pipe_fence_handle *fence = NULL;
393
394 st_flush(st, PIPE_FLUSH_RENDER_CACHE, &fence);
395
396 st->pipe->screen->fence_finish(st->pipe->screen, fence, 0);
397 st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL);
398 }
399
400 void st_notify_swapbuffers(struct st_framebuffer *stfb)
401 {
402 struct vg_context *ctx = vg_current_context();
403 if (ctx && ctx->draw_buffer == stfb) {
404 st_flush(ctx,
405 PIPE_FLUSH_RENDER_CACHE |
406 PIPE_FLUSH_SWAPBUFFERS |
407 PIPE_FLUSH_FRAME,
408 NULL);
409 }
410 }
411
412 void st_notify_swapbuffers_complete(struct st_framebuffer *stfb)
413 {
414 }
415
416 int st_bind_texture_surface(struct pipe_surface *ps, int target, int level,
417 enum pipe_format format)
418 {
419 return 0;
420 }
421
422 int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level)
423 {
424 return 0;
425 }