2 * Mesa 3-D graphics library
4 * Copyright 2009 VMware, Inc. All Rights Reserved.
5 * Copyright (C) 2010 LunarG Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
26 * Chia-I Wu <olv@lunarg.com>
29 #include "state_tracker/st_api.h"
31 #include "pipe/p_context.h"
32 #include "pipe/p_screen.h"
33 #include "util/u_memory.h"
34 #include "util/u_inlines.h"
35 #include "util/u_box.h"
36 #include "util/u_surface.h"
39 #include "vg_manager.h"
40 #include "vg_context.h"
45 vg_context_update_color_rb(struct vg_context
*ctx
, struct pipe_resource
*pt
)
47 struct st_renderbuffer
*strb
= ctx
->draw_buffer
->strb
;
48 struct pipe_context
*pipe
= ctx
->pipe
;
49 struct pipe_surface surf_tmpl
;
51 if (strb
->texture
== pt
) {
52 pipe_resource_reference(&pt
, NULL
);
56 /* unreference existing ones */
57 pipe_surface_reference(&strb
->surface
, NULL
);
58 pipe_resource_reference(&strb
->texture
, NULL
);
59 strb
->width
= strb
->height
= 0;
63 u_surface_default_template(&surf_tmpl
, strb
->texture
);
64 strb
->surface
= pipe
->create_surface(pipe
, strb
->texture
, &surf_tmpl
);
67 pipe_resource_reference(&strb
->texture
, NULL
);
71 strb
->width
= pt
->width0
;
72 strb
->height
= pt
->height0
;
78 * Flush the front buffer if the current context renders to the front buffer.
81 vg_manager_flush_frontbuffer(struct vg_context
*ctx
)
83 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
88 switch (stfb
->strb_att
) {
89 case ST_ATTACHMENT_FRONT_LEFT
:
90 case ST_ATTACHMENT_FRONT_RIGHT
:
91 stfb
->iface
->flush_front(&ctx
->iface
, stfb
->iface
, stfb
->strb_att
);
99 * Re-validate the framebuffer.
102 vg_manager_validate_framebuffer(struct vg_context
*ctx
)
104 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
105 struct pipe_resource
*pt
;
108 /* no binding surface */
112 new_stamp
= p_atomic_read(&stfb
->iface
->stamp
);
113 if (stfb
->iface_stamp
!= new_stamp
) {
115 /* validate the fb */
116 if (!stfb
->iface
->validate((struct st_context_iface
*)ctx
,
117 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 unsigned pipe_flags
= 0;
148 if (flags
& ST_FLUSH_END_OF_FRAME
) {
149 pipe_flags
|= PIPE_FLUSH_END_OF_FRAME
;
152 ctx
->pipe
->flush(ctx
->pipe
, fence
, pipe_flags
);
153 if (flags
& ST_FLUSH_FRONT
)
154 vg_manager_flush_frontbuffer(ctx
);
158 vg_context_destroy(struct st_context_iface
*stctxi
)
160 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
161 struct pipe_context
*pipe
= ctx
->pipe
;
163 vg_destroy_context(ctx
);
167 static struct st_context_iface
*
168 vg_api_create_context(struct st_api
*stapi
, struct st_manager
*smapi
,
169 const struct st_context_attribs
*attribs
,
170 enum st_context_error
*error
,
171 struct st_context_iface
*shared_stctxi
)
173 struct vg_context
*shared_ctx
= (struct vg_context
*) shared_stctxi
;
174 struct vg_context
*ctx
;
175 struct pipe_context
*pipe
;
177 if (!(stapi
->profile_mask
& (1 << attribs
->profile
))) {
178 *error
= ST_CONTEXT_ERROR_BAD_API
;
182 /* only 1.0 is supported */
183 if (attribs
->major
> 1 || (attribs
->major
== 1 && attribs
->minor
> 0)) {
184 *error
= ST_CONTEXT_ERROR_BAD_VERSION
;
188 /* for VGHandle / pointer lookups */
191 pipe
= smapi
->screen
->context_create(smapi
->screen
, NULL
);
193 *error
= ST_CONTEXT_ERROR_NO_MEMORY
;
196 ctx
= vg_create_context(pipe
, NULL
, shared_ctx
);
199 *error
= ST_CONTEXT_ERROR_NO_MEMORY
;
203 ctx
->iface
.destroy
= vg_context_destroy
;
205 ctx
->iface
.flush
= vg_context_flush
;
207 ctx
->iface
.teximage
= NULL
;
208 ctx
->iface
.copy
= NULL
;
210 ctx
->iface
.st_context_private
= (void *) smapi
;
215 static struct st_renderbuffer
*
216 create_renderbuffer(enum pipe_format format
)
218 struct st_renderbuffer
*strb
;
220 strb
= CALLOC_STRUCT(st_renderbuffer
);
222 strb
->format
= format
;
228 destroy_renderbuffer(struct st_renderbuffer
*strb
)
230 pipe_surface_reference(&strb
->surface
, NULL
);
231 pipe_resource_reference(&strb
->texture
, NULL
);
236 * Decide the buffer to render to.
238 static enum st_attachment_type
239 choose_attachment(struct st_framebuffer_iface
*stfbi
)
241 enum st_attachment_type statt
;
243 statt
= stfbi
->visual
->render_buffer
;
244 if (statt
!= ST_ATTACHMENT_INVALID
) {
245 /* use the buffer given by the visual, unless it is unavailable */
246 if (!st_visual_have_buffers(stfbi
->visual
, 1 << statt
)) {
248 case ST_ATTACHMENT_BACK_LEFT
:
249 statt
= ST_ATTACHMENT_FRONT_LEFT
;
251 case ST_ATTACHMENT_BACK_RIGHT
:
252 statt
= ST_ATTACHMENT_FRONT_RIGHT
;
258 if (!st_visual_have_buffers(stfbi
->visual
, 1 << statt
))
259 statt
= ST_ATTACHMENT_INVALID
;
267 * Bind the context to the given framebuffers.
270 vg_context_bind_framebuffers(struct st_context_iface
*stctxi
,
271 struct st_framebuffer_iface
*stdrawi
,
272 struct st_framebuffer_iface
*streadi
)
274 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
275 struct st_framebuffer
*stfb
;
276 enum st_attachment_type strb_att
;
278 /* the draw and read framebuffers must be the same */
279 if (stdrawi
!= streadi
)
282 strb_att
= (stdrawi
) ? choose_attachment(stdrawi
) : ST_ATTACHMENT_INVALID
;
284 if (ctx
->draw_buffer
) {
285 stfb
= ctx
->draw_buffer
;
287 /* free the existing fb */
289 stfb
->strb_att
!= strb_att
||
290 stfb
->strb
->format
!= stdrawi
->visual
->color_format
) {
291 destroy_renderbuffer(stfb
->strb
);
292 destroy_renderbuffer(stfb
->dsrb
);
295 ctx
->draw_buffer
= NULL
;
302 if (strb_att
== ST_ATTACHMENT_INVALID
)
305 /* create a new fb */
306 if (!ctx
->draw_buffer
) {
307 stfb
= CALLOC_STRUCT(st_framebuffer
);
311 stfb
->strb
= create_renderbuffer(stdrawi
->visual
->color_format
);
317 stfb
->dsrb
= create_renderbuffer(ctx
->ds_format
);
326 stfb
->strb_att
= strb_att
;
328 stfb
->iface_stamp
= p_atomic_read(&stdrawi
->stamp
) - 1;
330 ctx
->draw_buffer
= stfb
;
333 ctx
->draw_buffer
->iface
= stdrawi
;
334 ctx
->draw_stamp
= ctx
->draw_buffer
->stamp
- 1;
340 vg_api_make_current(struct st_api
*stapi
, struct st_context_iface
*stctxi
,
341 struct st_framebuffer_iface
*stdrawi
,
342 struct st_framebuffer_iface
*streadi
)
344 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
347 vg_context_bind_framebuffers(stctxi
, stdrawi
, streadi
);
348 vg_set_current_context(ctx
);
353 static struct st_context_iface
*
354 vg_api_get_current(struct st_api
*stapi
)
356 struct vg_context
*ctx
= vg_current_context();
358 return (ctx
) ? &ctx
->iface
: NULL
;
362 vg_api_get_proc_address(struct st_api
*stapi
, const char *procname
)
364 return api_get_proc_address(procname
);
368 vg_api_destroy(struct st_api
*stapi
)
373 vg_api_query_versions(struct st_api
*stapi
, struct st_manager
*sm
,
374 struct st_config_options
*options
,
375 int *gl_core_version
,
376 int *gl_compat_version
,
382 static const struct st_api vg_api
= {
383 "Vega " PACKAGE_VERSION
,
385 ST_PROFILE_DEFAULT_MASK
,
388 vg_api_query_versions
,
389 vg_api_get_proc_address
,
390 vg_api_create_context
,
395 const struct st_api
*