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_sampler.h"
37 #include "util/u_box.h"
38 #include "util/u_surface.h"
41 #include "vg_manager.h"
42 #include "vg_context.h"
47 vg_context_update_color_rb(struct vg_context
*ctx
, struct pipe_resource
*pt
)
49 struct st_renderbuffer
*strb
= ctx
->draw_buffer
->strb
;
50 struct pipe_context
*pipe
= ctx
->pipe
;
51 struct pipe_surface surf_tmpl
;
53 if (strb
->texture
== pt
) {
54 pipe_resource_reference(&pt
, NULL
);
58 /* unreference existing ones */
59 pipe_surface_reference(&strb
->surface
, NULL
);
60 pipe_resource_reference(&strb
->texture
, NULL
);
61 strb
->width
= strb
->height
= 0;
65 memset(&surf_tmpl
, 0, sizeof(surf_tmpl
));
66 u_surface_default_template(&surf_tmpl
, strb
->texture
,
67 PIPE_BIND_RENDER_TARGET
);
68 strb
->surface
= pipe
->create_surface(pipe
, strb
->texture
, &surf_tmpl
);
71 pipe_resource_reference(&strb
->texture
, NULL
);
75 strb
->width
= pt
->width0
;
76 strb
->height
= pt
->height0
;
82 * Flush the front buffer if the current context renders to the front buffer.
85 vg_manager_flush_frontbuffer(struct vg_context
*ctx
)
87 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
92 switch (stfb
->strb_att
) {
93 case ST_ATTACHMENT_FRONT_LEFT
:
94 case ST_ATTACHMENT_FRONT_RIGHT
:
95 stfb
->iface
->flush_front(stfb
->iface
, stfb
->strb_att
);
103 * Re-validate the framebuffer.
106 vg_manager_validate_framebuffer(struct vg_context
*ctx
)
108 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
109 struct pipe_resource
*pt
;
111 /* no binding surface */
115 if (!p_atomic_read(&ctx
->draw_buffer_invalid
))
118 /* validate the fb */
119 if (!stfb
->iface
->validate(stfb
->iface
, &stfb
->strb_att
, 1, &pt
) || !pt
)
122 p_atomic_set(&ctx
->draw_buffer_invalid
, FALSE
);
124 if (vg_context_update_color_rb(ctx
, pt
) ||
125 stfb
->width
!= pt
->width0
||
126 stfb
->height
!= pt
->height0
)
127 ctx
->state
.dirty
|= FRAMEBUFFER_DIRTY
;
129 stfb
->width
= pt
->width0
;
130 stfb
->height
= pt
->height0
;
134 vg_context_notify_invalid_framebuffer(struct st_context_iface
*stctxi
,
135 struct st_framebuffer_iface
*stfbi
)
137 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
138 p_atomic_set(&ctx
->draw_buffer_invalid
, TRUE
);
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
, flags
, fence
);
147 if (flags
& PIPE_FLUSH_RENDER_CACHE
)
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 struct st_context_iface
*shared_stctxi
)
166 struct vg_context
*shared_ctx
= (struct vg_context
*) shared_stctxi
;
167 struct vg_context
*ctx
;
168 struct pipe_context
*pipe
;
170 if (!(stapi
->profile_mask
& (1 << attribs
->profile
)))
173 /* only 1.0 is supported */
174 if (attribs
->major
> 1 || (attribs
->major
== 1 && attribs
->minor
> 0))
177 pipe
= smapi
->screen
->context_create(smapi
->screen
, NULL
);
180 ctx
= vg_create_context(pipe
, NULL
, shared_ctx
);
186 ctx
->iface
.destroy
= vg_context_destroy
;
188 ctx
->iface
.notify_invalid_framebuffer
=
189 vg_context_notify_invalid_framebuffer
;
190 ctx
->iface
.flush
= vg_context_flush
;
192 ctx
->iface
.teximage
= NULL
;
193 ctx
->iface
.copy
= NULL
;
195 ctx
->iface
.st_context_private
= (void *) smapi
;
200 static struct st_renderbuffer
*
201 create_renderbuffer(enum pipe_format format
)
203 struct st_renderbuffer
*strb
;
205 strb
= CALLOC_STRUCT(st_renderbuffer
);
207 strb
->format
= format
;
213 destroy_renderbuffer(struct st_renderbuffer
*strb
)
215 pipe_surface_reference(&strb
->surface
, NULL
);
216 pipe_resource_reference(&strb
->texture
, NULL
);
221 * Decide the buffer to render to.
223 static enum st_attachment_type
224 choose_attachment(struct st_framebuffer_iface
*stfbi
)
226 enum st_attachment_type statt
;
228 statt
= stfbi
->visual
->render_buffer
;
229 if (statt
!= ST_ATTACHMENT_INVALID
) {
230 /* use the buffer given by the visual, unless it is unavailable */
231 if (!st_visual_have_buffers(stfbi
->visual
, 1 << statt
)) {
233 case ST_ATTACHMENT_BACK_LEFT
:
234 statt
= ST_ATTACHMENT_FRONT_LEFT
;
236 case ST_ATTACHMENT_BACK_RIGHT
:
237 statt
= ST_ATTACHMENT_FRONT_RIGHT
;
243 if (!st_visual_have_buffers(stfbi
->visual
, 1 << statt
))
244 statt
= ST_ATTACHMENT_INVALID
;
252 * Bind the context to the given framebuffers.
255 vg_context_bind_framebuffers(struct st_context_iface
*stctxi
,
256 struct st_framebuffer_iface
*stdrawi
,
257 struct st_framebuffer_iface
*streadi
)
259 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
260 struct st_framebuffer
*stfb
;
261 enum st_attachment_type strb_att
;
263 /* the draw and read framebuffers must be the same */
264 if (stdrawi
!= streadi
)
267 p_atomic_set(&ctx
->draw_buffer_invalid
, TRUE
);
269 strb_att
= (stdrawi
) ? choose_attachment(stdrawi
) : ST_ATTACHMENT_INVALID
;
271 if (ctx
->draw_buffer
) {
272 stfb
= ctx
->draw_buffer
;
274 /* free the existing fb */
276 stfb
->strb_att
!= strb_att
||
277 stfb
->strb
->format
!= stdrawi
->visual
->color_format
) {
278 destroy_renderbuffer(stfb
->strb
);
279 destroy_renderbuffer(stfb
->dsrb
);
282 ctx
->draw_buffer
= NULL
;
289 if (strb_att
== ST_ATTACHMENT_INVALID
)
292 /* create a new fb */
293 if (!ctx
->draw_buffer
) {
294 stfb
= CALLOC_STRUCT(st_framebuffer
);
298 stfb
->strb
= create_renderbuffer(stdrawi
->visual
->color_format
);
304 stfb
->dsrb
= create_renderbuffer(ctx
->ds_format
);
313 stfb
->strb_att
= strb_att
;
315 ctx
->draw_buffer
= stfb
;
318 ctx
->draw_buffer
->iface
= stdrawi
;
324 vg_api_make_current(struct st_api
*stapi
, struct st_context_iface
*stctxi
,
325 struct st_framebuffer_iface
*stdrawi
,
326 struct st_framebuffer_iface
*streadi
)
328 struct vg_context
*ctx
= (struct vg_context
*) stctxi
;
331 vg_context_bind_framebuffers(stctxi
, stdrawi
, streadi
);
332 vg_set_current_context(ctx
);
337 static struct st_context_iface
*
338 vg_api_get_current(struct st_api
*stapi
)
340 struct vg_context
*ctx
= vg_current_context();
342 return (ctx
) ? &ctx
->iface
: NULL
;
346 vg_api_get_proc_address(struct st_api
*stapi
, const char *procname
)
348 return api_get_proc_address(procname
);
352 vg_api_destroy(struct st_api
*stapi
)
356 static const struct st_api vg_api
= {
357 "Vega " VEGA_VERSION_STRING
,
359 ST_PROFILE_DEFAULT_MASK
,
361 vg_api_get_proc_address
,
362 vg_api_create_context
,
367 const struct st_api
*