xm_st.c revision 72ed7eb15a12ad88647dddefde5999ddd308b9e4
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 34/* support OpenGL by default */ 35#ifndef XMESA_ST_MODULE 36#define XMESA_ST_MODULE st_module_OpenGL 37#endif 38 39struct xmesa_st_framebuffer { 40 struct pipe_screen *screen; 41 XMesaBuffer buffer; 42 43 struct st_visual stvis; 44 45 unsigned texture_width, texture_height; 46 struct pipe_texture *textures[ST_ATTACHMENT_COUNT]; 47 48 struct pipe_surface *display_surface; 49}; 50 51static INLINE struct xmesa_st_framebuffer * 52xmesa_st_framebuffer(struct st_framebuffer_iface *stfbi) 53{ 54 return (struct xmesa_st_framebuffer *) stfbi->st_manager_private; 55} 56 57/** 58 * Display an attachment to the xlib_drawable of the framebuffer. 59 */ 60static boolean 61xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi, 62 enum st_attachment_type statt) 63{ 64 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 65 struct pipe_texture *ptex = xstfb->textures[statt]; 66 struct pipe_surface *psurf; 67 68 if (!ptex) 69 return TRUE; 70 71 psurf = xstfb->display_surface; 72 /* (re)allocate the surface for the texture to be displayed */ 73 if (!psurf || psurf->texture != ptex) { 74 pipe_surface_reference(&xstfb->display_surface, NULL); 75 76 psurf = xstfb->screen->get_tex_surface(xstfb->screen, 77 ptex, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ); 78 if (!psurf) 79 return FALSE; 80 81 xstfb->display_surface = psurf; 82 } 83 84 xstfb->screen->flush_frontbuffer(xstfb->screen, psurf, &xstfb->buffer->ws); 85 86 return TRUE; 87} 88 89/** 90 * Remove outdated textures and create the requested ones. 91 */ 92static void 93xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, 94 const enum st_attachment_type *statts, 95 unsigned count) 96{ 97 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 98 struct pipe_texture templ; 99 unsigned request_mask, i; 100 101 request_mask = 0; 102 for (i = 0; i < count; i++) 103 request_mask |= 1 << statts[i]; 104 105 memset(&templ, 0, sizeof(templ)); 106 templ.target = PIPE_TEXTURE_2D; 107 templ.width0 = xstfb->texture_width; 108 templ.height0 = xstfb->texture_height; 109 templ.depth0 = 1; 110 templ.last_level = 0; 111 112 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 113 struct pipe_texture *ptex = xstfb->textures[i]; 114 enum pipe_format format; 115 unsigned tex_usage; 116 117 /* remove outdated textures */ 118 if (ptex && (ptex->width0 != xstfb->texture_width || 119 ptex->height0 != xstfb->texture_height)) { 120 pipe_texture_reference(&xstfb->textures[i], NULL); 121 ptex = NULL; 122 } 123 124 /* the texture already exists or not requested */ 125 if (ptex || !(request_mask & (1 << i))) 126 continue; 127 128 switch (i) { 129 case ST_ATTACHMENT_FRONT_LEFT: 130 case ST_ATTACHMENT_BACK_LEFT: 131 case ST_ATTACHMENT_FRONT_RIGHT: 132 case ST_ATTACHMENT_BACK_RIGHT: 133 format = xstfb->stvis.color_format; 134 tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET | 135 PIPE_TEXTURE_USAGE_RENDER_TARGET; 136 break; 137 case ST_ATTACHMENT_DEPTH_STENCIL: 138 format = xstfb->stvis.depth_stencil_format; 139 tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; 140 break; 141 default: 142 format = PIPE_FORMAT_NONE; 143 break; 144 } 145 146 if (format != PIPE_FORMAT_NONE) { 147 templ.format = format; 148 templ.tex_usage = tex_usage; 149 150 xstfb->textures[i] = 151 xstfb->screen->texture_create(xstfb->screen, &templ); 152 } 153 } 154} 155 156static boolean 157xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, 158 const enum st_attachment_type *statts, 159 unsigned count, 160 struct pipe_texture **out) 161{ 162 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 163 unsigned i; 164 165 /* revalidate textures */ 166 if (xstfb->buffer->width != xstfb->texture_width || 167 xstfb->buffer->height != xstfb->texture_height) { 168 xstfb->texture_width = xstfb->buffer->width; 169 xstfb->texture_height = xstfb->buffer->height; 170 171 xmesa_st_framebuffer_validate_textures(stfbi, statts, count); 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 229 FREE(xstfb); 230 FREE(stfbi); 231} 232 233void 234xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi) 235{ 236 struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); 237 boolean ret; 238 239 ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT); 240 if (ret) { 241 struct pipe_texture **front, **back, *tmp; 242 243 front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT]; 244 back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT]; 245 /* swap textures only if the front texture has been allocated */ 246 if (*front) { 247 tmp = *front; 248 *front = *back; 249 *back = tmp; 250 } 251 252 xmesa_check_buffer_size(xstfb->buffer); 253 } 254} 255 256void 257xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, 258 enum st_attachment_type src, 259 enum st_attachment_type dst, 260 int x, int y, int w, int h) 261{ 262 /* TODO */ 263} 264 265struct st_api * 266xmesa_create_st_api(void) 267{ 268 return XMESA_ST_MODULE.create_api(); 269} 270