2 * Mesa 3-D graphics library
5 * Copyright 2009 VMware, Inc. All Rights Reserved.
6 * Copyright (C) 2010 LunarG Inc.
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:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
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.
27 * Chia-I Wu <olv@lunarg.com>
30 #include "state_tracker/st_api.h"
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"
40 #include "vg_manager.h"
41 #include "vg_context.h"
46 vg_context_update_color_rb(struct vg_context
*ctx
, struct pipe_resource
*pt
)
48 struct st_renderbuffer
*strb
= ctx
->draw_buffer
->strb
;
49 struct pipe_context
*pipe
= ctx
->pipe
;
50 struct pipe_surface surf_tmpl
;
52 if (strb
->texture
== pt
) {
53 pipe_resource_reference(&pt
, NULL
);
57 /* unreference existing ones */
58 pipe_surface_reference(&strb
->surface
, NULL
);
59 pipe_resource_reference(&strb
->texture
, NULL
);
60 strb
->width
= strb
->height
= 0;
64 memset(&surf_tmpl
, 0, sizeof(surf_tmpl
));
65 u_surface_default_template(&surf_tmpl
, strb
->texture
,
66 PIPE_BIND_RENDER_TARGET
);
67 strb
->surface
= pipe
->create_surface(pipe
, strb
->texture
, &surf_tmpl
);
70 pipe_resource_reference(&strb
->texture
, NULL
);
74 strb
->width
= pt
->width0
;
75 strb
->height
= pt
->height0
;
81 * Flush the front buffer if the current context renders to the front buffer.
84 vg_manager_flush_frontbuffer(struct vg_context
*ctx
)
86 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
91 switch (stfb
->strb_att
) {
92 case ST_ATTACHMENT_FRONT_LEFT
:
93 case ST_ATTACHMENT_FRONT_RIGHT
:
94 stfb
->iface
->flush_front(stfb
->iface
, stfb
->strb_att
);
102 * Re-validate the framebuffer.
105 vg_manager_validate_framebuffer(struct vg_context
*ctx
)
107 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
108 struct pipe_resource
*pt
;
110 /* no binding surface */
114 if (!p_atomic_read(&ctx
->draw_buffer_invalid
))
117 /* validate the fb */
118 if (!stfb
->iface
->validate(stfb
->iface
, &stfb
->strb_att
, 1, &pt
) || !pt
)
121 p_atomic_set(&ctx
->draw_buffer_invalid
, FALSE
);
123 if (vg_context_update_color_rb(ctx
, pt
) ||
124 stfb
->width
!= pt
->width0
||
125 stfb
->height
!= pt
->height0
)
126 ctx
->state
.dirty
|= FRAMEBUFFER_DIRTY
;
128 stfb
->width
= pt
->width0
;
129 stfb
->height
= pt
->height0
;
133 vg_context_notify_invalid_framebuffer(struct st_context_iface
*stctxi
,
134 struct st_framebuffer_iface
*stfbi
)
136 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
137 p_atomic_set(&ctx
->draw_buffer_invalid
, TRUE
);
141 vg_context_flush(struct st_context_iface
*stctxi
, unsigned flags
,
142 struct pipe_fence_handle
**fence
)
144 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
145 ctx
->pipe
->flush(ctx
->pipe
, fence
);
146 if (flags
& ST_FLUSH_FRONT
)
147 vg_manager_flush_frontbuffer(ctx
);
151 vg_context_destroy(struct st_context_iface
*stctxi
)
153 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
154 struct pipe_context
*pipe
= ctx
->pipe
;
156 vg_destroy_context(ctx
);
160 static struct st_context_iface
*
161 vg_api_create_context(struct st_api
*stapi
, struct st_manager
*smapi
,
162 const struct st_context_attribs
*attribs
,
163 struct st_context_iface
*shared_stctxi
)
165 struct vg_context
*shared_ctx
= (struct vg_context
*) shared_stctxi
;
166 struct vg_context
*ctx
;
167 struct pipe_context
*pipe
;
169 if (!(stapi
->profile_mask
& (1 << attribs
->profile
)))
172 /* only 1.0 is supported */
173 if (attribs
->major
> 1 || (attribs
->major
== 1 && attribs
->minor
> 0))
176 /* for VGHandle / pointer lookups */
179 pipe
= smapi
->screen
->context_create(smapi
->screen
, NULL
);
182 ctx
= vg_create_context(pipe
, NULL
, shared_ctx
);
188 ctx
->iface
.destroy
= vg_context_destroy
;
190 ctx
->iface
.notify_invalid_framebuffer
=
191 vg_context_notify_invalid_framebuffer
;
192 ctx
->iface
.flush
= vg_context_flush
;
194 ctx
->iface
.teximage
= NULL
;
195 ctx
->iface
.copy
= NULL
;
197 ctx
->iface
.st_context_private
= (void *) smapi
;
202 static struct st_renderbuffer
*
203 create_renderbuffer(enum pipe_format format
)
205 struct st_renderbuffer
*strb
;
207 strb
= CALLOC_STRUCT(st_renderbuffer
);
209 strb
->format
= format
;
215 destroy_renderbuffer(struct st_renderbuffer
*strb
)
217 pipe_surface_reference(&strb
->surface
, NULL
);
218 pipe_resource_reference(&strb
->texture
, NULL
);
223 * Decide the buffer to render to.
225 static enum st_attachment_type
226 choose_attachment(struct st_framebuffer_iface
*stfbi
)
228 enum st_attachment_type statt
;
230 statt
= stfbi
->visual
->render_buffer
;
231 if (statt
!= ST_ATTACHMENT_INVALID
) {
232 /* use the buffer given by the visual, unless it is unavailable */
233 if (!st_visual_have_buffers(stfbi
->visual
, 1 << statt
)) {
235 case ST_ATTACHMENT_BACK_LEFT
:
236 statt
= ST_ATTACHMENT_FRONT_LEFT
;
238 case ST_ATTACHMENT_BACK_RIGHT
:
239 statt
= ST_ATTACHMENT_FRONT_RIGHT
;
245 if (!st_visual_have_buffers(stfbi
->visual
, 1 << statt
))
246 statt
= ST_ATTACHMENT_INVALID
;
254 * Bind the context to the given framebuffers.
257 vg_context_bind_framebuffers(struct st_context_iface
*stctxi
,
258 struct st_framebuffer_iface
*stdrawi
,
259 struct st_framebuffer_iface
*streadi
)
261 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
262 struct st_framebuffer
*stfb
;
263 enum st_attachment_type strb_att
;
265 /* the draw and read framebuffers must be the same */
266 if (stdrawi
!= streadi
)
269 p_atomic_set(&ctx
->draw_buffer_invalid
, TRUE
);
271 strb_att
= (stdrawi
) ? choose_attachment(stdrawi
) : ST_ATTACHMENT_INVALID
;
273 if (ctx
->draw_buffer
) {
274 stfb
= ctx
->draw_buffer
;
276 /* free the existing fb */
278 stfb
->strb_att
!= strb_att
||
279 stfb
->strb
->format
!= stdrawi
->visual
->color_format
) {
280 destroy_renderbuffer(stfb
->strb
);
281 destroy_renderbuffer(stfb
->dsrb
);
284 ctx
->draw_buffer
= NULL
;
291 if (strb_att
== ST_ATTACHMENT_INVALID
)
294 /* create a new fb */
295 if (!ctx
->draw_buffer
) {
296 stfb
= CALLOC_STRUCT(st_framebuffer
);
300 stfb
->strb
= create_renderbuffer(stdrawi
->visual
->color_format
);
306 stfb
->dsrb
= create_renderbuffer(ctx
->ds_format
);
315 stfb
->strb_att
= strb_att
;
317 ctx
->draw_buffer
= stfb
;
320 ctx
->draw_buffer
->iface
= stdrawi
;
326 vg_api_make_current(struct st_api
*stapi
, struct st_context_iface
*stctxi
,
327 struct st_framebuffer_iface
*stdrawi
,
328 struct st_framebuffer_iface
*streadi
)
330 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
333 vg_context_bind_framebuffers(stctxi
, stdrawi
, streadi
);
334 vg_set_current_context(ctx
);
339 static struct st_context_iface
*
340 vg_api_get_current(struct st_api
*stapi
)
342 struct vg_context
*ctx
= vg_current_context();
344 return (ctx
) ? &ctx
->iface
: NULL
;
348 vg_api_get_proc_address(struct st_api
*stapi
, const char *procname
)
350 return api_get_proc_address(procname
);
354 vg_api_destroy(struct st_api
*stapi
)
358 static const struct st_api vg_api
= {
359 "Vega " VEGA_VERSION_STRING
,
361 ST_PROFILE_DEFAULT_MASK
,
363 vg_api_get_proc_address
,
364 vg_api_create_context
,
369 const struct st_api
*