drisw.c revision 53c57191c5f24d3620e2e4ce95dd12b5c6e9109b
1/************************************************************************** 2 * 3 * Copyright 2009, VMware, Inc. 4 * All Rights Reserved. 5 * Copyright 2010 George Sapountzis <gsapountzis@gmail.com> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29/* TODO: 30 * 31 * xshm / texture_from_pixmap / EGLImage: 32 * 33 * Allow the loaders to use the XSHM extension. It probably requires callbacks 34 * for createImage/destroyImage similar to DRI2 getBuffers. 35 */ 36 37#include "util/u_format.h" 38#include "util/u_memory.h" 39#include "util/u_inlines.h" 40#include "pipe/p_context.h" 41#include "state_tracker/drisw_api.h" 42 43#include "dri_screen.h" 44#include "dri_context.h" 45#include "dri_drawable.h" 46#include "dri1_helper.h" 47#include "drisw.h" 48 49 50static INLINE void 51get_drawable_info(__DRIdrawable *dPriv, int *w, int *h) 52{ 53 __DRIscreen *sPriv = dPriv->driScreenPriv; 54 const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; 55 int x, y; 56 57 loader->getDrawableInfo(dPriv, 58 &x, &y, w, h, 59 dPriv->loaderPrivate); 60} 61 62static INLINE void 63put_image(__DRIdrawable *dPriv, void *data, unsigned width, unsigned height) 64{ 65 __DRIscreen *sPriv = dPriv->driScreenPriv; 66 const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; 67 68 loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, 69 0, 0, width, height, 70 data, dPriv->loaderPrivate); 71} 72 73void 74drisw_update_drawable_info(struct dri_drawable *drawable) 75{ 76 __DRIdrawable *dPriv = drawable->dPriv; 77 78 get_drawable_info(dPriv, &dPriv->w, &dPriv->h); 79} 80 81static void 82drisw_put_image(struct dri_drawable *drawable, 83 void *data, unsigned width, unsigned height) 84{ 85 __DRIdrawable *dPriv = drawable->dPriv; 86 87 put_image(dPriv, data, width, height); 88} 89 90static INLINE void 91drisw_present_texture(__DRIdrawable *dPriv, 92 struct pipe_resource *ptex) 93{ 94 struct dri_drawable *drawable = dri_drawable(dPriv); 95 struct dri_screen *screen = dri_screen(drawable->sPriv); 96 struct pipe_surface *psurf; 97 98 psurf = dri1_get_pipe_surface(drawable, ptex); 99 if (!psurf) 100 return; 101 102 screen->pipe_screen->flush_frontbuffer(screen->pipe_screen, psurf, drawable); 103} 104 105static INLINE void 106drisw_invalidate_drawable(__DRIdrawable *dPriv) 107{ 108 struct dri_context *ctx = dri_get_current(); 109 struct dri_drawable *drawable = dri_drawable(dPriv); 110 111 drawable->texture_stamp = dPriv->lastStamp - 1; 112 113 /* check if swapping currently bound buffer */ 114 if (ctx && ctx->dPriv == dPriv) 115 ctx->st->notify_invalid_framebuffer(ctx->st, drawable->stfb); 116} 117 118static INLINE void 119drisw_copy_to_front(__DRIdrawable * dPriv, 120 struct pipe_resource *ptex) 121{ 122 drisw_present_texture(dPriv, ptex); 123 124 drisw_invalidate_drawable(dPriv); 125} 126 127/* 128 * Backend functions for st_framebuffer interface and swap_buffers. 129 */ 130 131void 132drisw_swap_buffers(__DRIdrawable *dPriv) 133{ 134 struct dri_context *ctx = dri_get_current(); 135 struct dri_drawable *drawable = dri_drawable(dPriv); 136 struct pipe_resource *ptex; 137 138 if (!ctx) 139 return; 140 141 ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; 142 143 if (ptex) { 144 ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); 145 146 drisw_copy_to_front(dPriv, ptex); 147 } 148} 149 150void 151drisw_flush_frontbuffer(struct dri_drawable *drawable, 152 enum st_attachment_type statt) 153{ 154 struct dri_context *ctx = dri_get_current(); 155 struct pipe_resource *ptex; 156 157 if (!ctx) 158 return; 159 160 ptex = drawable->textures[statt]; 161 162 if (ptex) { 163 drisw_copy_to_front(ctx->dPriv, ptex); 164 } 165} 166 167/** 168 * Allocate framebuffer attachments. 169 * 170 * During fixed-size operation, the function keeps allocating new attachments 171 * as they are requested. Unused attachments are not removed, not until the 172 * framebuffer is resized or destroyed. 173 * 174 * It should be possible for DRI1 and DRISW to share this function, but it 175 * seems a better seperation and safer for each DRI version to provide its own 176 * function. 177 */ 178void 179drisw_allocate_textures(struct dri_drawable *drawable, 180 unsigned mask) 181{ 182 struct dri_screen *screen = dri_screen(drawable->sPriv); 183 struct pipe_resource templ; 184 unsigned width, height; 185 boolean resized; 186 int i; 187 188 width = drawable->dPriv->w; 189 height = drawable->dPriv->h; 190 191 resized = (drawable->old_w != width || 192 drawable->old_h != height); 193 194 /* remove outdated textures */ 195 if (resized) { 196 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) 197 pipe_resource_reference(&drawable->textures[i], NULL); 198 } 199 200 memset(&templ, 0, sizeof(templ)); 201 templ.target = PIPE_TEXTURE_2D; 202 templ.width0 = width; 203 templ.height0 = height; 204 templ.depth0 = 1; 205 templ.last_level = 0; 206 207 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 208 enum pipe_format format; 209 unsigned tex_usage; 210 211 /* the texture already exists or not requested */ 212 if (drawable->textures[i] || !(mask & (1 << i))) { 213 continue; 214 } 215 216 switch (i) { 217 case ST_ATTACHMENT_FRONT_LEFT: 218 case ST_ATTACHMENT_BACK_LEFT: 219 case ST_ATTACHMENT_FRONT_RIGHT: 220 case ST_ATTACHMENT_BACK_RIGHT: 221 format = drawable->stvis.color_format; 222 tex_usage = PIPE_BIND_DISPLAY_TARGET | 223 PIPE_BIND_RENDER_TARGET; 224 break; 225 case ST_ATTACHMENT_DEPTH_STENCIL: 226 format = drawable->stvis.depth_stencil_format; 227 tex_usage = PIPE_BIND_DEPTH_STENCIL; 228 break; 229 default: 230 format = PIPE_FORMAT_NONE; 231 break; 232 } 233 234 if (format != PIPE_FORMAT_NONE) { 235 templ.format = format; 236 templ.bind = tex_usage; 237 238 drawable->textures[i] = 239 screen->pipe_screen->resource_create(screen->pipe_screen, &templ); 240 } 241 } 242 243 drawable->old_w = width; 244 drawable->old_h = height; 245} 246 247/* 248 * Backend function for init_screen. 249 */ 250 251static const __DRIextension *drisw_screen_extensions[] = { 252 NULL 253}; 254 255static struct drisw_loader_funcs drisw_lf = { 256 .put_image = drisw_put_image 257}; 258 259const __DRIconfig ** 260drisw_init_screen(__DRIscreen * sPriv) 261{ 262 const __DRIconfig **configs; 263 struct dri_screen *screen; 264 struct pipe_screen *pscreen; 265 266 screen = CALLOC_STRUCT(dri_screen); 267 if (!screen) 268 return NULL; 269 270 screen->api = NULL; /* not needed */ 271 screen->sPriv = sPriv; 272 screen->fd = -1; 273 274 sPriv->private = (void *)screen; 275 sPriv->extensions = drisw_screen_extensions; 276 277 pscreen = drisw_create_screen(&drisw_lf); 278 /* dri_init_screen_helper checks pscreen for us */ 279 280 configs = dri_init_screen_helper(screen, pscreen, 32); 281 if (!configs) 282 goto fail; 283 284 return configs; 285fail: 286 dri_destroy_screen_helper(screen); 287 FREE(screen); 288 return NULL; 289} 290 291/* This is the table of extensions that the loader will dlsym() for. */ 292PUBLIC const __DRIextension *__driDriverExtensions[] = { 293 &driCoreExtension.base, 294 &driSWRastExtension.base, 295 NULL 296}; 297 298/* vim: set sw=3 ts=8 sts=3 expandtab: */ 299