1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2009, VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci/* 28bf215546Sopenharmony_ci * Author: Keith Whitwell <keithw@vmware.com> 29bf215546Sopenharmony_ci * Author: Jakob Bornecrantz <wallbraker@gmail.com> 30bf215546Sopenharmony_ci */ 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "dri_screen.h" 33bf215546Sopenharmony_ci#include "dri_context.h" 34bf215546Sopenharmony_ci#include "dri_drawable.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include "pipe/p_screen.h" 37bf215546Sopenharmony_ci#include "util/format/u_format.h" 38bf215546Sopenharmony_ci#include "util/u_memory.h" 39bf215546Sopenharmony_ci#include "util/u_inlines.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cistatic uint32_t drifb_ID = 0; 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistatic bool 44bf215546Sopenharmony_cidri_st_framebuffer_validate(struct st_context_iface *stctx, 45bf215546Sopenharmony_ci struct st_framebuffer_iface *stfbi, 46bf215546Sopenharmony_ci const enum st_attachment_type *statts, 47bf215546Sopenharmony_ci unsigned count, 48bf215546Sopenharmony_ci struct pipe_resource **out) 49bf215546Sopenharmony_ci{ 50bf215546Sopenharmony_ci struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; 51bf215546Sopenharmony_ci struct dri_drawable *drawable = 52bf215546Sopenharmony_ci (struct dri_drawable *) stfbi->st_manager_private; 53bf215546Sopenharmony_ci struct dri_screen *screen = dri_screen(drawable->sPriv); 54bf215546Sopenharmony_ci unsigned statt_mask, new_mask; 55bf215546Sopenharmony_ci bool new_stamp; 56bf215546Sopenharmony_ci int i; 57bf215546Sopenharmony_ci unsigned int lastStamp; 58bf215546Sopenharmony_ci struct pipe_resource **textures = 59bf215546Sopenharmony_ci drawable->stvis.samples > 1 ? drawable->msaa_textures 60bf215546Sopenharmony_ci : drawable->textures; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci statt_mask = 0x0; 63bf215546Sopenharmony_ci for (i = 0; i < count; i++) 64bf215546Sopenharmony_ci statt_mask |= (1 << statts[i]); 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci /* record newly allocated textures */ 67bf215546Sopenharmony_ci new_mask = (statt_mask & ~drawable->texture_mask); 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci /* 70bf215546Sopenharmony_ci * dPriv->dri2.stamp is the server stamp. dPriv->lastStamp is the 71bf215546Sopenharmony_ci * client stamp. It has the value of the server stamp when last 72bf215546Sopenharmony_ci * checked. 73bf215546Sopenharmony_ci */ 74bf215546Sopenharmony_ci do { 75bf215546Sopenharmony_ci lastStamp = drawable->dPriv->lastStamp; 76bf215546Sopenharmony_ci new_stamp = (drawable->texture_stamp != lastStamp); 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci if (new_stamp || new_mask) { 79bf215546Sopenharmony_ci if (new_stamp && drawable->update_drawable_info) 80bf215546Sopenharmony_ci drawable->update_drawable_info(drawable); 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci drawable->allocate_textures(ctx, drawable, statts, count); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci /* add existing textures */ 85bf215546Sopenharmony_ci for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 86bf215546Sopenharmony_ci if (textures[i]) 87bf215546Sopenharmony_ci statt_mask |= (1 << i); 88bf215546Sopenharmony_ci } 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci drawable->texture_stamp = lastStamp; 91bf215546Sopenharmony_ci drawable->texture_mask = statt_mask; 92bf215546Sopenharmony_ci } 93bf215546Sopenharmony_ci } while (lastStamp != drawable->dPriv->lastStamp); 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci /* Flush the pending set_damage_region request. */ 96bf215546Sopenharmony_ci struct pipe_screen *pscreen = screen->base.screen; 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci if (new_mask & (1 << ST_ATTACHMENT_BACK_LEFT) && 99bf215546Sopenharmony_ci pscreen->set_damage_region) { 100bf215546Sopenharmony_ci struct pipe_resource *resource = textures[ST_ATTACHMENT_BACK_LEFT]; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci pscreen->set_damage_region(pscreen, resource, 103bf215546Sopenharmony_ci drawable->num_damage_rects, 104bf215546Sopenharmony_ci drawable->damage_rects); 105bf215546Sopenharmony_ci } 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci if (!out) 108bf215546Sopenharmony_ci return true; 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci /* Set the window-system buffers for the gallium frontend. */ 111bf215546Sopenharmony_ci for (i = 0; i < count; i++) 112bf215546Sopenharmony_ci pipe_resource_reference(&out[i], textures[statts[i]]); 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci return true; 115bf215546Sopenharmony_ci} 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_cistatic bool 118bf215546Sopenharmony_cidri_st_framebuffer_flush_front(struct st_context_iface *stctx, 119bf215546Sopenharmony_ci struct st_framebuffer_iface *stfbi, 120bf215546Sopenharmony_ci enum st_attachment_type statt) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; 123bf215546Sopenharmony_ci struct dri_drawable *drawable = 124bf215546Sopenharmony_ci (struct dri_drawable *) stfbi->st_manager_private; 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci /* XXX remove this and just set the correct one on the framebuffer */ 127bf215546Sopenharmony_ci return drawable->flush_frontbuffer(ctx, drawable, statt); 128bf215546Sopenharmony_ci} 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci/** 131bf215546Sopenharmony_ci * The gallium frontend framebuffer interface flush_swapbuffers callback 132bf215546Sopenharmony_ci */ 133bf215546Sopenharmony_cistatic bool 134bf215546Sopenharmony_cidri_st_framebuffer_flush_swapbuffers(struct st_context_iface *stctx, 135bf215546Sopenharmony_ci struct st_framebuffer_iface *stfbi) 136bf215546Sopenharmony_ci{ 137bf215546Sopenharmony_ci struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; 138bf215546Sopenharmony_ci struct dri_drawable *drawable = 139bf215546Sopenharmony_ci (struct dri_drawable *) stfbi->st_manager_private; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci if (drawable->flush_swapbuffers) 142bf215546Sopenharmony_ci drawable->flush_swapbuffers(ctx, drawable); 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci return true; 145bf215546Sopenharmony_ci} 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci/** 148bf215546Sopenharmony_ci * This is called when we need to set up GL rendering to a new X window. 149bf215546Sopenharmony_ci */ 150bf215546Sopenharmony_cibool 151bf215546Sopenharmony_cidri_create_buffer(__DRIscreen * sPriv, 152bf215546Sopenharmony_ci __DRIdrawable * dPriv, 153bf215546Sopenharmony_ci const struct gl_config * visual, bool isPixmap) 154bf215546Sopenharmony_ci{ 155bf215546Sopenharmony_ci struct dri_screen *screen = sPriv->driverPrivate; 156bf215546Sopenharmony_ci struct dri_drawable *drawable = NULL; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci if (isPixmap) 159bf215546Sopenharmony_ci goto fail; /* not implemented */ 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci drawable = CALLOC_STRUCT(dri_drawable); 162bf215546Sopenharmony_ci if (drawable == NULL) 163bf215546Sopenharmony_ci goto fail; 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci dri_fill_st_visual(&drawable->stvis, screen, visual); 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci /* setup the st_framebuffer_iface */ 168bf215546Sopenharmony_ci drawable->base.visual = &drawable->stvis; 169bf215546Sopenharmony_ci drawable->base.flush_front = dri_st_framebuffer_flush_front; 170bf215546Sopenharmony_ci drawable->base.validate = dri_st_framebuffer_validate; 171bf215546Sopenharmony_ci drawable->base.flush_swapbuffers = dri_st_framebuffer_flush_swapbuffers; 172bf215546Sopenharmony_ci drawable->base.st_manager_private = (void *) drawable; 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci drawable->screen = screen; 175bf215546Sopenharmony_ci drawable->sPriv = sPriv; 176bf215546Sopenharmony_ci drawable->dPriv = dPriv; 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci dPriv->driverPrivate = (void *)drawable; 179bf215546Sopenharmony_ci p_atomic_set(&drawable->base.stamp, 1); 180bf215546Sopenharmony_ci drawable->base.ID = p_atomic_inc_return(&drifb_ID); 181bf215546Sopenharmony_ci drawable->base.state_manager = &screen->base; 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci return true; 184bf215546Sopenharmony_cifail: 185bf215546Sopenharmony_ci FREE(drawable); 186bf215546Sopenharmony_ci return false; 187bf215546Sopenharmony_ci} 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_civoid 190bf215546Sopenharmony_cidri_destroy_buffer(__DRIdrawable * dPriv) 191bf215546Sopenharmony_ci{ 192bf215546Sopenharmony_ci struct dri_drawable *drawable = dri_drawable(dPriv); 193bf215546Sopenharmony_ci struct dri_screen *screen = drawable->screen; 194bf215546Sopenharmony_ci struct st_api *stapi = screen->st_api; 195bf215546Sopenharmony_ci int i; 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci for (i = 0; i < ST_ATTACHMENT_COUNT; i++) 198bf215546Sopenharmony_ci pipe_resource_reference(&drawable->textures[i], NULL); 199bf215546Sopenharmony_ci for (i = 0; i < ST_ATTACHMENT_COUNT; i++) 200bf215546Sopenharmony_ci pipe_resource_reference(&drawable->msaa_textures[i], NULL); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci screen->base.screen->fence_reference(screen->base.screen, 203bf215546Sopenharmony_ci &drawable->throttle_fence, NULL); 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci /* Notify the st manager that this drawable is no longer valid */ 206bf215546Sopenharmony_ci stapi->destroy_drawable(stapi, &drawable->base); 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci FREE(drawable->damage_rects); 209bf215546Sopenharmony_ci FREE(drawable); 210bf215546Sopenharmony_ci} 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci/** 213bf215546Sopenharmony_ci * Validate the texture at an attachment. Allocate the texture if it does not 214bf215546Sopenharmony_ci * exist. Used by the TFP extension. 215bf215546Sopenharmony_ci */ 216bf215546Sopenharmony_cistatic void 217bf215546Sopenharmony_cidri_drawable_validate_att(struct dri_context *ctx, 218bf215546Sopenharmony_ci struct dri_drawable *drawable, 219bf215546Sopenharmony_ci enum st_attachment_type statt) 220bf215546Sopenharmony_ci{ 221bf215546Sopenharmony_ci enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; 222bf215546Sopenharmony_ci unsigned i, count = 0; 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci /* check if buffer already exists */ 225bf215546Sopenharmony_ci if (drawable->texture_mask & (1 << statt)) 226bf215546Sopenharmony_ci return; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci /* make sure DRI2 does not destroy existing buffers */ 229bf215546Sopenharmony_ci for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 230bf215546Sopenharmony_ci if (drawable->texture_mask & (1 << i)) { 231bf215546Sopenharmony_ci statts[count++] = i; 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci } 234bf215546Sopenharmony_ci statts[count++] = statt; 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci drawable->texture_stamp = drawable->dPriv->lastStamp - 1; 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci drawable->base.validate(ctx->st, &drawable->base, statts, count, NULL); 239bf215546Sopenharmony_ci} 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci/** 242bf215546Sopenharmony_ci * These are used for GLX_EXT_texture_from_pixmap 243bf215546Sopenharmony_ci */ 244bf215546Sopenharmony_cistatic void 245bf215546Sopenharmony_cidri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, 246bf215546Sopenharmony_ci GLint format, __DRIdrawable *dPriv) 247bf215546Sopenharmony_ci{ 248bf215546Sopenharmony_ci struct dri_context *ctx = dri_context(pDRICtx); 249bf215546Sopenharmony_ci struct st_context_iface *st = ctx->st; 250bf215546Sopenharmony_ci struct dri_drawable *drawable = dri_drawable(dPriv); 251bf215546Sopenharmony_ci struct pipe_resource *pt; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci if (st->thread_finish) 254bf215546Sopenharmony_ci st->thread_finish(st); 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci dri_drawable_validate_att(ctx, drawable, ST_ATTACHMENT_FRONT_LEFT); 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci /* Use the pipe resource associated with the X drawable */ 259bf215546Sopenharmony_ci pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci if (pt) { 262bf215546Sopenharmony_ci enum pipe_format internal_format = pt->format; 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci if (format == __DRI_TEXTURE_FORMAT_RGB) { 265bf215546Sopenharmony_ci /* only need to cover the formats recognized by dri_fill_st_visual */ 266bf215546Sopenharmony_ci switch (internal_format) { 267bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16B16A16_FLOAT: 268bf215546Sopenharmony_ci internal_format = PIPE_FORMAT_R16G16B16X16_FLOAT; 269bf215546Sopenharmony_ci break; 270bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_UNORM: 271bf215546Sopenharmony_ci internal_format = PIPE_FORMAT_B10G10R10X2_UNORM; 272bf215546Sopenharmony_ci break; 273bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10A2_UNORM: 274bf215546Sopenharmony_ci internal_format = PIPE_FORMAT_R10G10B10X2_UNORM; 275bf215546Sopenharmony_ci break; 276bf215546Sopenharmony_ci case PIPE_FORMAT_BGRA8888_UNORM: 277bf215546Sopenharmony_ci internal_format = PIPE_FORMAT_BGRX8888_UNORM; 278bf215546Sopenharmony_ci break; 279bf215546Sopenharmony_ci case PIPE_FORMAT_ARGB8888_UNORM: 280bf215546Sopenharmony_ci internal_format = PIPE_FORMAT_XRGB8888_UNORM; 281bf215546Sopenharmony_ci break; 282bf215546Sopenharmony_ci default: 283bf215546Sopenharmony_ci break; 284bf215546Sopenharmony_ci } 285bf215546Sopenharmony_ci } 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci drawable->update_tex_buffer(drawable, ctx, pt); 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci ctx->st->teximage(ctx->st, 290bf215546Sopenharmony_ci (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, 291bf215546Sopenharmony_ci 0, internal_format, pt, false); 292bf215546Sopenharmony_ci } 293bf215546Sopenharmony_ci} 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_cistatic void 296bf215546Sopenharmony_cidri_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, 297bf215546Sopenharmony_ci __DRIdrawable *dPriv) 298bf215546Sopenharmony_ci{ 299bf215546Sopenharmony_ci dri_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); 300bf215546Sopenharmony_ci} 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ciconst __DRItexBufferExtension driTexBufferExtension = { 303bf215546Sopenharmony_ci .base = { __DRI_TEX_BUFFER, 2 }, 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci .setTexBuffer = dri_set_tex_buffer, 306bf215546Sopenharmony_ci .setTexBuffer2 = dri_set_tex_buffer2, 307bf215546Sopenharmony_ci .releaseTexBuffer = NULL, 308bf215546Sopenharmony_ci}; 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci/** 311bf215546Sopenharmony_ci * Get the format and binding of an attachment. 312bf215546Sopenharmony_ci */ 313bf215546Sopenharmony_civoid 314bf215546Sopenharmony_cidri_drawable_get_format(struct dri_drawable *drawable, 315bf215546Sopenharmony_ci enum st_attachment_type statt, 316bf215546Sopenharmony_ci enum pipe_format *format, 317bf215546Sopenharmony_ci unsigned *bind) 318bf215546Sopenharmony_ci{ 319bf215546Sopenharmony_ci switch (statt) { 320bf215546Sopenharmony_ci case ST_ATTACHMENT_FRONT_LEFT: 321bf215546Sopenharmony_ci case ST_ATTACHMENT_BACK_LEFT: 322bf215546Sopenharmony_ci case ST_ATTACHMENT_FRONT_RIGHT: 323bf215546Sopenharmony_ci case ST_ATTACHMENT_BACK_RIGHT: 324bf215546Sopenharmony_ci /* Other pieces of the driver stack get confused and behave incorrectly 325bf215546Sopenharmony_ci * when they get an sRGB drawable. st/mesa receives "drawable->stvis" 326bf215546Sopenharmony_ci * though other means and handles it correctly, so we don't really need 327bf215546Sopenharmony_ci * to use an sRGB format here. 328bf215546Sopenharmony_ci */ 329bf215546Sopenharmony_ci *format = util_format_linear(drawable->stvis.color_format); 330bf215546Sopenharmony_ci *bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 331bf215546Sopenharmony_ci break; 332bf215546Sopenharmony_ci case ST_ATTACHMENT_DEPTH_STENCIL: 333bf215546Sopenharmony_ci *format = drawable->stvis.depth_stencil_format; 334bf215546Sopenharmony_ci *bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ 335bf215546Sopenharmony_ci break; 336bf215546Sopenharmony_ci default: 337bf215546Sopenharmony_ci *format = PIPE_FORMAT_NONE; 338bf215546Sopenharmony_ci *bind = 0; 339bf215546Sopenharmony_ci break; 340bf215546Sopenharmony_ci } 341bf215546Sopenharmony_ci} 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_civoid 344bf215546Sopenharmony_cidri_pipe_blit(struct pipe_context *pipe, 345bf215546Sopenharmony_ci struct pipe_resource *dst, 346bf215546Sopenharmony_ci struct pipe_resource *src) 347bf215546Sopenharmony_ci{ 348bf215546Sopenharmony_ci struct pipe_blit_info blit; 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci if (!dst || !src) 351bf215546Sopenharmony_ci return; 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci /* From the GL spec, version 4.2, section 4.1.11 (Additional Multisample 354bf215546Sopenharmony_ci * Fragment Operations): 355bf215546Sopenharmony_ci * 356bf215546Sopenharmony_ci * If a framebuffer object is not bound, after all operations have 357bf215546Sopenharmony_ci * been completed on the multisample buffer, the sample values for 358bf215546Sopenharmony_ci * each color in the multisample buffer are combined to produce a 359bf215546Sopenharmony_ci * single color value, and that value is written into the 360bf215546Sopenharmony_ci * corresponding color buffers selected by DrawBuffer or 361bf215546Sopenharmony_ci * DrawBuffers. An implementation may defer the writing of the color 362bf215546Sopenharmony_ci * buffers until a later time, but the state of the framebuffer must 363bf215546Sopenharmony_ci * behave as if the color buffers were updated as each fragment was 364bf215546Sopenharmony_ci * processed. The method of combination is not specified. If the 365bf215546Sopenharmony_ci * framebuffer contains sRGB values, then it is recommended that the 366bf215546Sopenharmony_ci * an average of sample values is computed in a linearized space, as 367bf215546Sopenharmony_ci * for blending (see section 4.1.7). 368bf215546Sopenharmony_ci * 369bf215546Sopenharmony_ci * In other words, to do a resolve operation in a linear space, we have 370bf215546Sopenharmony_ci * to set sRGB formats if the original resources were sRGB, so don't use 371bf215546Sopenharmony_ci * util_format_linear. 372bf215546Sopenharmony_ci */ 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci memset(&blit, 0, sizeof(blit)); 375bf215546Sopenharmony_ci blit.dst.resource = dst; 376bf215546Sopenharmony_ci blit.dst.box.width = dst->width0; 377bf215546Sopenharmony_ci blit.dst.box.height = dst->height0; 378bf215546Sopenharmony_ci blit.dst.box.depth = 1; 379bf215546Sopenharmony_ci blit.dst.format = dst->format; 380bf215546Sopenharmony_ci blit.src.resource = src; 381bf215546Sopenharmony_ci blit.src.box.width = src->width0; 382bf215546Sopenharmony_ci blit.src.box.height = src->height0; 383bf215546Sopenharmony_ci blit.src.box.depth = 1; 384bf215546Sopenharmony_ci blit.src.format = src->format; 385bf215546Sopenharmony_ci blit.mask = PIPE_MASK_RGBA; 386bf215546Sopenharmony_ci blit.filter = PIPE_TEX_FILTER_NEAREST; 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci pipe->blit(pipe, &blit); 389bf215546Sopenharmony_ci} 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_cistatic void 392bf215546Sopenharmony_cidri_postprocessing(struct dri_context *ctx, 393bf215546Sopenharmony_ci struct dri_drawable *drawable, 394bf215546Sopenharmony_ci enum st_attachment_type att) 395bf215546Sopenharmony_ci{ 396bf215546Sopenharmony_ci struct pipe_resource *src = drawable->textures[att]; 397bf215546Sopenharmony_ci struct pipe_resource *zsbuf = drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]; 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci if (ctx->pp && src) 400bf215546Sopenharmony_ci pp_run(ctx->pp, src, src, zsbuf); 401bf215546Sopenharmony_ci} 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_cistruct notify_before_flush_cb_args { 404bf215546Sopenharmony_ci struct dri_context *ctx; 405bf215546Sopenharmony_ci struct dri_drawable *drawable; 406bf215546Sopenharmony_ci unsigned flags; 407bf215546Sopenharmony_ci enum __DRI2throttleReason reason; 408bf215546Sopenharmony_ci bool swap_msaa_buffers; 409bf215546Sopenharmony_ci}; 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_cistatic void 412bf215546Sopenharmony_cinotify_before_flush_cb(void* _args) 413bf215546Sopenharmony_ci{ 414bf215546Sopenharmony_ci struct notify_before_flush_cb_args *args = (struct notify_before_flush_cb_args *) _args; 415bf215546Sopenharmony_ci struct st_context_iface *st = args->ctx->st; 416bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ci if (args->drawable->stvis.samples > 1 && 419bf215546Sopenharmony_ci (args->reason == __DRI2_THROTTLE_SWAPBUFFER || 420bf215546Sopenharmony_ci args->reason == __DRI2_THROTTLE_COPYSUBBUFFER)) { 421bf215546Sopenharmony_ci /* Resolve the MSAA back buffer. */ 422bf215546Sopenharmony_ci dri_pipe_blit(st->pipe, 423bf215546Sopenharmony_ci args->drawable->textures[ST_ATTACHMENT_BACK_LEFT], 424bf215546Sopenharmony_ci args->drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci if (args->reason == __DRI2_THROTTLE_SWAPBUFFER && 427bf215546Sopenharmony_ci args->drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] && 428bf215546Sopenharmony_ci args->drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]) { 429bf215546Sopenharmony_ci args->swap_msaa_buffers = true; 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci /* FRONT_LEFT is resolved in drawable->flush_frontbuffer. */ 433bf215546Sopenharmony_ci } 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci dri_postprocessing(args->ctx, args->drawable, ST_ATTACHMENT_BACK_LEFT); 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_ci if (pipe->invalidate_resource && 438bf215546Sopenharmony_ci (args->flags & __DRI2_FLUSH_INVALIDATE_ANCILLARY)) { 439bf215546Sopenharmony_ci if (args->drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) 440bf215546Sopenharmony_ci pipe->invalidate_resource(pipe, args->drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); 441bf215546Sopenharmony_ci if (args->drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]) 442bf215546Sopenharmony_ci pipe->invalidate_resource(pipe, args->drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]); 443bf215546Sopenharmony_ci } 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci if (args->ctx->hud) { 446bf215546Sopenharmony_ci hud_run(args->ctx->hud, args->ctx->st->cso_context, 447bf215546Sopenharmony_ci args->drawable->textures[ST_ATTACHMENT_BACK_LEFT]); 448bf215546Sopenharmony_ci } 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_ci pipe->flush_resource(pipe, args->drawable->textures[ST_ATTACHMENT_BACK_LEFT]); 451bf215546Sopenharmony_ci} 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci/** 454bf215546Sopenharmony_ci * DRI2 flush extension, the flush_with_flags function. 455bf215546Sopenharmony_ci * 456bf215546Sopenharmony_ci * \param context the context 457bf215546Sopenharmony_ci * \param drawable the drawable to flush 458bf215546Sopenharmony_ci * \param flags a combination of _DRI2_FLUSH_xxx flags 459bf215546Sopenharmony_ci * \param throttle_reason the reason for throttling, 0 = no throttling 460bf215546Sopenharmony_ci */ 461bf215546Sopenharmony_civoid 462bf215546Sopenharmony_cidri_flush(__DRIcontext *cPriv, 463bf215546Sopenharmony_ci __DRIdrawable *dPriv, 464bf215546Sopenharmony_ci unsigned flags, 465bf215546Sopenharmony_ci enum __DRI2throttleReason reason) 466bf215546Sopenharmony_ci{ 467bf215546Sopenharmony_ci struct dri_context *ctx = dri_context(cPriv); 468bf215546Sopenharmony_ci struct dri_drawable *drawable = dri_drawable(dPriv); 469bf215546Sopenharmony_ci struct st_context_iface *st; 470bf215546Sopenharmony_ci unsigned flush_flags; 471bf215546Sopenharmony_ci struct notify_before_flush_cb_args args = { 0 }; 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci if (!ctx) { 474bf215546Sopenharmony_ci assert(0); 475bf215546Sopenharmony_ci return; 476bf215546Sopenharmony_ci } 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci st = ctx->st; 479bf215546Sopenharmony_ci if (st->thread_finish) 480bf215546Sopenharmony_ci st->thread_finish(st); 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci if (drawable) { 483bf215546Sopenharmony_ci /* prevent recursion */ 484bf215546Sopenharmony_ci if (drawable->flushing) 485bf215546Sopenharmony_ci return; 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci drawable->flushing = true; 488bf215546Sopenharmony_ci } 489bf215546Sopenharmony_ci else { 490bf215546Sopenharmony_ci flags &= ~__DRI2_FLUSH_DRAWABLE; 491bf215546Sopenharmony_ci } 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci if ((flags & __DRI2_FLUSH_DRAWABLE) && 494bf215546Sopenharmony_ci drawable->textures[ST_ATTACHMENT_BACK_LEFT]) { 495bf215546Sopenharmony_ci /* We can't do operations on the back buffer here, because there 496bf215546Sopenharmony_ci * may be some pending operations that will get flushed by the 497bf215546Sopenharmony_ci * call to st->flush (eg: FLUSH_VERTICES). 498bf215546Sopenharmony_ci * Instead we register a callback to be notified when all operations 499bf215546Sopenharmony_ci * have been submitted but before the call to st_flush. 500bf215546Sopenharmony_ci */ 501bf215546Sopenharmony_ci args.ctx = ctx; 502bf215546Sopenharmony_ci args.drawable = drawable; 503bf215546Sopenharmony_ci args.flags = flags; 504bf215546Sopenharmony_ci args.reason = reason; 505bf215546Sopenharmony_ci } 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci flush_flags = 0; 508bf215546Sopenharmony_ci if (flags & __DRI2_FLUSH_CONTEXT) 509bf215546Sopenharmony_ci flush_flags |= ST_FLUSH_FRONT; 510bf215546Sopenharmony_ci if (reason == __DRI2_THROTTLE_SWAPBUFFER) 511bf215546Sopenharmony_ci flush_flags |= ST_FLUSH_END_OF_FRAME; 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci /* Flush the context and throttle if needed. */ 514bf215546Sopenharmony_ci if (dri_screen(ctx->sPriv)->throttle && 515bf215546Sopenharmony_ci drawable && 516bf215546Sopenharmony_ci (reason == __DRI2_THROTTLE_SWAPBUFFER || 517bf215546Sopenharmony_ci reason == __DRI2_THROTTLE_FLUSHFRONT)) { 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci struct pipe_screen *screen = drawable->screen->base.screen; 520bf215546Sopenharmony_ci struct pipe_fence_handle *new_fence = NULL; 521bf215546Sopenharmony_ci 522bf215546Sopenharmony_ci st->flush(st, flush_flags, &new_fence, args.ctx ? notify_before_flush_cb : NULL, &args); 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci /* throttle on the previous fence */ 525bf215546Sopenharmony_ci if (drawable->throttle_fence) { 526bf215546Sopenharmony_ci screen->fence_finish(screen, NULL, drawable->throttle_fence, PIPE_TIMEOUT_INFINITE); 527bf215546Sopenharmony_ci screen->fence_reference(screen, &drawable->throttle_fence, NULL); 528bf215546Sopenharmony_ci } 529bf215546Sopenharmony_ci drawable->throttle_fence = new_fence; 530bf215546Sopenharmony_ci } 531bf215546Sopenharmony_ci else if (flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) { 532bf215546Sopenharmony_ci st->flush(st, flush_flags, NULL, args.ctx ? notify_before_flush_cb : NULL, &args); 533bf215546Sopenharmony_ci } 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci if (drawable) { 536bf215546Sopenharmony_ci drawable->flushing = false; 537bf215546Sopenharmony_ci } 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci /* Swap the MSAA front and back buffers, so that reading 540bf215546Sopenharmony_ci * from the front buffer after SwapBuffers returns what was 541bf215546Sopenharmony_ci * in the back buffer. 542bf215546Sopenharmony_ci */ 543bf215546Sopenharmony_ci if (args.swap_msaa_buffers) { 544bf215546Sopenharmony_ci struct pipe_resource *tmp = 545bf215546Sopenharmony_ci drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]; 546bf215546Sopenharmony_ci 547bf215546Sopenharmony_ci drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] = 548bf215546Sopenharmony_ci drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; 549bf215546Sopenharmony_ci drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT] = tmp; 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci /* Now that we have swapped the buffers, this tells the gallium 552bf215546Sopenharmony_ci * frontend to revalidate the framebuffer. 553bf215546Sopenharmony_ci */ 554bf215546Sopenharmony_ci p_atomic_inc(&drawable->base.stamp); 555bf215546Sopenharmony_ci } 556bf215546Sopenharmony_ci} 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci/** 559bf215546Sopenharmony_ci * dri_throttle - A DRI2ThrottleExtension throttling function. 560bf215546Sopenharmony_ci */ 561bf215546Sopenharmony_cistatic void 562bf215546Sopenharmony_cidri_throttle(__DRIcontext *cPriv, __DRIdrawable *dPriv, 563bf215546Sopenharmony_ci enum __DRI2throttleReason reason) 564bf215546Sopenharmony_ci{ 565bf215546Sopenharmony_ci dri_flush(cPriv, dPriv, 0, reason); 566bf215546Sopenharmony_ci} 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_ciconst __DRI2throttleExtension dri2ThrottleExtension = { 570bf215546Sopenharmony_ci .base = { __DRI2_THROTTLE, 1 }, 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci .throttle = dri_throttle, 573bf215546Sopenharmony_ci}; 574bf215546Sopenharmony_ci 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci/* vim: set sw=3 ts=8 sts=3 expandtab: */ 577