stw_st.c revision 0bddb58d2f8dc07500d0b063608d995628dbe363
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.9 4 * 5 * Copyright (C) 2010 LunarG Inc. 6 * 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: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 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. 23 * 24 * Authors: 25 * Chia-I Wu <olv@lunarg.com> 26 */ 27 28#include "util/u_memory.h" 29#include "util/u_inlines.h" 30#include "state_tracker/st_manager.h" /* for st_manager_create_api */ 31 32#include "stw_st.h" 33#include "stw_device.h" 34#include "stw_framebuffer.h" 35#include "stw_pixelformat.h" 36 37struct stw_st_framebuffer { 38 struct st_framebuffer_iface base; 39 40 struct stw_framebuffer *fb; 41 struct st_visual stvis; 42 43 struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; 44 unsigned texture_width, texture_height; 45 unsigned texture_mask; 46 47 struct pipe_surface *front_surface, *back_surface; 48}; 49 50static INLINE struct stw_st_framebuffer * 51stw_st_framebuffer(struct st_framebuffer_iface *stfb) 52{ 53 return (struct stw_st_framebuffer *) stfb; 54} 55 56/** 57 * Remove outdated textures and create the requested ones. 58 */ 59static void 60stw_st_framebuffer_validate_locked(struct st_framebuffer_iface *stfb, 61 unsigned width, unsigned height, 62 unsigned mask) 63{ 64 struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 65 struct pipe_resource templ; 66 unsigned i; 67 68 /* remove outdated surface */ 69 pipe_surface_reference(&stwfb->front_surface, NULL); 70 pipe_surface_reference(&stwfb->back_surface, NULL); 71 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); 76 } 77 78 memset(&templ, 0, sizeof(templ)); 79 templ.target = PIPE_TEXTURE_2D; 80 templ.width0 = width; 81 templ.height0 = height; 82 templ.depth0 = 1; 83 templ.last_level = 0; 84 85 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 86 enum pipe_format format; 87 unsigned bind; 88 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]) 93 mask |= (1 << i); 94 continue; 95 } 96 97 switch (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; 103 break; 104 case ST_ATTACHMENT_DEPTH_STENCIL: 105 format = stwfb->stvis.depth_stencil_format; 106 bind = PIPE_BIND_DEPTH_STENCIL; 107 break; 108 default: 109 format = PIPE_FORMAT_NONE; 110 break; 111 } 112 113 if (format != PIPE_FORMAT_NONE) { 114 templ.format = format; 115 templ.bind = bind; 116 117 stwfb->textures[i] = 118 stw_dev->screen->resource_create(stw_dev->screen, &templ); 119 } 120 } 121 122 stwfb->texture_width = width; 123 stwfb->texture_height = height; 124 stwfb->texture_mask = mask; 125} 126 127static boolean 128stw_st_framebuffer_validate(struct st_framebuffer_iface *stfb, 129 const enum st_attachment_type *statts, 130 unsigned count, 131 struct pipe_resource **out) 132{ 133 struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 134 unsigned statt_mask, i; 135 136 statt_mask = 0x0; 137 for (i = 0; i < count; i++) 138 statt_mask |= 1 << statts[i]; 139 140 pipe_mutex_lock(stwfb->fb->mutex); 141 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; 146 } 147 148 for (i = 0; i < count; i++) { 149 out[i] = NULL; 150 pipe_resource_reference(&out[i], stwfb->textures[statts[i]]); 151 } 152 153 stw_framebuffer_release(stwfb->fb); 154 155 return TRUE; 156} 157 158static struct pipe_surface * 159get_present_surface_locked(struct st_framebuffer_iface *stfb, 160 enum st_attachment_type statt) 161{ 162 struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 163 struct pipe_resource *ptex; 164 struct pipe_surface *psurf, **cache; 165 166 ptex = stwfb->textures[statt]; 167 if (!ptex) 168 return NULL; 169 170 psurf = NULL; 171 172 switch (statt) { 173 case ST_ATTACHMENT_FRONT_LEFT: 174 cache = &stwfb->front_surface; 175 break; 176 case ST_ATTACHMENT_BACK_LEFT: 177 cache = &stwfb->back_surface; 178 break; 179 default: 180 cache = &psurf; 181 break; 182 } 183 184 if (!*cache) { 185 *cache = stw_dev->screen->get_tex_surface(stw_dev->screen, 186 ptex, 0, 0, 0, 187 PIPE_BIND_DISPLAY_TARGET | 188 PIPE_BIND_RENDER_TARGET); 189 } 190 191 if (psurf != *cache) 192 pipe_surface_reference(&psurf, *cache); 193 194 return psurf; 195} 196 197/** 198 * Present an attachment of the framebuffer. 199 */ 200static boolean 201stw_st_framebuffer_present_locked(struct st_framebuffer_iface *stfb, 202 enum st_attachment_type statt) 203{ 204 struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 205 struct pipe_surface *psurf; 206 207 psurf = get_present_surface_locked(&stwfb->base, statt); 208 if (psurf) { 209 stw_framebuffer_present_locked(stwfb->fb->hDC, stwfb->fb, psurf); 210 pipe_surface_reference(&psurf, NULL); 211 } 212 213 return TRUE; 214} 215 216static boolean 217stw_st_framebuffer_flush_front(struct st_framebuffer_iface *stfb, 218 enum st_attachment_type statt) 219{ 220 struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 221 222 pipe_mutex_lock(stwfb->fb->mutex); 223 224 return stw_st_framebuffer_present_locked(&stwfb->base, statt); 225} 226 227/** 228 * Create a framebuffer interface. 229 */ 230struct st_framebuffer_iface * 231stw_st_create_framebuffer(struct stw_framebuffer *fb) 232{ 233 struct stw_st_framebuffer *stwfb; 234 235 stwfb = CALLOC_STRUCT(stw_st_framebuffer); 236 if (!stwfb) 237 return NULL; 238 239 stwfb->fb = fb; 240 stwfb->stvis = fb->pfi->stvis; 241 242 stwfb->base.visual = &stwfb->stvis; 243 stwfb->base.flush_front = stw_st_framebuffer_flush_front; 244 stwfb->base.validate = stw_st_framebuffer_validate; 245 246 return &stwfb->base; 247} 248 249/** 250 * Destroy a framebuffer interface. 251 */ 252void 253stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb) 254{ 255 struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 256 int i; 257 258 pipe_surface_reference(&stwfb->front_surface, NULL); 259 pipe_surface_reference(&stwfb->back_surface, NULL); 260 261 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) 262 pipe_resource_reference(&stwfb->textures[i], NULL); 263 264 FREE(stwfb); 265} 266 267/** 268 * Swap the buffers of the given framebuffer. 269 */ 270boolean 271stw_st_swap_framebuffer_locked(struct st_framebuffer_iface *stfb) 272{ 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; 277 unsigned mask; 278 279 /* swap the textures */ 280 ptex = stwfb->textures[front]; 281 stwfb->textures[front] = stwfb->textures[back]; 282 stwfb->textures[back] = ptex; 283 284 /* swap the surfaces */ 285 psurf = stwfb->front_surface; 286 stwfb->front_surface = stwfb->back_surface; 287 stwfb->back_surface = psurf; 288 289 /* convert to mask */ 290 front = 1 << front; 291 back = 1 << back; 292 293 /* swap the bits in mask */ 294 mask = stwfb->texture_mask & ~(front | back); 295 if (stwfb->texture_mask & front) 296 mask |= back; 297 if (stwfb->texture_mask & back) 298 mask |= front; 299 stwfb->texture_mask = mask; 300 301 front = ST_ATTACHMENT_FRONT_LEFT; 302 return stw_st_framebuffer_present_locked(&stwfb->base, front); 303} 304 305/** 306 * Create an st_api of the state tracker. 307 */ 308struct st_api * 309stw_st_create_api(void) 310{ 311 return st_manager_create_api(); 312} 313