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
;
111 /* no binding surface */
115 new_stamp
= p_atomic_read(&stfb
->iface
->stamp
);
116 if (stfb
->iface_stamp
!= new_stamp
) {
118 /* validate the fb */
119 if (!stfb
->iface
->validate(stfb
->iface
, &stfb
->strb_att
,
123 stfb
->iface_stamp
= new_stamp
;
124 new_stamp
= p_atomic_read(&stfb
->iface
->stamp
);
126 } while (stfb
->iface_stamp
!= new_stamp
);
128 if (vg_context_update_color_rb(ctx
, pt
) ||
129 stfb
->width
!= pt
->width0
||
130 stfb
->height
!= pt
->height0
)
133 stfb
->width
= pt
->width0
;
134 stfb
->height
= pt
->height0
;
137 if (ctx
->draw_stamp
!= stfb
->stamp
) {
138 ctx
->state
.dirty
|= FRAMEBUFFER_DIRTY
;
139 ctx
->draw_stamp
= stfb
->stamp
;
144 vg_context_flush(struct st_context_iface
*stctxi
, unsigned flags
,
145 struct pipe_fence_handle
**fence
)
147 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
148 ctx
->pipe
->flush(ctx
->pipe
, fence
);
149 if (flags
& ST_FLUSH_FRONT
)
150 vg_manager_flush_frontbuffer(ctx
);
154 vg_context_destroy(struct st_context_iface
*stctxi
)
156 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
157 struct pipe_context
*pipe
= ctx
->pipe
;
159 vg_destroy_context(ctx
);
163 static struct st_context_iface
*
164 vg_api_create_context(struct st_api
*stapi
, struct st_manager
*smapi
,
165 const struct st_context_attribs
*attribs
,
166 struct st_context_iface
*shared_stctxi
)
168 struct vg_context
*shared_ctx
= (struct vg_context
*) shared_stctxi
;
169 struct vg_context
*ctx
;
170 struct pipe_context
*pipe
;
172 if (!(stapi
->profile_mask
& (1 << attribs
->profile
)))
175 /* only 1.0 is supported */
176 if (attribs
->major
> 1 || (attribs
->major
== 1 && attribs
->minor
> 0))
179 /* for VGHandle / pointer lookups */
182 pipe
= smapi
->screen
->context_create(smapi
->screen
, NULL
);
185 ctx
= vg_create_context(pipe
, NULL
, shared_ctx
);
191 ctx
->iface
.destroy
= vg_context_destroy
;
193 ctx
->iface
.flush
= vg_context_flush
;
195 ctx
->iface
.teximage
= NULL
;
196 ctx
->iface
.copy
= NULL
;
198 ctx
->iface
.st_context_private
= (void *) smapi
;
203 static struct st_renderbuffer
*
204 create_renderbuffer(enum pipe_format format
)
206 struct st_renderbuffer
*strb
;
208 strb
= CALLOC_STRUCT(st_renderbuffer
);
210 strb
->format
= format
;
216 destroy_renderbuffer(struct st_renderbuffer
*strb
)
218 pipe_surface_reference(&strb
->surface
, NULL
);
219 pipe_resource_reference(&strb
->texture
, NULL
);
224 * Decide the buffer to render to.
226 static enum st_attachment_type
227 choose_attachment(struct st_framebuffer_iface
*stfbi
)
229 enum st_attachment_type statt
;
231 statt
= stfbi
->visual
->render_buffer
;
232 if (statt
!= ST_ATTACHMENT_INVALID
) {
233 /* use the buffer given by the visual, unless it is unavailable */
234 if (!st_visual_have_buffers(stfbi
->visual
, 1 << statt
)) {
236 case ST_ATTACHMENT_BACK_LEFT
:
237 statt
= ST_ATTACHMENT_FRONT_LEFT
;
239 case ST_ATTACHMENT_BACK_RIGHT
:
240 statt
= ST_ATTACHMENT_FRONT_RIGHT
;
246 if (!st_visual_have_buffers(stfbi
->visual
, 1 << statt
))
247 statt
= ST_ATTACHMENT_INVALID
;
255 * Bind the context to the given framebuffers.
258 vg_context_bind_framebuffers(struct st_context_iface
*stctxi
,
259 struct st_framebuffer_iface
*stdrawi
,
260 struct st_framebuffer_iface
*streadi
)
262 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
263 struct st_framebuffer
*stfb
;
264 enum st_attachment_type strb_att
;
266 /* the draw and read framebuffers must be the same */
267 if (stdrawi
!= streadi
)
270 strb_att
= (stdrawi
) ? choose_attachment(stdrawi
) : ST_ATTACHMENT_INVALID
;
272 if (ctx
->draw_buffer
) {
273 stfb
= ctx
->draw_buffer
;
275 /* free the existing fb */
277 stfb
->strb_att
!= strb_att
||
278 stfb
->strb
->format
!= stdrawi
->visual
->color_format
) {
279 destroy_renderbuffer(stfb
->strb
);
280 destroy_renderbuffer(stfb
->dsrb
);
283 ctx
->draw_buffer
= NULL
;
290 if (strb_att
== ST_ATTACHMENT_INVALID
)
293 /* create a new fb */
294 if (!ctx
->draw_buffer
) {
295 stfb
= CALLOC_STRUCT(st_framebuffer
);
299 stfb
->strb
= create_renderbuffer(stdrawi
->visual
->color_format
);
305 stfb
->dsrb
= create_renderbuffer(ctx
->ds_format
);
314 stfb
->strb_att
= strb_att
;
316 stfb
->iface_stamp
= p_atomic_read(&stdrawi
->stamp
) - 1;
318 ctx
->draw_buffer
= stfb
;
321 ctx
->draw_buffer
->iface
= stdrawi
;
322 ctx
->draw_stamp
= ctx
->draw_buffer
->stamp
- 1;
328 vg_api_make_current(struct st_api
*stapi
, struct st_context_iface
*stctxi
,
329 struct st_framebuffer_iface
*stdrawi
,
330 struct st_framebuffer_iface
*streadi
)
332 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
335 vg_context_bind_framebuffers(stctxi
, stdrawi
, streadi
);
336 vg_set_current_context(ctx
);
341 static struct st_context_iface
*
342 vg_api_get_current(struct st_api
*stapi
)
344 struct vg_context
*ctx
= vg_current_context();
346 return (ctx
) ? &ctx
->iface
: NULL
;
350 vg_api_get_proc_address(struct st_api
*stapi
, const char *procname
)
352 return api_get_proc_address(procname
);
356 vg_api_destroy(struct st_api
*stapi
)
360 static const struct st_api vg_api
= {
361 "Vega " VEGA_VERSION_STRING
,
363 ST_PROFILE_DEFAULT_MASK
,
365 vg_api_get_proc_address
,
366 vg_api_create_context
,
371 const struct st_api
*