1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Mesa 3-D graphics library 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Copyright (C) 2010 LunarG Inc. 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 "Software"), 8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 14bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci * Authors: 25bf215546Sopenharmony_ci * Chia-I Wu <olv@lunarg.com> 26bf215546Sopenharmony_ci */ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "util/u_memory.h" 29bf215546Sopenharmony_ci#include "util/u_inlines.h" 30bf215546Sopenharmony_ci#include "util/u_atomic.h" 31bf215546Sopenharmony_ci#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ 32bf215546Sopenharmony_ci#include "pipe/p_state.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "stw_st.h" 35bf215546Sopenharmony_ci#include "stw_device.h" 36bf215546Sopenharmony_ci#include "stw_framebuffer.h" 37bf215546Sopenharmony_ci#include "stw_pixelformat.h" 38bf215546Sopenharmony_ci#include "stw_winsys.h" 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci#ifdef GALLIUM_ZINK 41bf215546Sopenharmony_ci#include "kopper_interface.h" 42bf215546Sopenharmony_ci#endif 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_cistruct stw_st_framebuffer { 45bf215546Sopenharmony_ci struct st_framebuffer_iface base; 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci struct stw_framebuffer *fb; 48bf215546Sopenharmony_ci struct st_visual stvis; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; 51bf215546Sopenharmony_ci struct pipe_resource *msaa_textures[ST_ATTACHMENT_COUNT]; 52bf215546Sopenharmony_ci struct pipe_resource *back_texture; 53bf215546Sopenharmony_ci bool needs_fake_front; 54bf215546Sopenharmony_ci unsigned texture_width, texture_height; 55bf215546Sopenharmony_ci unsigned texture_mask; 56bf215546Sopenharmony_ci}; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_cistatic uint32_t stwfb_ID = 0; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci/** 61bf215546Sopenharmony_ci * Is the given mutex held by the calling thread? 62bf215546Sopenharmony_ci */ 63bf215546Sopenharmony_cibool 64bf215546Sopenharmony_cistw_own_mutex(const CRITICAL_SECTION *cs) 65bf215546Sopenharmony_ci{ 66bf215546Sopenharmony_ci // We can't compare OwningThread with our thread handle/id (see 67bf215546Sopenharmony_ci // http://stackoverflow.com/a/12675635 ) but we can compare with the 68bf215546Sopenharmony_ci // OwningThread member of a critical section we know we own. 69bf215546Sopenharmony_ci CRITICAL_SECTION dummy; 70bf215546Sopenharmony_ci InitializeCriticalSection(&dummy); 71bf215546Sopenharmony_ci EnterCriticalSection(&dummy); 72bf215546Sopenharmony_ci if (0) 73bf215546Sopenharmony_ci _debug_printf("%p %p\n", cs->OwningThread, dummy.OwningThread); 74bf215546Sopenharmony_ci bool ret = cs->OwningThread == dummy.OwningThread; 75bf215546Sopenharmony_ci LeaveCriticalSection(&dummy); 76bf215546Sopenharmony_ci DeleteCriticalSection(&dummy); 77bf215546Sopenharmony_ci return ret; 78bf215546Sopenharmony_ci} 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_cistatic void 81bf215546Sopenharmony_cistw_pipe_blit(struct pipe_context *pipe, 82bf215546Sopenharmony_ci struct pipe_resource *dst, 83bf215546Sopenharmony_ci struct pipe_resource *src) 84bf215546Sopenharmony_ci{ 85bf215546Sopenharmony_ci struct pipe_blit_info blit; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci if (!dst || !src) 88bf215546Sopenharmony_ci return; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci /* From the GL spec, version 4.2, section 4.1.11 (Additional Multisample 91bf215546Sopenharmony_ci * Fragment Operations): 92bf215546Sopenharmony_ci * 93bf215546Sopenharmony_ci * If a framebuffer object is not bound, after all operations have 94bf215546Sopenharmony_ci * been completed on the multisample buffer, the sample values for 95bf215546Sopenharmony_ci * each color in the multisample buffer are combined to produce a 96bf215546Sopenharmony_ci * single color value, and that value is written into the 97bf215546Sopenharmony_ci * corresponding color buffers selected by DrawBuffer or 98bf215546Sopenharmony_ci * DrawBuffers. An implementation may defer the writing of the color 99bf215546Sopenharmony_ci * buffers until a later time, but the state of the framebuffer must 100bf215546Sopenharmony_ci * behave as if the color buffers were updated as each fragment was 101bf215546Sopenharmony_ci * processed. The method of combination is not specified. If the 102bf215546Sopenharmony_ci * framebuffer contains sRGB values, then it is recommended that the 103bf215546Sopenharmony_ci * an average of sample values is computed in a linearized space, as 104bf215546Sopenharmony_ci * for blending (see section 4.1.7). 105bf215546Sopenharmony_ci * 106bf215546Sopenharmony_ci * In other words, to do a resolve operation in a linear space, we have 107bf215546Sopenharmony_ci * to set sRGB formats if the original resources were sRGB, so don't use 108bf215546Sopenharmony_ci * util_format_linear. 109bf215546Sopenharmony_ci */ 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci memset(&blit, 0, sizeof(blit)); 112bf215546Sopenharmony_ci blit.dst.resource = dst; 113bf215546Sopenharmony_ci blit.dst.box.width = dst->width0; 114bf215546Sopenharmony_ci blit.dst.box.height = dst->height0; 115bf215546Sopenharmony_ci blit.dst.box.depth = 1; 116bf215546Sopenharmony_ci blit.dst.format = dst->format; 117bf215546Sopenharmony_ci blit.src.resource = src; 118bf215546Sopenharmony_ci blit.src.box.width = src->width0; 119bf215546Sopenharmony_ci blit.src.box.height = src->height0; 120bf215546Sopenharmony_ci blit.src.box.depth = 1; 121bf215546Sopenharmony_ci blit.src.format = src->format; 122bf215546Sopenharmony_ci blit.mask = PIPE_MASK_RGBA; 123bf215546Sopenharmony_ci blit.filter = PIPE_TEX_FILTER_NEAREST; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci pipe->blit(pipe, &blit); 126bf215546Sopenharmony_ci} 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci#ifdef GALLIUM_ZINK 129bf215546Sopenharmony_cistatic void 130bf215546Sopenharmony_cistw_st_fill_private_loader_data(struct stw_st_framebuffer *stwfb, struct kopper_loader_info *out) 131bf215546Sopenharmony_ci{ 132bf215546Sopenharmony_ci out->win32.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; 133bf215546Sopenharmony_ci out->win32.pNext = NULL; 134bf215546Sopenharmony_ci out->win32.flags = 0; 135bf215546Sopenharmony_ci out->win32.hinstance = GetModuleHandle(NULL); 136bf215546Sopenharmony_ci out->win32.hwnd = stwfb->fb->hWnd; 137bf215546Sopenharmony_ci out->has_alpha = true; 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci#endif 140bf215546Sopenharmony_ci/** 141bf215546Sopenharmony_ci * Remove outdated textures and create the requested ones. 142bf215546Sopenharmony_ci */ 143bf215546Sopenharmony_cistatic void 144bf215546Sopenharmony_cistw_st_framebuffer_validate_locked(struct st_context_iface *stctx, 145bf215546Sopenharmony_ci struct st_framebuffer_iface *stfb, 146bf215546Sopenharmony_ci unsigned width, unsigned height, 147bf215546Sopenharmony_ci unsigned mask) 148bf215546Sopenharmony_ci{ 149bf215546Sopenharmony_ci struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 150bf215546Sopenharmony_ci struct pipe_resource templ; 151bf215546Sopenharmony_ci unsigned i; 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci memset(&templ, 0, sizeof(templ)); 154bf215546Sopenharmony_ci templ.target = PIPE_TEXTURE_2D; 155bf215546Sopenharmony_ci templ.width0 = width; 156bf215546Sopenharmony_ci templ.height0 = height; 157bf215546Sopenharmony_ci templ.depth0 = 1; 158bf215546Sopenharmony_ci templ.array_size = 1; 159bf215546Sopenharmony_ci templ.last_level = 0; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci /* As of now, the only stw_winsys_framebuffer implementation is 162bf215546Sopenharmony_ci * d3d12_wgl_framebuffer and it doesn't support front buffer 163bf215546Sopenharmony_ci * drawing. A fake front texture is needed to handle that scenario. 164bf215546Sopenharmony_ci * For MSAA, we just need to make sure that the back buffer also 165bf215546Sopenharmony_ci * exists, so we can blt to it during flush_frontbuffer. */ 166bf215546Sopenharmony_ci if (mask & ST_ATTACHMENT_FRONT_LEFT_MASK && 167bf215546Sopenharmony_ci stwfb->fb->winsys_framebuffer) { 168bf215546Sopenharmony_ci if (stwfb->stvis.samples <= 1) 169bf215546Sopenharmony_ci stwfb->needs_fake_front = true; 170bf215546Sopenharmony_ci else 171bf215546Sopenharmony_ci mask |= ST_ATTACHMENT_BACK_LEFT_MASK; 172bf215546Sopenharmony_ci } 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci /* remove outdated textures */ 175bf215546Sopenharmony_ci if (stwfb->texture_width != width || stwfb->texture_height != height) { 176bf215546Sopenharmony_ci for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 177bf215546Sopenharmony_ci pipe_resource_reference(&stwfb->msaa_textures[i], NULL); 178bf215546Sopenharmony_ci pipe_resource_reference(&stwfb->textures[i], NULL); 179bf215546Sopenharmony_ci } 180bf215546Sopenharmony_ci pipe_resource_reference(&stwfb->back_texture, NULL); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci if (stwfb->fb->winsys_framebuffer) { 183bf215546Sopenharmony_ci templ.nr_samples = templ.nr_storage_samples = 1; 184bf215546Sopenharmony_ci templ.format = stwfb->stvis.color_format; 185bf215546Sopenharmony_ci stwfb->fb->winsys_framebuffer->resize(stwfb->fb->winsys_framebuffer, stctx->pipe, &templ); 186bf215546Sopenharmony_ci } 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 190bf215546Sopenharmony_ci enum pipe_format format; 191bf215546Sopenharmony_ci unsigned bind; 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci /* the texture already exists or not requested */ 194bf215546Sopenharmony_ci if (stwfb->textures[i] || !(mask & (1 << i))) { 195bf215546Sopenharmony_ci /* remember the texture */ 196bf215546Sopenharmony_ci if (stwfb->textures[i]) 197bf215546Sopenharmony_ci mask |= (1 << i); 198bf215546Sopenharmony_ci continue; 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci switch (i) { 202bf215546Sopenharmony_ci case ST_ATTACHMENT_FRONT_LEFT: 203bf215546Sopenharmony_ci case ST_ATTACHMENT_BACK_LEFT: 204bf215546Sopenharmony_ci format = stwfb->stvis.color_format; 205bf215546Sopenharmony_ci bind = PIPE_BIND_DISPLAY_TARGET | 206bf215546Sopenharmony_ci PIPE_BIND_SAMPLER_VIEW | 207bf215546Sopenharmony_ci PIPE_BIND_RENDER_TARGET; 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci#ifdef GALLIUM_ZINK 210bf215546Sopenharmony_ci if (stw_dev->zink) { 211bf215546Sopenharmony_ci /* Covers the case where we have already created a drawable that 212bf215546Sopenharmony_ci * then got swapped and now we have to make a new back buffer. 213bf215546Sopenharmony_ci * For Zink, we just alias the front buffer in that case. 214bf215546Sopenharmony_ci */ 215bf215546Sopenharmony_ci if (i == ST_ATTACHMENT_BACK_LEFT && stwfb->textures[ST_ATTACHMENT_FRONT_LEFT]) 216bf215546Sopenharmony_ci bind &= ~PIPE_BIND_DISPLAY_TARGET; 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci#endif 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci break; 221bf215546Sopenharmony_ci case ST_ATTACHMENT_DEPTH_STENCIL: 222bf215546Sopenharmony_ci format = stwfb->stvis.depth_stencil_format; 223bf215546Sopenharmony_ci bind = PIPE_BIND_DEPTH_STENCIL; 224bf215546Sopenharmony_ci break; 225bf215546Sopenharmony_ci default: 226bf215546Sopenharmony_ci format = PIPE_FORMAT_NONE; 227bf215546Sopenharmony_ci break; 228bf215546Sopenharmony_ci } 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci if (format != PIPE_FORMAT_NONE) { 231bf215546Sopenharmony_ci templ.format = format; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci if (bind != PIPE_BIND_DEPTH_STENCIL && stwfb->stvis.samples > 1) { 234bf215546Sopenharmony_ci templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 235bf215546Sopenharmony_ci templ.nr_samples = templ.nr_storage_samples = 236bf215546Sopenharmony_ci stwfb->stvis.samples; 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci stwfb->msaa_textures[i] = 239bf215546Sopenharmony_ci stw_dev->screen->resource_create(stw_dev->screen, &templ); 240bf215546Sopenharmony_ci } 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci templ.bind = bind; 243bf215546Sopenharmony_ci templ.nr_samples = templ.nr_storage_samples = 1; 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci#ifdef GALLIUM_ZINK 246bf215546Sopenharmony_ci if (stw_dev->zink && 247bf215546Sopenharmony_ci i < ST_ATTACHMENT_DEPTH_STENCIL && 248bf215546Sopenharmony_ci stw_dev->screen->resource_create_drawable) { 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci struct kopper_loader_info loader_info; 251bf215546Sopenharmony_ci void *data; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci if (bind & PIPE_BIND_DISPLAY_TARGET) { 254bf215546Sopenharmony_ci stw_st_fill_private_loader_data(stwfb, &loader_info); 255bf215546Sopenharmony_ci data = &loader_info; 256bf215546Sopenharmony_ci } else 257bf215546Sopenharmony_ci data = stwfb->textures[ST_ATTACHMENT_FRONT_LEFT]; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci assert(data); 260bf215546Sopenharmony_ci stwfb->textures[i] = 261bf215546Sopenharmony_ci stw_dev->screen->resource_create_drawable(stw_dev->screen, 262bf215546Sopenharmony_ci &templ, 263bf215546Sopenharmony_ci data); 264bf215546Sopenharmony_ci } else { 265bf215546Sopenharmony_ci#endif 266bf215546Sopenharmony_ci if (stwfb->fb->winsys_framebuffer) 267bf215546Sopenharmony_ci stwfb->textures[i] = stwfb->fb->winsys_framebuffer->get_resource( 268bf215546Sopenharmony_ci stwfb->fb->winsys_framebuffer, i); 269bf215546Sopenharmony_ci else 270bf215546Sopenharmony_ci stwfb->textures[i] = 271bf215546Sopenharmony_ci stw_dev->screen->resource_create(stw_dev->screen, &templ); 272bf215546Sopenharmony_ci#ifdef GALLIUM_ZINK 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci#endif 275bf215546Sopenharmony_ci } 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci /* When a fake front buffer is needed for drawing, we use the back buffer 279bf215546Sopenharmony_ci * as it reduces the number of blits needed: 280bf215546Sopenharmony_ci * 281bf215546Sopenharmony_ci * - When flushing the front buffer, we only need to swap the real buffers 282bf215546Sopenharmony_ci * - When swapping buffers, we can safely overwrite the fake front buffer 283bf215546Sopenharmony_ci * as it is now invalid anyway. 284bf215546Sopenharmony_ci * 285bf215546Sopenharmony_ci * A new texture is created to store the back buffer content. 286bf215546Sopenharmony_ci */ 287bf215546Sopenharmony_ci if (stwfb->needs_fake_front) { 288bf215546Sopenharmony_ci if (!stwfb->back_texture) { 289bf215546Sopenharmony_ci templ.format = stwfb->stvis.color_format; 290bf215546Sopenharmony_ci templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 291bf215546Sopenharmony_ci templ.nr_samples = templ.nr_storage_samples = 1; 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci stwfb->back_texture = 294bf215546Sopenharmony_ci stw_dev->screen->resource_create(stw_dev->screen, &templ); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci /* TODO Only blit if there is something currently drawn on the back buffer */ 297bf215546Sopenharmony_ci stw_pipe_blit(stctx->pipe, 298bf215546Sopenharmony_ci stwfb->back_texture, 299bf215546Sopenharmony_ci stwfb->textures[ST_ATTACHMENT_BACK_LEFT]); 300bf215546Sopenharmony_ci } 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci /* Copying front texture content to fake front texture (back texture) */ 303bf215546Sopenharmony_ci stw_pipe_blit(stctx->pipe, 304bf215546Sopenharmony_ci stwfb->textures[ST_ATTACHMENT_BACK_LEFT], 305bf215546Sopenharmony_ci stwfb->textures[ST_ATTACHMENT_FRONT_LEFT]); 306bf215546Sopenharmony_ci } 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci stwfb->texture_width = width; 309bf215546Sopenharmony_ci stwfb->texture_height = height; 310bf215546Sopenharmony_ci stwfb->texture_mask = mask; 311bf215546Sopenharmony_ci} 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_cistatic bool 314bf215546Sopenharmony_cistw_st_framebuffer_validate(struct st_context_iface *stctx, 315bf215546Sopenharmony_ci struct st_framebuffer_iface *stfb, 316bf215546Sopenharmony_ci const enum st_attachment_type *statts, 317bf215546Sopenharmony_ci unsigned count, 318bf215546Sopenharmony_ci struct pipe_resource **out) 319bf215546Sopenharmony_ci{ 320bf215546Sopenharmony_ci struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 321bf215546Sopenharmony_ci unsigned statt_mask, i; 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci statt_mask = 0x0; 324bf215546Sopenharmony_ci for (i = 0; i < count; i++) 325bf215546Sopenharmony_ci statt_mask |= 1 << statts[i]; 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci stw_framebuffer_lock(stwfb->fb); 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci if (stwfb->fb->must_resize || stwfb->needs_fake_front || (statt_mask & ~stwfb->texture_mask)) { 330bf215546Sopenharmony_ci stw_st_framebuffer_validate_locked(stctx, &stwfb->base, 331bf215546Sopenharmony_ci stwfb->fb->width, stwfb->fb->height, statt_mask); 332bf215546Sopenharmony_ci stwfb->fb->must_resize = FALSE; 333bf215546Sopenharmony_ci } 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci struct pipe_resource **textures = 336bf215546Sopenharmony_ci stwfb->stvis.samples > 1 ? stwfb->msaa_textures 337bf215546Sopenharmony_ci : stwfb->textures; 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 340bf215546Sopenharmony_ci struct pipe_resource *texture = NULL; 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci if (stwfb->needs_fake_front) { 343bf215546Sopenharmony_ci if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) 344bf215546Sopenharmony_ci texture = textures[ST_ATTACHMENT_BACK_LEFT]; /* Fake front buffer */ 345bf215546Sopenharmony_ci else if (statts[i] == ST_ATTACHMENT_BACK_LEFT) 346bf215546Sopenharmony_ci texture = stwfb->back_texture; 347bf215546Sopenharmony_ci } else { 348bf215546Sopenharmony_ci texture = textures[statts[i]]; 349bf215546Sopenharmony_ci } 350bf215546Sopenharmony_ci pipe_resource_reference(&out[i], texture); 351bf215546Sopenharmony_ci } 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci stw_framebuffer_unlock(stwfb->fb); 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci return true; 356bf215546Sopenharmony_ci} 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_cistruct notify_before_flush_cb_args { 359bf215546Sopenharmony_ci struct st_context_iface *stctx; 360bf215546Sopenharmony_ci struct stw_st_framebuffer *stwfb; 361bf215546Sopenharmony_ci unsigned flags; 362bf215546Sopenharmony_ci}; 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_cistatic void 365bf215546Sopenharmony_cinotify_before_flush_cb(void* _args) 366bf215546Sopenharmony_ci{ 367bf215546Sopenharmony_ci struct notify_before_flush_cb_args *args = (struct notify_before_flush_cb_args *) _args; 368bf215546Sopenharmony_ci struct st_context_iface *st = args->stctx; 369bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci if (args->stwfb->stvis.samples > 1) { 372bf215546Sopenharmony_ci /* Resolve the MSAA back buffer. */ 373bf215546Sopenharmony_ci stw_pipe_blit(pipe, 374bf215546Sopenharmony_ci args->stwfb->textures[ST_ATTACHMENT_BACK_LEFT], 375bf215546Sopenharmony_ci args->stwfb->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci /* FRONT_LEFT is resolved in flush_frontbuffer. */ 378bf215546Sopenharmony_ci } else if (args->stwfb->back_texture) { 379bf215546Sopenharmony_ci /* Fake front texture is dirty ?? */ 380bf215546Sopenharmony_ci stw_pipe_blit(pipe, 381bf215546Sopenharmony_ci args->stwfb->textures[ST_ATTACHMENT_BACK_LEFT], 382bf215546Sopenharmony_ci args->stwfb->back_texture); 383bf215546Sopenharmony_ci } 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci if (args->stwfb->textures[ST_ATTACHMENT_BACK_LEFT]) 386bf215546Sopenharmony_ci pipe->flush_resource(pipe, args->stwfb->textures[ST_ATTACHMENT_BACK_LEFT]); 387bf215546Sopenharmony_ci} 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_civoid 390bf215546Sopenharmony_cistw_st_flush(struct st_context_iface *stctx, 391bf215546Sopenharmony_ci struct st_framebuffer_iface *stfb, 392bf215546Sopenharmony_ci unsigned flags) 393bf215546Sopenharmony_ci{ 394bf215546Sopenharmony_ci struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 395bf215546Sopenharmony_ci struct notify_before_flush_cb_args args; 396bf215546Sopenharmony_ci struct pipe_fence_handle **pfence = NULL; 397bf215546Sopenharmony_ci struct pipe_fence_handle *fence = NULL; 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci args.stctx = stctx; 400bf215546Sopenharmony_ci args.stwfb = stwfb; 401bf215546Sopenharmony_ci args.flags = flags; 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci if (flags & ST_FLUSH_END_OF_FRAME && !stwfb->fb->winsys_framebuffer) 404bf215546Sopenharmony_ci flags |= ST_FLUSH_WAIT; 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci if (flags & ST_FLUSH_WAIT) 407bf215546Sopenharmony_ci pfence = &fence; 408bf215546Sopenharmony_ci stctx->flush(stctx, flags, pfence, notify_before_flush_cb, &args); 409bf215546Sopenharmony_ci} 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci/** 412bf215546Sopenharmony_ci * Present an attachment of the framebuffer. 413bf215546Sopenharmony_ci */ 414bf215546Sopenharmony_cistatic bool 415bf215546Sopenharmony_cistw_st_framebuffer_present_locked(HDC hdc, 416bf215546Sopenharmony_ci struct st_context_iface *stctx, 417bf215546Sopenharmony_ci struct st_framebuffer_iface *stfb, 418bf215546Sopenharmony_ci enum st_attachment_type statt) 419bf215546Sopenharmony_ci{ 420bf215546Sopenharmony_ci struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 421bf215546Sopenharmony_ci struct pipe_resource *resource; 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci assert(stw_own_mutex(&stwfb->fb->mutex)); 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ci resource = stwfb->textures[statt]; 426bf215546Sopenharmony_ci if (resource) { 427bf215546Sopenharmony_ci stw_framebuffer_present_locked(hdc, stwfb->fb, resource); 428bf215546Sopenharmony_ci } 429bf215546Sopenharmony_ci else { 430bf215546Sopenharmony_ci stw_framebuffer_unlock(stwfb->fb); 431bf215546Sopenharmony_ci } 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci assert(!stw_own_mutex(&stwfb->fb->mutex)); 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci return true; 436bf215546Sopenharmony_ci} 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_cistatic bool 439bf215546Sopenharmony_cistw_st_framebuffer_flush_front(struct st_context_iface *stctx, 440bf215546Sopenharmony_ci struct st_framebuffer_iface *stfb, 441bf215546Sopenharmony_ci enum st_attachment_type statt) 442bf215546Sopenharmony_ci{ 443bf215546Sopenharmony_ci struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 444bf215546Sopenharmony_ci struct pipe_context *pipe = stctx->pipe; 445bf215546Sopenharmony_ci bool ret; 446bf215546Sopenharmony_ci HDC hDC; 447bf215546Sopenharmony_ci bool need_swap_textures = false; 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ci if (statt != ST_ATTACHMENT_FRONT_LEFT) 450bf215546Sopenharmony_ci return false; 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci stw_framebuffer_lock(stwfb->fb); 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci /* Resolve the front buffer. */ 455bf215546Sopenharmony_ci if (stwfb->stvis.samples > 1) { 456bf215546Sopenharmony_ci enum st_attachment_type blit_target = statt; 457bf215546Sopenharmony_ci if (stwfb->fb->winsys_framebuffer) { 458bf215546Sopenharmony_ci blit_target = ST_ATTACHMENT_BACK_LEFT; 459bf215546Sopenharmony_ci need_swap_textures = true; 460bf215546Sopenharmony_ci } 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci stw_pipe_blit(pipe, stwfb->textures[blit_target], 463bf215546Sopenharmony_ci stwfb->msaa_textures[statt]); 464bf215546Sopenharmony_ci } else if (stwfb->needs_fake_front) { 465bf215546Sopenharmony_ci /* fake front texture is now invalid */ 466bf215546Sopenharmony_ci p_atomic_inc(&stwfb->base.stamp); 467bf215546Sopenharmony_ci need_swap_textures = true; 468bf215546Sopenharmony_ci } 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci if (need_swap_textures) { 471bf215546Sopenharmony_ci struct pipe_resource *ptex = stwfb->textures[ST_ATTACHMENT_FRONT_LEFT]; 472bf215546Sopenharmony_ci stwfb->textures[ST_ATTACHMENT_FRONT_LEFT] = stwfb->textures[ST_ATTACHMENT_BACK_LEFT]; 473bf215546Sopenharmony_ci stwfb->textures[ST_ATTACHMENT_BACK_LEFT] = ptex; 474bf215546Sopenharmony_ci } 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci if (stwfb->textures[statt]) 477bf215546Sopenharmony_ci pipe->flush_resource(pipe, stwfb->textures[statt]); 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci pipe->flush(pipe, NULL, 0); 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci /* We must not cache HDCs anywhere, as they can be invalidated by the 482bf215546Sopenharmony_ci * application, or screen resolution changes. */ 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci hDC = GetDC(stwfb->fb->hWnd); 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci ret = stw_st_framebuffer_present_locked(hDC, stctx, &stwfb->base, statt); 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci ReleaseDC(stwfb->fb->hWnd, hDC); 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci return ret; 491bf215546Sopenharmony_ci} 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci/** 494bf215546Sopenharmony_ci * Create a framebuffer interface. 495bf215546Sopenharmony_ci */ 496bf215546Sopenharmony_cistruct st_framebuffer_iface * 497bf215546Sopenharmony_cistw_st_create_framebuffer(struct stw_framebuffer *fb) 498bf215546Sopenharmony_ci{ 499bf215546Sopenharmony_ci struct stw_st_framebuffer *stwfb; 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_ci stwfb = CALLOC_STRUCT(stw_st_framebuffer); 502bf215546Sopenharmony_ci if (!stwfb) 503bf215546Sopenharmony_ci return NULL; 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci stwfb->fb = fb; 506bf215546Sopenharmony_ci stwfb->stvis = fb->pfi->stvis; 507bf215546Sopenharmony_ci stwfb->base.ID = p_atomic_inc_return(&stwfb_ID); 508bf215546Sopenharmony_ci stwfb->base.state_manager = stw_dev->smapi; 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci stwfb->base.visual = &stwfb->stvis; 511bf215546Sopenharmony_ci p_atomic_set(&stwfb->base.stamp, 1); 512bf215546Sopenharmony_ci stwfb->base.flush_front = stw_st_framebuffer_flush_front; 513bf215546Sopenharmony_ci stwfb->base.validate = stw_st_framebuffer_validate; 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_ci return &stwfb->base; 516bf215546Sopenharmony_ci} 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci/** 519bf215546Sopenharmony_ci * Destroy a framebuffer interface. 520bf215546Sopenharmony_ci */ 521bf215546Sopenharmony_civoid 522bf215546Sopenharmony_cistw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb) 523bf215546Sopenharmony_ci{ 524bf215546Sopenharmony_ci struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 525bf215546Sopenharmony_ci int i; 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 528bf215546Sopenharmony_ci pipe_resource_reference(&stwfb->msaa_textures[i], NULL); 529bf215546Sopenharmony_ci pipe_resource_reference(&stwfb->textures[i], NULL); 530bf215546Sopenharmony_ci } 531bf215546Sopenharmony_ci pipe_resource_reference(&stwfb->back_texture, NULL); 532bf215546Sopenharmony_ci 533bf215546Sopenharmony_ci /* Notify the st manager that the framebuffer interface is no 534bf215546Sopenharmony_ci * longer valid. 535bf215546Sopenharmony_ci */ 536bf215546Sopenharmony_ci stw_dev->stapi->destroy_drawable(stw_dev->stapi, &stwfb->base); 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci FREE(stwfb); 539bf215546Sopenharmony_ci} 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci/** 542bf215546Sopenharmony_ci * Swap the buffers of the given framebuffer. 543bf215546Sopenharmony_ci */ 544bf215546Sopenharmony_cibool 545bf215546Sopenharmony_cistw_st_swap_framebuffer_locked(HDC hdc, struct st_context_iface *stctx, 546bf215546Sopenharmony_ci struct st_framebuffer_iface *stfb) 547bf215546Sopenharmony_ci{ 548bf215546Sopenharmony_ci struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 549bf215546Sopenharmony_ci unsigned front = ST_ATTACHMENT_FRONT_LEFT, back = ST_ATTACHMENT_BACK_LEFT; 550bf215546Sopenharmony_ci struct pipe_resource *ptex; 551bf215546Sopenharmony_ci unsigned mask; 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci /* swap the textures */ 554bf215546Sopenharmony_ci ptex = stwfb->textures[front]; 555bf215546Sopenharmony_ci stwfb->textures[front] = stwfb->textures[back]; 556bf215546Sopenharmony_ci stwfb->textures[back] = ptex; 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci /* swap msaa_textures */ 559bf215546Sopenharmony_ci ptex = stwfb->msaa_textures[front]; 560bf215546Sopenharmony_ci stwfb->msaa_textures[front] = stwfb->msaa_textures[back]; 561bf215546Sopenharmony_ci stwfb->msaa_textures[back] = ptex; 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci /* Fake front texture is now dirty */ 565bf215546Sopenharmony_ci if (stwfb->needs_fake_front) 566bf215546Sopenharmony_ci p_atomic_inc(&stwfb->base.stamp); 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_ci /* convert to mask */ 569bf215546Sopenharmony_ci front = 1 << front; 570bf215546Sopenharmony_ci back = 1 << back; 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci /* swap the bits in mask */ 573bf215546Sopenharmony_ci mask = stwfb->texture_mask & ~(front | back); 574bf215546Sopenharmony_ci if (stwfb->texture_mask & front) 575bf215546Sopenharmony_ci mask |= back; 576bf215546Sopenharmony_ci if (stwfb->texture_mask & back) 577bf215546Sopenharmony_ci mask |= front; 578bf215546Sopenharmony_ci stwfb->texture_mask = mask; 579bf215546Sopenharmony_ci 580bf215546Sopenharmony_ci front = ST_ATTACHMENT_FRONT_LEFT; 581bf215546Sopenharmony_ci return stw_st_framebuffer_present_locked(hdc, stctx, &stwfb->base, front); 582bf215546Sopenharmony_ci} 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci/** 586bf215546Sopenharmony_ci * Return the pipe_resource that correspond to given buffer. 587bf215546Sopenharmony_ci */ 588bf215546Sopenharmony_cistruct pipe_resource * 589bf215546Sopenharmony_cistw_get_framebuffer_resource(struct st_framebuffer_iface *stfb, 590bf215546Sopenharmony_ci enum st_attachment_type att) 591bf215546Sopenharmony_ci{ 592bf215546Sopenharmony_ci struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); 593bf215546Sopenharmony_ci return stwfb->textures[att]; 594bf215546Sopenharmony_ci} 595bf215546Sopenharmony_ci 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_ci/** 598bf215546Sopenharmony_ci * Create an st_api of the gallium frontend. 599bf215546Sopenharmony_ci */ 600bf215546Sopenharmony_cistruct st_api * 601bf215546Sopenharmony_cistw_st_create_api(void) 602bf215546Sopenharmony_ci{ 603bf215546Sopenharmony_ci return st_gl_api_create(); 604bf215546Sopenharmony_ci} 605