xm_st.c revision 66cd38f465499863de106e1ae83b5de85072c29b
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 31#include "xm_api.h" 32#include "xm_st.h" 33 34struct xmesa_st_framebuffer { 35 struct pipe_screen *screen; 36 XMesaBuffer buffer; 37 38 struct st_visual stvis; 39 40 unsigned texture_width, texture_height, texture_mask; 41 struct pipe_texture *textures[ST_ATTACHMENT_COUNT]; 42 43 struct pipe_surface *display_surface; 44}; 45 46static INLINE struct xmesa_st_framebuffer * 47xmesa_st_framebuffer(struct st_framebuffer_iface *stfbi) 48{ 49 return (struct xmesa_st_framebuffer *) stfbi->st_manager_private; 50} 51 52/** 53 * Display an attachment to the xlib_drawable of the framebuffer. 54 */ 55static boolean 56xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi, 57 enum st_attachment_type statt) 58{ 59 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 60 struct pipe_texture *ptex = xstfb->textures[statt]; 61 struct pipe_surface *psurf; 62 63 if (!ptex) 64 return TRUE; 65 66 psurf = xstfb->display_surface; 67 /* (re)allocate the surface for the texture to be displayed */ 68 if (!psurf || psurf->texture != ptex) { 69 pipe_surface_reference(&xstfb->display_surface, NULL); 70 71 psurf = xstfb->screen->get_tex_surface(xstfb->screen, 72 ptex, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ); 73 if (!psurf) 74 return FALSE; 75 76 xstfb->display_surface = psurf; 77 } 78 79 xstfb->screen->flush_frontbuffer(xstfb->screen, psurf, &xstfb->buffer->ws); 80 81 return TRUE; 82} 83 84/** 85 * Remove outdated textures and create the requested ones. 86 */ 87static void 88xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, 89 unsigned width, unsigned height, 90 unsigned mask) 91{ 92 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 93 struct pipe_texture templ; 94 unsigned i; 95 96 /* remove outdated textures */ 97 if (xstfb->texture_width != width || xstfb->texture_height != height) { 98 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) 99 pipe_texture_reference(&xstfb->textures[i], NULL); 100 } 101 102 memset(&templ, 0, sizeof(templ)); 103 templ.target = PIPE_TEXTURE_2D; 104 templ.width0 = width; 105 templ.height0 = height; 106 templ.depth0 = 1; 107 templ.last_level = 0; 108 109 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 110 enum pipe_format format; 111 unsigned tex_usage; 112 113 /* the texture already exists or not requested */ 114 if (xstfb->textures[i] || !(mask & (1 << i))) { 115 /* remember the texture */ 116 if (xstfb->textures[i]) 117 mask |= (1 << i); 118 continue; 119 } 120 121 switch (i) { 122 case ST_ATTACHMENT_FRONT_LEFT: 123 case ST_ATTACHMENT_BACK_LEFT: 124 case ST_ATTACHMENT_FRONT_RIGHT: 125 case ST_ATTACHMENT_BACK_RIGHT: 126 format = xstfb->stvis.color_format; 127 tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET | 128 PIPE_TEXTURE_USAGE_RENDER_TARGET; 129 break; 130 case ST_ATTACHMENT_DEPTH_STENCIL: 131 format = xstfb->stvis.depth_stencil_format; 132 tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; 133 break; 134 default: 135 format = PIPE_FORMAT_NONE; 136 break; 137 } 138 139 if (format != PIPE_FORMAT_NONE) { 140 templ.format = format; 141 templ.tex_usage = tex_usage; 142 143 xstfb->textures[i] = 144 xstfb->screen->texture_create(xstfb->screen, &templ); 145 } 146 } 147 148 xstfb->texture_width = width; 149 xstfb->texture_height = height; 150 xstfb->texture_mask = mask; 151} 152 153static boolean 154xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, 155 const enum st_attachment_type *statts, 156 unsigned count, 157 struct pipe_texture **out) 158{ 159 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 160 unsigned statt_mask, i; 161 162 statt_mask = 0x0; 163 for (i = 0; i < count; i++) 164 statt_mask |= 1 << statts[i]; 165 166 /* revalidate textures */ 167 if (xstfb->buffer->width != xstfb->texture_width || 168 xstfb->buffer->height != xstfb->texture_height || 169 (xstfb->texture_mask & statt_mask) != statt_mask) { 170 xmesa_st_framebuffer_validate_textures(stfbi, 171 xstfb->buffer->width, xstfb->buffer->height, statt_mask); 172 } 173 174 for (i = 0; i < count; i++) { 175 out[i] = NULL; 176 pipe_texture_reference(&out[i], xstfb->textures[statts[i]]); 177 } 178 179 return TRUE; 180} 181 182static boolean 183xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, 184 enum st_attachment_type statt) 185{ 186 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 187 boolean ret; 188 189 ret = xmesa_st_framebuffer_display(stfbi, statt); 190 if (ret) 191 xmesa_check_buffer_size(xstfb->buffer); 192 193 return ret; 194} 195 196struct st_framebuffer_iface * 197xmesa_create_st_framebuffer(struct pipe_screen *screen, XMesaBuffer b) 198{ 199 struct st_framebuffer_iface *stfbi; 200 struct xmesa_st_framebuffer *xstfb; 201 202 stfbi = CALLOC_STRUCT(st_framebuffer_iface); 203 xstfb = CALLOC_STRUCT(xmesa_st_framebuffer); 204 if (!stfbi || !xstfb) { 205 if (stfbi) 206 FREE(stfbi); 207 if (xstfb) 208 FREE(xstfb); 209 return NULL; 210 } 211 212 xstfb->screen = screen; 213 xstfb->buffer = b; 214 xstfb->stvis = b->xm_visual->stvis; 215 216 stfbi->visual = &xstfb->stvis; 217 stfbi->flush_front = xmesa_st_framebuffer_flush_front; 218 stfbi->validate = xmesa_st_framebuffer_validate; 219 stfbi->st_manager_private = (void *) xstfb; 220 221 return stfbi; 222} 223 224void 225xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) 226{ 227 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 228 int i; 229 230 pipe_surface_reference(&xstfb->display_surface, NULL); 231 232 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) 233 pipe_texture_reference(&xstfb->textures[i], NULL); 234 235 FREE(xstfb); 236 FREE(stfbi); 237} 238 239void 240xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi) 241{ 242 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 243 boolean ret; 244 245 ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT); 246 if (ret) { 247 struct pipe_texture **front, **back, *tmp; 248 249 front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT]; 250 back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT]; 251 /* swap textures only if the front texture has been allocated */ 252 if (*front) { 253 tmp = *front; 254 *front = *back; 255 *back = tmp; 256 } 257 258 xmesa_check_buffer_size(xstfb->buffer); 259 } 260} 261 262void 263xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, 264 enum st_attachment_type src, 265 enum st_attachment_type dst, 266 int x, int y, int w, int h) 267{ 268 /* TODO */ 269} 270