st/vega: Destroy the pipe context with vg_context.
[mesa.git] / src / gallium / state_trackers / vega / vg_manager.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.9
4 *
5 * Copyright 2009 VMware, Inc. All Rights Reserved.
6 * Copyright (C) 2010 LunarG Inc.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Chia-I Wu <olv@lunarg.com>
28 */
29
30 #include "state_tracker/st_api.h"
31
32 #include "pipe/p_context.h"
33 #include "pipe/p_screen.h"
34 #include "util/u_memory.h"
35 #include "util/u_inlines.h"
36 #include "util/u_sampler.h"
37 #include "util/u_box.h"
38 #include "util/u_surface.h"
39
40 #include "vg_api.h"
41 #include "vg_manager.h"
42 #include "vg_context.h"
43 #include "image.h"
44 #include "api.h"
45
46 static boolean
47 vg_context_update_color_rb(struct vg_context *ctx, struct pipe_resource *pt)
48 {
49 struct st_renderbuffer *strb = ctx->draw_buffer->strb;
50 struct pipe_context *pipe = ctx->pipe;
51 struct pipe_surface surf_tmpl;
52
53 if (strb->texture == pt) {
54 pipe_resource_reference(&pt, NULL);
55 return FALSE;
56 }
57
58 /* unreference existing ones */
59 pipe_surface_reference(&strb->surface, NULL);
60 pipe_resource_reference(&strb->texture, NULL);
61 strb->width = strb->height = 0;
62
63 strb->texture = pt;
64
65 memset(&surf_tmpl, 0, sizeof(surf_tmpl));
66 u_surface_default_template(&surf_tmpl, strb->texture,
67 PIPE_BIND_RENDER_TARGET);
68 strb->surface = pipe->create_surface(pipe, strb->texture, &surf_tmpl);
69
70 if (!strb->surface) {
71 pipe_resource_reference(&strb->texture, NULL);
72 return TRUE;
73 }
74
75 strb->width = pt->width0;
76 strb->height = pt->height0;
77
78 return TRUE;
79 }
80
81 /**
82 * Flush the front buffer if the current context renders to the front buffer.
83 */
84 void
85 vg_manager_flush_frontbuffer(struct vg_context *ctx)
86 {
87 struct st_framebuffer *stfb = ctx->draw_buffer;
88
89 if (!stfb)
90 return;
91
92 switch (stfb->strb_att) {
93 case ST_ATTACHMENT_FRONT_LEFT:
94 case ST_ATTACHMENT_FRONT_RIGHT:
95 stfb->iface->flush_front(stfb->iface, stfb->strb_att);
96 break;
97 default:
98 break;
99 }
100 }
101
102 /**
103 * Re-validate the framebuffer.
104 */
105 void
106 vg_manager_validate_framebuffer(struct vg_context *ctx)
107 {
108 struct st_framebuffer *stfb = ctx->draw_buffer;
109 struct pipe_resource *pt;
110
111 /* no binding surface */
112 if (!stfb)
113 return;
114
115 if (!p_atomic_read(&ctx->draw_buffer_invalid))
116 return;
117
118 /* validate the fb */
119 if (!stfb->iface->validate(stfb->iface, &stfb->strb_att, 1, &pt) || !pt)
120 return;
121
122 p_atomic_set(&ctx->draw_buffer_invalid, FALSE);
123
124 if (vg_context_update_color_rb(ctx, pt) ||
125 stfb->width != pt->width0 ||
126 stfb->height != pt->height0)
127 ctx->state.dirty |= FRAMEBUFFER_DIRTY;
128
129 stfb->width = pt->width0;
130 stfb->height = pt->height0;
131 }
132
133 static void
134 vg_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
135 struct st_framebuffer_iface *stfbi)
136 {
137 struct vg_context *ctx = (struct vg_context *) stctxi;
138 p_atomic_set(&ctx->draw_buffer_invalid, TRUE);
139 }
140
141 static void
142 vg_context_flush(struct st_context_iface *stctxi, unsigned flags,
143 struct pipe_fence_handle **fence)
144 {
145 struct vg_context *ctx = (struct vg_context *) stctxi;
146 ctx->pipe->flush(ctx->pipe, flags, fence);
147 if (flags & PIPE_FLUSH_RENDER_CACHE)
148 vg_manager_flush_frontbuffer(ctx);
149 }
150
151 static void
152 vg_context_destroy(struct st_context_iface *stctxi)
153 {
154 struct vg_context *ctx = (struct vg_context *) stctxi;
155 struct pipe_context *pipe = ctx->pipe;
156
157 vg_destroy_context(ctx);
158 pipe->destroy(pipe);
159 }
160
161 static struct st_context_iface *
162 vg_api_create_context(struct st_api *stapi, struct st_manager *smapi,
163 const struct st_context_attribs *attribs,
164 struct st_context_iface *shared_stctxi)
165 {
166 struct vg_context *shared_ctx = (struct vg_context *) shared_stctxi;
167 struct vg_context *ctx;
168 struct pipe_context *pipe;
169
170 if (!(stapi->profile_mask & (1 << attribs->profile)))
171 return NULL;
172
173 /* only 1.0 is supported */
174 if (attribs->major > 1 || (attribs->major == 1 && attribs->minor > 0))
175 return NULL;
176
177 pipe = smapi->screen->context_create(smapi->screen, NULL);
178 if (!pipe)
179 return NULL;
180 ctx = vg_create_context(pipe, NULL, shared_ctx);
181 if (!ctx) {
182 pipe->destroy(pipe);
183 return NULL;
184 }
185
186 ctx->iface.destroy = vg_context_destroy;
187
188 ctx->iface.notify_invalid_framebuffer =
189 vg_context_notify_invalid_framebuffer;
190 ctx->iface.flush = vg_context_flush;
191
192 ctx->iface.teximage = NULL;
193 ctx->iface.copy = NULL;
194
195 ctx->iface.st_context_private = (void *) smapi;
196
197 return &ctx->iface;
198 }
199
200 static struct st_renderbuffer *
201 create_renderbuffer(enum pipe_format format)
202 {
203 struct st_renderbuffer *strb;
204
205 strb = CALLOC_STRUCT(st_renderbuffer);
206 if (strb)
207 strb->format = format;
208
209 return strb;
210 }
211
212 static void
213 destroy_renderbuffer(struct st_renderbuffer *strb)
214 {
215 pipe_surface_reference(&strb->surface, NULL);
216 pipe_resource_reference(&strb->texture, NULL);
217 FREE(strb);
218 }
219
220 /**
221 * Decide the buffer to render to.
222 */
223 static enum st_attachment_type
224 choose_attachment(struct st_framebuffer_iface *stfbi)
225 {
226 enum st_attachment_type statt;
227
228 statt = stfbi->visual->render_buffer;
229 if (statt != ST_ATTACHMENT_INVALID) {
230 /* use the buffer given by the visual, unless it is unavailable */
231 if (!st_visual_have_buffers(stfbi->visual, 1 << statt)) {
232 switch (statt) {
233 case ST_ATTACHMENT_BACK_LEFT:
234 statt = ST_ATTACHMENT_FRONT_LEFT;
235 break;
236 case ST_ATTACHMENT_BACK_RIGHT:
237 statt = ST_ATTACHMENT_FRONT_RIGHT;
238 break;
239 default:
240 break;
241 }
242
243 if (!st_visual_have_buffers(stfbi->visual, 1 << statt))
244 statt = ST_ATTACHMENT_INVALID;
245 }
246 }
247
248 return statt;
249 }
250
251 /**
252 * Bind the context to the given framebuffers.
253 */
254 static boolean
255 vg_context_bind_framebuffers(struct st_context_iface *stctxi,
256 struct st_framebuffer_iface *stdrawi,
257 struct st_framebuffer_iface *streadi)
258 {
259 struct vg_context *ctx = (struct vg_context *) stctxi;
260 struct st_framebuffer *stfb;
261 enum st_attachment_type strb_att;
262
263 /* the draw and read framebuffers must be the same */
264 if (stdrawi != streadi)
265 return FALSE;
266
267 p_atomic_set(&ctx->draw_buffer_invalid, TRUE);
268
269 strb_att = (stdrawi) ? choose_attachment(stdrawi) : ST_ATTACHMENT_INVALID;
270
271 if (ctx->draw_buffer) {
272 stfb = ctx->draw_buffer;
273
274 /* free the existing fb */
275 if (!stdrawi ||
276 stfb->strb_att != strb_att ||
277 stfb->strb->format != stdrawi->visual->color_format) {
278 destroy_renderbuffer(stfb->strb);
279 destroy_renderbuffer(stfb->dsrb);
280 FREE(stfb);
281
282 ctx->draw_buffer = NULL;
283 }
284 }
285
286 if (!stdrawi)
287 return TRUE;
288
289 if (strb_att == ST_ATTACHMENT_INVALID)
290 return FALSE;
291
292 /* create a new fb */
293 if (!ctx->draw_buffer) {
294 stfb = CALLOC_STRUCT(st_framebuffer);
295 if (!stfb)
296 return FALSE;
297
298 stfb->strb = create_renderbuffer(stdrawi->visual->color_format);
299 if (!stfb->strb) {
300 FREE(stfb);
301 return FALSE;
302 }
303
304 stfb->dsrb = create_renderbuffer(ctx->ds_format);
305 if (!stfb->dsrb) {
306 FREE(stfb->strb);
307 FREE(stfb);
308 return FALSE;
309 }
310
311 stfb->width = 0;
312 stfb->height = 0;
313 stfb->strb_att = strb_att;
314
315 ctx->draw_buffer = stfb;
316 }
317
318 ctx->draw_buffer->iface = stdrawi;
319
320 return TRUE;
321 }
322
323 static boolean
324 vg_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
325 struct st_framebuffer_iface *stdrawi,
326 struct st_framebuffer_iface *streadi)
327 {
328 struct vg_context *ctx = (struct vg_context *) stctxi;
329
330 if (stctxi)
331 vg_context_bind_framebuffers(stctxi, stdrawi, streadi);
332 vg_set_current_context(ctx);
333
334 return TRUE;
335 }
336
337 static struct st_context_iface *
338 vg_api_get_current(struct st_api *stapi)
339 {
340 struct vg_context *ctx = vg_current_context();
341
342 return (ctx) ? &ctx->iface : NULL;
343 }
344
345 static st_proc_t
346 vg_api_get_proc_address(struct st_api *stapi, const char *procname)
347 {
348 return api_get_proc_address(procname);
349 }
350
351 static void
352 vg_api_destroy(struct st_api *stapi)
353 {
354 }
355
356 static const struct st_api vg_api = {
357 "Vega " VEGA_VERSION_STRING,
358 ST_API_OPENVG,
359 ST_PROFILE_DEFAULT_MASK,
360 vg_api_destroy,
361 vg_api_get_proc_address,
362 vg_api_create_context,
363 vg_api_make_current,
364 vg_api_get_current,
365 };
366
367 const struct st_api *
368 vg_api_get(void)
369 {
370 return &vg_api;
371 }