drisw.c revision a66b391edf746a5eb0cb4aad1ff2e546df00a11d
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 73static void 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(dPriv->driScreenPriv); 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(dPriv->driScreenPriv); 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 150static void 151drisw_flush_frontbuffer(struct dri_drawable *drawable, 152 enum st_attachment_type statt) 153{ 154 struct dri_context *ctx = dri_get_current(drawable->sPriv); 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 */ 178static void 179drisw_allocate_textures(struct dri_drawable *drawable, 180 const enum st_attachment_type *statts, 181 unsigned count) 182{ 183 struct dri_screen *screen = dri_screen(drawable->sPriv); 184 struct pipe_resource templ; 185 unsigned width, height; 186 boolean resized; 187 int i; 188 189 width = drawable->dPriv->w; 190 height = drawable->dPriv->h; 191 192 resized = (drawable->old_w != width || 193 drawable->old_h != height); 194 195 /* remove outdated textures */ 196 if (resized) { 197 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) 198 pipe_resource_reference(&drawable->textures[i], NULL); 199 } 200 201 memset(&templ, 0, sizeof(templ)); 202 templ.target = PIPE_TEXTURE_2D; 203 templ.width0 = width; 204 templ.height0 = height; 205 templ.depth0 = 1; 206 templ.last_level = 0; 207 208 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 209 enum pipe_format format; 210 unsigned bind; 211 212 /* the texture already exists or not requested */ 213 if (drawable->textures[statts[i]]) 214 continue; 215 216 dri_drawable_get_format(drawable, statts[i], &format, &bind); 217 218 if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL) 219 bind |= PIPE_BIND_DISPLAY_TARGET; 220 221 if (format == PIPE_FORMAT_NONE) 222 continue; 223 224 templ.format = format; 225 templ.bind = bind; 226 227 drawable->textures[statts[i]] = 228 screen->pipe_screen->resource_create(screen->pipe_screen, &templ); 229 } 230 231 drawable->old_w = width; 232 drawable->old_h = height; 233} 234 235/* 236 * Backend function for init_screen. 237 */ 238 239static const __DRIextension *drisw_screen_extensions[] = { 240 NULL 241}; 242 243static struct drisw_loader_funcs drisw_lf = { 244 .put_image = drisw_put_image 245}; 246 247const __DRIconfig ** 248drisw_init_screen(__DRIscreen * sPriv) 249{ 250 const __DRIconfig **configs; 251 struct dri_screen *screen; 252 struct pipe_screen *pscreen; 253 254 screen = CALLOC_STRUCT(dri_screen); 255 if (!screen) 256 return NULL; 257 258 screen->api = NULL; /* not needed */ 259 screen->sPriv = sPriv; 260 screen->fd = -1; 261 screen->allocate_textures = drisw_allocate_textures; 262 screen->update_drawable_info = drisw_update_drawable_info; 263 screen->flush_frontbuffer = drisw_flush_frontbuffer; 264 265 sPriv->private = (void *)screen; 266 sPriv->extensions = drisw_screen_extensions; 267 268 pscreen = drisw_create_screen(&drisw_lf); 269 /* dri_init_screen_helper checks pscreen for us */ 270 271 configs = dri_init_screen_helper(screen, pscreen, 32); 272 if (!configs) 273 goto fail; 274 275 return configs; 276fail: 277 dri_destroy_screen_helper(screen); 278 FREE(screen); 279 return NULL; 280} 281 282/* This is the table of extensions that the loader will dlsym() for. */ 283PUBLIC const __DRIextension *__driDriverExtensions[] = { 284 &driCoreExtension.base, 285 &driSWRastExtension.base, 286 NULL 287}; 288 289/* vim: set sw=3 ts=8 sts=3 expandtab: */ 290