2 * Mesa 3-D graphics library
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
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 * Chia-I Wu <olv@lunarg.com>
28 #include "util/u_memory.h"
29 #include "util/u_inlines.h"
30 #include "state_tracker/st_gl_api.h" /* for st_gl_api_create */
33 #include "stw_device.h"
34 #include "stw_framebuffer.h"
35 #include "stw_pixelformat.h"
37 struct stw_st_framebuffer
{
38 struct st_framebuffer_iface base
;
40 struct stw_framebuffer
*fb
;
41 struct st_visual stvis
;
43 struct pipe_resource
*textures
[ST_ATTACHMENT_COUNT
];
44 unsigned texture_width
, texture_height
;
45 unsigned texture_mask
;
47 struct pipe_surface
*front_surface
, *back_surface
;
50 static INLINE
struct stw_st_framebuffer
*
51 stw_st_framebuffer(struct st_framebuffer_iface
*stfb
)
53 return (struct stw_st_framebuffer
*) stfb
;
57 * Remove outdated textures and create the requested ones.
60 stw_st_framebuffer_validate_locked(struct st_framebuffer_iface
*stfb
,
61 unsigned width
, unsigned height
,
64 struct stw_st_framebuffer
*stwfb
= stw_st_framebuffer(stfb
);
65 struct pipe_resource templ
;
68 /* remove outdated surface */
69 pipe_surface_reference(&stwfb
->front_surface
, NULL
);
70 pipe_surface_reference(&stwfb
->back_surface
, NULL
);
72 /* remove outdated textures */
73 if (stwfb
->texture_width
!= width
|| stwfb
->texture_height
!= height
) {
74 for (i
= 0; i
< ST_ATTACHMENT_COUNT
; i
++)
75 pipe_resource_reference(&stwfb
->textures
[i
], NULL
);
78 memset(&templ
, 0, sizeof(templ
));
79 templ
.target
= PIPE_TEXTURE_2D
;
81 templ
.height0
= height
;
85 for (i
= 0; i
< ST_ATTACHMENT_COUNT
; i
++) {
86 enum pipe_format format
;
89 /* the texture already exists or not requested */
90 if (stwfb
->textures
[i
] || !(mask
& (1 << i
))) {
91 /* remember the texture */
92 if (stwfb
->textures
[i
])
98 case ST_ATTACHMENT_FRONT_LEFT
:
99 case ST_ATTACHMENT_BACK_LEFT
:
100 format
= stwfb
->stvis
.color_format
;
101 bind
= PIPE_BIND_DISPLAY_TARGET
|
102 PIPE_BIND_RENDER_TARGET
;
104 case ST_ATTACHMENT_DEPTH_STENCIL
:
105 format
= stwfb
->stvis
.depth_stencil_format
;
106 bind
= PIPE_BIND_DEPTH_STENCIL
;
109 format
= PIPE_FORMAT_NONE
;
113 if (format
!= PIPE_FORMAT_NONE
) {
114 templ
.format
= format
;
118 stw_dev
->screen
->resource_create(stw_dev
->screen
, &templ
);
122 stwfb
->texture_width
= width
;
123 stwfb
->texture_height
= height
;
124 stwfb
->texture_mask
= mask
;
128 stw_st_framebuffer_validate(struct st_framebuffer_iface
*stfb
,
129 const enum st_attachment_type
*statts
,
131 struct pipe_resource
**out
)
133 struct stw_st_framebuffer
*stwfb
= stw_st_framebuffer(stfb
);
134 unsigned statt_mask
, i
;
137 for (i
= 0; i
< count
; i
++)
138 statt_mask
|= 1 << statts
[i
];
140 pipe_mutex_lock(stwfb
->fb
->mutex
);
142 if (stwfb
->fb
->must_resize
|| (statt_mask
& ~stwfb
->texture_mask
)) {
143 stw_st_framebuffer_validate_locked(&stwfb
->base
,
144 stwfb
->fb
->width
, stwfb
->fb
->height
, statt_mask
);
145 stwfb
->fb
->must_resize
= FALSE
;
148 for (i
= 0; i
< count
; i
++) {
150 pipe_resource_reference(&out
[i
], stwfb
->textures
[statts
[i
]]);
153 stw_framebuffer_release(stwfb
->fb
);
158 static struct pipe_surface
*
159 get_present_surface_locked(struct st_framebuffer_iface
*stfb
,
160 enum st_attachment_type statt
)
162 struct stw_st_framebuffer
*stwfb
= stw_st_framebuffer(stfb
);
163 struct pipe_resource
*ptex
;
164 struct pipe_surface
*psurf
, **cache
;
166 ptex
= stwfb
->textures
[statt
];
173 case ST_ATTACHMENT_FRONT_LEFT
:
174 cache
= &stwfb
->front_surface
;
176 case ST_ATTACHMENT_BACK_LEFT
:
177 cache
= &stwfb
->back_surface
;
185 *cache
= stw_dev
->screen
->get_tex_surface(stw_dev
->screen
,
187 PIPE_BIND_DISPLAY_TARGET
|
188 PIPE_BIND_RENDER_TARGET
);
192 pipe_surface_reference(&psurf
, *cache
);
198 * Present an attachment of the framebuffer.
201 stw_st_framebuffer_present_locked(struct st_framebuffer_iface
*stfb
,
202 enum st_attachment_type statt
)
204 struct stw_st_framebuffer
*stwfb
= stw_st_framebuffer(stfb
);
205 struct pipe_surface
*psurf
;
207 psurf
= get_present_surface_locked(&stwfb
->base
, statt
);
209 stw_framebuffer_present_locked(stwfb
->fb
->hDC
, stwfb
->fb
, psurf
);
210 pipe_surface_reference(&psurf
, NULL
);
217 stw_st_framebuffer_flush_front(struct st_framebuffer_iface
*stfb
,
218 enum st_attachment_type statt
)
220 struct stw_st_framebuffer
*stwfb
= stw_st_framebuffer(stfb
);
222 pipe_mutex_lock(stwfb
->fb
->mutex
);
224 return stw_st_framebuffer_present_locked(&stwfb
->base
, statt
);
228 * Create a framebuffer interface.
230 struct st_framebuffer_iface
*
231 stw_st_create_framebuffer(struct stw_framebuffer
*fb
)
233 struct stw_st_framebuffer
*stwfb
;
235 stwfb
= CALLOC_STRUCT(stw_st_framebuffer
);
240 stwfb
->stvis
= fb
->pfi
->stvis
;
242 stwfb
->base
.visual
= &stwfb
->stvis
;
243 stwfb
->base
.flush_front
= stw_st_framebuffer_flush_front
;
244 stwfb
->base
.validate
= stw_st_framebuffer_validate
;
250 * Destroy a framebuffer interface.
253 stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface
*stfb
)
255 struct stw_st_framebuffer
*stwfb
= stw_st_framebuffer(stfb
);
258 pipe_surface_reference(&stwfb
->front_surface
, NULL
);
259 pipe_surface_reference(&stwfb
->back_surface
, NULL
);
261 for (i
= 0; i
< ST_ATTACHMENT_COUNT
; i
++)
262 pipe_resource_reference(&stwfb
->textures
[i
], NULL
);
268 * Swap the buffers of the given framebuffer.
271 stw_st_swap_framebuffer_locked(struct st_framebuffer_iface
*stfb
)
273 struct stw_st_framebuffer
*stwfb
= stw_st_framebuffer(stfb
);
274 unsigned front
= ST_ATTACHMENT_FRONT_LEFT
, back
= ST_ATTACHMENT_BACK_LEFT
;
275 struct pipe_resource
*ptex
;
276 struct pipe_surface
*psurf
;
279 /* swap the textures */
280 ptex
= stwfb
->textures
[front
];
281 stwfb
->textures
[front
] = stwfb
->textures
[back
];
282 stwfb
->textures
[back
] = ptex
;
284 /* swap the surfaces */
285 psurf
= stwfb
->front_surface
;
286 stwfb
->front_surface
= stwfb
->back_surface
;
287 stwfb
->back_surface
= psurf
;
289 /* convert to mask */
293 /* swap the bits in mask */
294 mask
= stwfb
->texture_mask
& ~(front
| back
);
295 if (stwfb
->texture_mask
& front
)
297 if (stwfb
->texture_mask
& back
)
299 stwfb
->texture_mask
= mask
;
301 front
= ST_ATTACHMENT_FRONT_LEFT
;
302 return stw_st_framebuffer_present_locked(&stwfb
->base
, front
);
306 * Create an st_api of the state tracker.
309 stw_st_create_api(void)
311 return st_gl_api_create();