xm_st.c revision 813c58d77e21cb59adb914b4b4ee26be758ff0ea
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; 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 const enum st_attachment_type *statts, 90 unsigned count) 91{ 92 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 93 struct pipe_texture templ; 94 unsigned request_mask, i; 95 96 request_mask = 0; 97 for (i = 0; i < count; i++) 98 request_mask |= 1 << statts[i]; 99 100 memset(&templ, 0, sizeof(templ)); 101 templ.target = PIPE_TEXTURE_2D; 102 templ.width0 = xstfb->texture_width; 103 templ.height0 = xstfb->texture_height; 104 templ.depth0 = 1; 105 templ.last_level = 0; 106 107 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 108 struct pipe_texture *ptex = xstfb->textures[i]; 109 enum pipe_format format; 110 unsigned tex_usage; 111 112 /* remove outdated textures */ 113 if (ptex && (ptex->width0 != xstfb->texture_width || 114 ptex->height0 != xstfb->texture_height)) { 115 pipe_texture_reference(&xstfb->textures[i], NULL); 116 ptex = NULL; 117 } 118 119 /* the texture already exists or not requested */ 120 if (ptex || !(request_mask & (1 << i))) 121 continue; 122 123 switch (i) { 124 case ST_ATTACHMENT_FRONT_LEFT: 125 case ST_ATTACHMENT_BACK_LEFT: 126 case ST_ATTACHMENT_FRONT_RIGHT: 127 case ST_ATTACHMENT_BACK_RIGHT: 128 format = xstfb->stvis.color_format; 129 tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET | 130 PIPE_TEXTURE_USAGE_RENDER_TARGET; 131 break; 132 case ST_ATTACHMENT_DEPTH_STENCIL: 133 format = xstfb->stvis.depth_stencil_format; 134 tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; 135 break; 136 default: 137 format = PIPE_FORMAT_NONE; 138 break; 139 } 140 141 if (format != PIPE_FORMAT_NONE) { 142 templ.format = format; 143 templ.tex_usage = tex_usage; 144 145 xstfb->textures[i] = 146 xstfb->screen->texture_create(xstfb->screen, &templ); 147 } 148 } 149} 150 151static boolean 152xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, 153 const enum st_attachment_type *statts, 154 unsigned count, 155 struct pipe_texture **out) 156{ 157 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 158 unsigned i; 159 160 /* revalidate textures */ 161 if (xstfb->buffer->width != xstfb->texture_width || 162 xstfb->buffer->height != xstfb->texture_height) { 163 xstfb->texture_width = xstfb->buffer->width; 164 xstfb->texture_height = xstfb->buffer->height; 165 166 xmesa_st_framebuffer_validate_textures(stfbi, statts, count); 167 } 168 169 for (i = 0; i < count; i++) { 170 out[i] = NULL; 171 pipe_texture_reference(&out[i], xstfb->textures[statts[i]]); 172 } 173 174 return TRUE; 175} 176 177static boolean 178xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, 179 enum st_attachment_type statt) 180{ 181 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 182 boolean ret; 183 184 ret = xmesa_st_framebuffer_display(stfbi, statt); 185 if (ret) 186 xmesa_check_buffer_size(xstfb->buffer); 187 188 return ret; 189} 190 191struct st_framebuffer_iface * 192xmesa_create_st_framebuffer(struct pipe_screen *screen, XMesaBuffer b) 193{ 194 struct st_framebuffer_iface *stfbi; 195 struct xmesa_st_framebuffer *xstfb; 196 197 stfbi = CALLOC_STRUCT(st_framebuffer_iface); 198 xstfb = CALLOC_STRUCT(xmesa_st_framebuffer); 199 if (!stfbi || !xstfb) { 200 if (stfbi) 201 FREE(stfbi); 202 if (xstfb) 203 FREE(xstfb); 204 return NULL; 205 } 206 207 xstfb->screen = screen; 208 xstfb->buffer = b; 209 xstfb->stvis = b->xm_visual->stvis; 210 211 stfbi->visual = &xstfb->stvis; 212 stfbi->flush_front = xmesa_st_framebuffer_flush_front; 213 stfbi->validate = xmesa_st_framebuffer_validate; 214 stfbi->st_manager_private = (void *) xstfb; 215 216 return stfbi; 217} 218 219void 220xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) 221{ 222 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 223 int i; 224 225 pipe_surface_reference(&xstfb->display_surface, NULL); 226 227 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) 228 pipe_texture_reference(&xstfb->textures[i], NULL); 229 230 FREE(xstfb); 231 FREE(stfbi); 232} 233 234void 235xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi) 236{ 237 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 238 boolean ret; 239 240 ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT); 241 if (ret) { 242 struct pipe_texture **front, **back, *tmp; 243 244 front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT]; 245 back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT]; 246 /* swap textures only if the front texture has been allocated */ 247 if (*front) { 248 tmp = *front; 249 *front = *back; 250 *back = tmp; 251 } 252 253 xmesa_check_buffer_size(xstfb->buffer); 254 } 255} 256 257void 258xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, 259 enum st_attachment_type src, 260 enum st_attachment_type dst, 261 int x, int y, int w, int h) 262{ 263 /* TODO */ 264} 265