radeonsi: fix int->bool conversion in fence_signalled
[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_box.h"
37 #include "util/u_surface.h"
38
39 #include "vg_api.h"
40 #include "vg_manager.h"
41 #include "vg_context.h"
42 #include "api.h"
43 #include "handle.h"
44
45 static boolean
46 vg_context_update_color_rb(struct vg_context *ctx, struct pipe_resource *pt)
47 {
48 struct st_renderbuffer *strb = ctx->draw_buffer->strb;
49 struct pipe_context *pipe = ctx->pipe;
50 struct pipe_surface surf_tmpl;
51
52 if (strb->texture == pt) {
53 pipe_resource_reference(&pt, NULL);
54 return FALSE;
55 }
56
57 /* unreference existing ones */
58 pipe_surface_reference(&strb->surface, NULL);
59 pipe_resource_reference(&strb->texture, NULL);
60 strb->width = strb->height = 0;
61
62 strb->texture = pt;
63
64 u_surface_default_template(&surf_tmpl, strb->texture);
65 strb->surface = pipe->create_surface(pipe, strb->texture, &surf_tmpl);
66
67 if (!strb->surface) {
68 pipe_resource_reference(&strb->texture, NULL);
69 return TRUE;
70 }
71
72 strb->width = pt->width0;
73 strb->height = pt->height0;
74
75 return TRUE;
76 }
77
78 /**
79 * Flush the front buffer if the current context renders to the front buffer.
80 */
81 void
82 vg_manager_flush_frontbuffer(struct vg_context *ctx)
83 {
84 struct st_framebuffer *stfb = ctx->draw_buffer;
85
86 if (!stfb)
87 return;
88
89 switch (stfb->strb_att) {
90 case ST_ATTACHMENT_FRONT_LEFT:
91 case ST_ATTACHMENT_FRONT_RIGHT:
92 stfb->iface->flush_front(&ctx->iface, stfb->iface, stfb->strb_att);
93 break;
94 default:
95 break;
96 }
97 }
98
99 /**
100 * Re-validate the framebuffer.
101 */
102 void
103 vg_manager_validate_framebuffer(struct vg_context *ctx)
104 {
105 struct st_framebuffer *stfb = ctx->draw_buffer;
106 struct pipe_resource *pt;
107 int32_t new_stamp;
108
109 /* no binding surface */
110 if (!stfb)
111 return;
112
113 new_stamp = p_atomic_read(&stfb->iface->stamp);
114 if (stfb->iface_stamp != new_stamp) {
115 do {
116 /* validate the fb */
117 if (!stfb->iface->validate(stfb->iface, &stfb->strb_att,
118 1, &pt) || !pt)
119 return;
120
121 stfb->iface_stamp = new_stamp;
122 new_stamp = p_atomic_read(&stfb->iface->stamp);
123
124 } while (stfb->iface_stamp != new_stamp);
125
126 if (vg_context_update_color_rb(ctx, pt) ||
127 stfb->width != pt->width0 ||
128 stfb->height != pt->height0)
129 ++stfb->stamp;
130
131 stfb->width = pt->width0;
132 stfb->height = pt->height0;
133 }
134
135 if (ctx->draw_stamp != stfb->stamp) {
136 ctx->state.dirty |= FRAMEBUFFER_DIRTY;
137 ctx->draw_stamp = stfb->stamp;
138 }
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, fence);
147 if (flags & ST_FLUSH_FRONT)
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 enum st_context_error *error,
165 struct st_context_iface *shared_stctxi)
166 {
167 struct vg_context *shared_ctx = (struct vg_context *) shared_stctxi;
168 struct vg_context *ctx;
169 struct pipe_context *pipe;
170
171 if (!(stapi->profile_mask & (1 << attribs->profile))) {
172 *error = ST_CONTEXT_ERROR_BAD_API;
173 return NULL;
174 }
175
176 /* only 1.0 is supported */
177 if (attribs->major > 1 || (attribs->major == 1 && attribs->minor > 0)) {
178 *error = ST_CONTEXT_ERROR_BAD_VERSION;
179 return NULL;
180 }
181
182 /* for VGHandle / pointer lookups */
183 init_handles();
184
185 pipe = smapi->screen->context_create(smapi->screen, NULL);
186 if (!pipe) {
187 *error = ST_CONTEXT_ERROR_NO_MEMORY;
188 return NULL;
189 }
190 ctx = vg_create_context(pipe, NULL, shared_ctx);
191 if (!ctx) {
192 pipe->destroy(pipe);
193 *error = ST_CONTEXT_ERROR_NO_MEMORY;
194 return NULL;
195 }
196
197 ctx->iface.destroy = vg_context_destroy;
198
199 ctx->iface.flush = vg_context_flush;
200
201 ctx->iface.teximage = NULL;
202 ctx->iface.copy = NULL;
203
204 ctx->iface.st_context_private = (void *) smapi;
205
206 return &ctx->iface;
207 }
208
209 static struct st_renderbuffer *
210 create_renderbuffer(enum pipe_format format)
211 {
212 struct st_renderbuffer *strb;
213
214 strb = CALLOC_STRUCT(st_renderbuffer);
215 if (strb)
216 strb->format = format;
217
218 return strb;
219 }
220
221 static void
222 destroy_renderbuffer(struct st_renderbuffer *strb)
223 {
224 pipe_surface_reference(&strb->surface, NULL);
225 pipe_resource_reference(&strb->texture, NULL);
226 FREE(strb);
227 }
228
229 /**
230 * Decide the buffer to render to.
231 */
232 static enum st_attachment_type
233 choose_attachment(struct st_framebuffer_iface *stfbi)
234 {
235 enum st_attachment_type statt;
236
237 statt = stfbi->visual->render_buffer;
238 if (statt != ST_ATTACHMENT_INVALID) {
239 /* use the buffer given by the visual, unless it is unavailable */
240 if (!st_visual_have_buffers(stfbi->visual, 1 << statt)) {
241 switch (statt) {
242 case ST_ATTACHMENT_BACK_LEFT:
243 statt = ST_ATTACHMENT_FRONT_LEFT;
244 break;
245 case ST_ATTACHMENT_BACK_RIGHT:
246 statt = ST_ATTACHMENT_FRONT_RIGHT;
247 break;
248 default:
249 break;
250 }
251
252 if (!st_visual_have_buffers(stfbi->visual, 1 << statt))
253 statt = ST_ATTACHMENT_INVALID;
254 }
255 }
256
257 return statt;
258 }
259
260 /**
261 * Bind the context to the given framebuffers.
262 */
263 static boolean
264 vg_context_bind_framebuffers(struct st_context_iface *stctxi,
265 struct st_framebuffer_iface *stdrawi,
266 struct st_framebuffer_iface *streadi)
267 {
268 struct vg_context *ctx = (struct vg_context *) stctxi;
269 struct st_framebuffer *stfb;
270 enum st_attachment_type strb_att;
271
272 /* the draw and read framebuffers must be the same */
273 if (stdrawi != streadi)
274 return FALSE;
275
276 strb_att = (stdrawi) ? choose_attachment(stdrawi) : ST_ATTACHMENT_INVALID;
277
278 if (ctx->draw_buffer) {
279 stfb = ctx->draw_buffer;
280
281 /* free the existing fb */
282 if (!stdrawi ||
283 stfb->strb_att != strb_att ||
284 stfb->strb->format != stdrawi->visual->color_format) {
285 destroy_renderbuffer(stfb->strb);
286 destroy_renderbuffer(stfb->dsrb);
287 FREE(stfb);
288
289 ctx->draw_buffer = NULL;
290 }
291 }
292
293 if (!stdrawi)
294 return TRUE;
295
296 if (strb_att == ST_ATTACHMENT_INVALID)
297 return FALSE;
298
299 /* create a new fb */
300 if (!ctx->draw_buffer) {
301 stfb = CALLOC_STRUCT(st_framebuffer);
302 if (!stfb)
303 return FALSE;
304
305 stfb->strb = create_renderbuffer(stdrawi->visual->color_format);
306 if (!stfb->strb) {
307 FREE(stfb);
308 return FALSE;
309 }
310
311 stfb->dsrb = create_renderbuffer(ctx->ds_format);
312 if (!stfb->dsrb) {
313 FREE(stfb->strb);
314 FREE(stfb);
315 return FALSE;
316 }
317
318 stfb->width = 0;
319 stfb->height = 0;
320 stfb->strb_att = strb_att;
321 stfb->stamp = 1;
322 stfb->iface_stamp = p_atomic_read(&stdrawi->stamp) - 1;
323
324 ctx->draw_buffer = stfb;
325 }
326
327 ctx->draw_buffer->iface = stdrawi;
328 ctx->draw_stamp = ctx->draw_buffer->stamp - 1;
329
330 return TRUE;
331 }
332
333 static boolean
334 vg_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
335 struct st_framebuffer_iface *stdrawi,
336 struct st_framebuffer_iface *streadi)
337 {
338 struct vg_context *ctx = (struct vg_context *) stctxi;
339
340 if (stctxi)
341 vg_context_bind_framebuffers(stctxi, stdrawi, streadi);
342 vg_set_current_context(ctx);
343
344 return TRUE;
345 }
346
347 static struct st_context_iface *
348 vg_api_get_current(struct st_api *stapi)
349 {
350 struct vg_context *ctx = vg_current_context();
351
352 return (ctx) ? &ctx->iface : NULL;
353 }
354
355 static st_proc_t
356 vg_api_get_proc_address(struct st_api *stapi, const char *procname)
357 {
358 return api_get_proc_address(procname);
359 }
360
361 static void
362 vg_api_destroy(struct st_api *stapi)
363 {
364 }
365
366 static const struct st_api vg_api = {
367 "Vega " VEGA_VERSION_STRING,
368 ST_API_OPENVG,
369 ST_PROFILE_DEFAULT_MASK,
370 0,
371 vg_api_destroy,
372 vg_api_get_proc_address,
373 vg_api_create_context,
374 vg_api_make_current,
375 vg_api_get_current,
376 };
377
378 const struct st_api *
379 vg_api_get(void)
380 {
381 return &vg_api;
382 }