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 u_surface_default_template(&surf_tmpl
, strb
->texture
);
65 strb
->surface
= pipe
->create_surface(pipe
, strb
->texture
, &surf_tmpl
);
68 pipe_resource_reference(&strb
->texture
, NULL
);
72 strb
->width
= pt
->width0
;
73 strb
->height
= pt
->height0
;
79 * Flush the front buffer if the current context renders to the front buffer.
82 vg_manager_flush_frontbuffer(struct vg_context
*ctx
)
84 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
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
);
100 * Re-validate the framebuffer.
103 vg_manager_validate_framebuffer(struct vg_context
*ctx
)
105 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
106 struct pipe_resource
*pt
;
109 /* no binding surface */
113 new_stamp
= p_atomic_read(&stfb
->iface
->stamp
);
114 if (stfb
->iface_stamp
!= new_stamp
) {
116 /* validate the fb */
117 if (!stfb
->iface
->validate(stfb
->iface
, &stfb
->strb_att
,
121 stfb
->iface_stamp
= new_stamp
;
122 new_stamp
= p_atomic_read(&stfb
->iface
->stamp
);
124 } while (stfb
->iface_stamp
!= new_stamp
);
126 if (vg_context_update_color_rb(ctx
, pt
) ||
127 stfb
->width
!= pt
->width0
||
128 stfb
->height
!= pt
->height0
)
131 stfb
->width
= pt
->width0
;
132 stfb
->height
= pt
->height0
;
135 if (ctx
->draw_stamp
!= stfb
->stamp
) {
136 ctx
->state
.dirty
|= FRAMEBUFFER_DIRTY
;
137 ctx
->draw_stamp
= stfb
->stamp
;
142 vg_context_flush(struct st_context_iface
*stctxi
, unsigned flags
,
143 struct pipe_fence_handle
**fence
)
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
);
152 vg_context_destroy(struct st_context_iface
*stctxi
)
154 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
155 struct pipe_context
*pipe
= ctx
->pipe
;
157 vg_destroy_context(ctx
);
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
)
167 struct vg_context
*shared_ctx
= (struct vg_context
*) shared_stctxi
;
168 struct vg_context
*ctx
;
169 struct pipe_context
*pipe
;
171 if (!(stapi
->profile_mask
& (1 << attribs
->profile
))) {
172 *error
= ST_CONTEXT_ERROR_BAD_API
;
176 /* only 1.0 is supported */
177 if (attribs
->major
> 1 || (attribs
->major
== 1 && attribs
->minor
> 0)) {
178 *error
= ST_CONTEXT_ERROR_BAD_VERSION
;
182 /* for VGHandle / pointer lookups */
185 pipe
= smapi
->screen
->context_create(smapi
->screen
, NULL
);
187 *error
= ST_CONTEXT_ERROR_NO_MEMORY
;
190 ctx
= vg_create_context(pipe
, NULL
, shared_ctx
);
193 *error
= ST_CONTEXT_ERROR_NO_MEMORY
;
197 ctx
->iface
.destroy
= vg_context_destroy
;
199 ctx
->iface
.flush
= vg_context_flush
;
201 ctx
->iface
.teximage
= NULL
;
202 ctx
->iface
.copy
= NULL
;
204 ctx
->iface
.st_context_private
= (void *) smapi
;
209 static struct st_renderbuffer
*
210 create_renderbuffer(enum pipe_format format
)
212 struct st_renderbuffer
*strb
;
214 strb
= CALLOC_STRUCT(st_renderbuffer
);
216 strb
->format
= format
;
222 destroy_renderbuffer(struct st_renderbuffer
*strb
)
224 pipe_surface_reference(&strb
->surface
, NULL
);
225 pipe_resource_reference(&strb
->texture
, NULL
);
230 * Decide the buffer to render to.
232 static enum st_attachment_type
233 choose_attachment(struct st_framebuffer_iface
*stfbi
)
235 enum st_attachment_type statt
;
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
)) {
242 case ST_ATTACHMENT_BACK_LEFT
:
243 statt
= ST_ATTACHMENT_FRONT_LEFT
;
245 case ST_ATTACHMENT_BACK_RIGHT
:
246 statt
= ST_ATTACHMENT_FRONT_RIGHT
;
252 if (!st_visual_have_buffers(stfbi
->visual
, 1 << statt
))
253 statt
= ST_ATTACHMENT_INVALID
;
261 * Bind the context to the given framebuffers.
264 vg_context_bind_framebuffers(struct st_context_iface
*stctxi
,
265 struct st_framebuffer_iface
*stdrawi
,
266 struct st_framebuffer_iface
*streadi
)
268 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
269 struct st_framebuffer
*stfb
;
270 enum st_attachment_type strb_att
;
272 /* the draw and read framebuffers must be the same */
273 if (stdrawi
!= streadi
)
276 strb_att
= (stdrawi
) ? choose_attachment(stdrawi
) : ST_ATTACHMENT_INVALID
;
278 if (ctx
->draw_buffer
) {
279 stfb
= ctx
->draw_buffer
;
281 /* free the existing fb */
283 stfb
->strb_att
!= strb_att
||
284 stfb
->strb
->format
!= stdrawi
->visual
->color_format
) {
285 destroy_renderbuffer(stfb
->strb
);
286 destroy_renderbuffer(stfb
->dsrb
);
289 ctx
->draw_buffer
= NULL
;
296 if (strb_att
== ST_ATTACHMENT_INVALID
)
299 /* create a new fb */
300 if (!ctx
->draw_buffer
) {
301 stfb
= CALLOC_STRUCT(st_framebuffer
);
305 stfb
->strb
= create_renderbuffer(stdrawi
->visual
->color_format
);
311 stfb
->dsrb
= create_renderbuffer(ctx
->ds_format
);
320 stfb
->strb_att
= strb_att
;
322 stfb
->iface_stamp
= p_atomic_read(&stdrawi
->stamp
) - 1;
324 ctx
->draw_buffer
= stfb
;
327 ctx
->draw_buffer
->iface
= stdrawi
;
328 ctx
->draw_stamp
= ctx
->draw_buffer
->stamp
- 1;
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
)
338 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
341 vg_context_bind_framebuffers(stctxi
, stdrawi
, streadi
);
342 vg_set_current_context(ctx
);
347 static struct st_context_iface
*
348 vg_api_get_current(struct st_api
*stapi
)
350 struct vg_context
*ctx
= vg_current_context();
352 return (ctx
) ? &ctx
->iface
: NULL
;
356 vg_api_get_proc_address(struct st_api
*stapi
, const char *procname
)
358 return api_get_proc_address(procname
);
362 vg_api_destroy(struct st_api
*stapi
)
366 static const struct st_api vg_api
= {
367 "Vega " VEGA_VERSION_STRING
,
369 ST_PROFILE_DEFAULT_MASK
,
372 vg_api_get_proc_address
,
373 vg_api_create_context
,
378 const struct st_api
*