1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (c) 2013 Brian Paul All Rights Reserved. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 12bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci/* 25bf215546Sopenharmony_ci * Off-Screen rendering into client memory. 26bf215546Sopenharmony_ci * OpenGL gallium frontend for softpipe and llvmpipe. 27bf215546Sopenharmony_ci * 28bf215546Sopenharmony_ci * Notes: 29bf215546Sopenharmony_ci * 30bf215546Sopenharmony_ci * If Gallium is built with LLVM support we use the llvmpipe driver. 31bf215546Sopenharmony_ci * Otherwise we use softpipe. The GALLIUM_DRIVER environment variable 32bf215546Sopenharmony_ci * may be set to "softpipe" or "llvmpipe" to override. 33bf215546Sopenharmony_ci * 34bf215546Sopenharmony_ci * With softpipe we could render directly into the user's buffer by using a 35bf215546Sopenharmony_ci * display target resource. However, softpipe doesn't support "upside-down" 36bf215546Sopenharmony_ci * rendering which would be needed for the OSMESA_Y_UP=TRUE case. 37bf215546Sopenharmony_ci * 38bf215546Sopenharmony_ci * With llvmpipe we could only render directly into the user's buffer when its 39bf215546Sopenharmony_ci * width and height is a multiple of the tile size (64 pixels). 40bf215546Sopenharmony_ci * 41bf215546Sopenharmony_ci * Because of these constraints we always render into ordinary resources then 42bf215546Sopenharmony_ci * copy the results to the user's buffer in the flush_front() function which 43bf215546Sopenharmony_ci * is called when the app calls glFlush/Finish. 44bf215546Sopenharmony_ci * 45bf215546Sopenharmony_ci * In general, the OSMesa interface is pretty ugly and not a good match 46bf215546Sopenharmony_ci * for Gallium. But we're interested in doing the best we can to preserve 47bf215546Sopenharmony_ci * application portability. With a little work we could come up with a 48bf215546Sopenharmony_ci * much nicer, new off-screen Gallium interface... 49bf215546Sopenharmony_ci */ 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci#include <stdio.h> 53bf215546Sopenharmony_ci#include <c11/threads.h> 54bf215546Sopenharmony_ci#include "GL/osmesa.h" 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci#include "glapi/glapi.h" /* for OSMesaGetProcAddress below */ 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci#include "pipe/p_context.h" 59bf215546Sopenharmony_ci#include "pipe/p_screen.h" 60bf215546Sopenharmony_ci#include "pipe/p_state.h" 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci#include "util/u_atomic.h" 63bf215546Sopenharmony_ci#include "util/u_box.h" 64bf215546Sopenharmony_ci#include "util/u_debug.h" 65bf215546Sopenharmony_ci#include "util/format/u_format.h" 66bf215546Sopenharmony_ci#include "util/u_inlines.h" 67bf215546Sopenharmony_ci#include "util/u_memory.h" 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci#include "postprocess/filters.h" 70bf215546Sopenharmony_ci#include "postprocess/postprocess.h" 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci#include "frontend/api.h" 73bf215546Sopenharmony_ci#include "state_tracker/st_gl_api.h" 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ciextern struct pipe_screen * 78bf215546Sopenharmony_ciosmesa_create_screen(void); 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_cistruct osmesa_buffer 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci struct st_framebuffer_iface *stfb; 85bf215546Sopenharmony_ci struct st_visual visual; 86bf215546Sopenharmony_ci unsigned width, height; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci void *map; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci struct osmesa_buffer *next; /**< next in linked list */ 93bf215546Sopenharmony_ci}; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_cistruct osmesa_context 97bf215546Sopenharmony_ci{ 98bf215546Sopenharmony_ci struct st_context_iface *stctx; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci boolean ever_used; /*< Has this context ever been current? */ 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci struct osmesa_buffer *current_buffer; 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci /* Storage for depth/stencil, if the user has requested access. The backing 105bf215546Sopenharmony_ci * driver always has its own storage for the actual depth/stencil, which we 106bf215546Sopenharmony_ci * have to transfer in and out. 107bf215546Sopenharmony_ci */ 108bf215546Sopenharmony_ci void *zs; 109bf215546Sopenharmony_ci unsigned zs_stride; 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci enum pipe_format depth_stencil_format, accum_format; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci GLenum format; /*< User-specified context format */ 114bf215546Sopenharmony_ci GLenum type; /*< Buffer's data type */ 115bf215546Sopenharmony_ci GLint user_row_length; /*< user-specified number of pixels per row */ 116bf215546Sopenharmony_ci GLboolean y_up; /*< TRUE -> Y increases upward */ 117bf215546Sopenharmony_ci /*< FALSE -> Y increases downward */ 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci /** Which postprocessing filters are enabled. */ 120bf215546Sopenharmony_ci unsigned pp_enabled[PP_FILTERS]; 121bf215546Sopenharmony_ci struct pp_queue_t *pp; 122bf215546Sopenharmony_ci}; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci/** 125bf215546Sopenharmony_ci * Called from the ST manager. 126bf215546Sopenharmony_ci */ 127bf215546Sopenharmony_cistatic int 128bf215546Sopenharmony_ciosmesa_st_get_param(struct st_manager *smapi, enum st_manager_param param) 129bf215546Sopenharmony_ci{ 130bf215546Sopenharmony_ci /* no-op */ 131bf215546Sopenharmony_ci return 0; 132bf215546Sopenharmony_ci} 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_cistatic struct st_manager *stmgr = NULL; 135bf215546Sopenharmony_cistatic struct st_api *stapi = NULL; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_cistatic void 138bf215546Sopenharmony_cidestroy_st_manager(void) 139bf215546Sopenharmony_ci{ 140bf215546Sopenharmony_ci if (stmgr) { 141bf215546Sopenharmony_ci if (stmgr->screen) 142bf215546Sopenharmony_ci stmgr->screen->destroy(stmgr->screen); 143bf215546Sopenharmony_ci FREE(stmgr); 144bf215546Sopenharmony_ci } 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci if (stapi && stapi->destroy) { 147bf215546Sopenharmony_ci stapi->destroy(stapi); 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci} 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_cistatic void 152bf215546Sopenharmony_cicreate_st_manager(void) 153bf215546Sopenharmony_ci{ 154bf215546Sopenharmony_ci if (atexit(destroy_st_manager) != 0) 155bf215546Sopenharmony_ci return; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci stmgr = CALLOC_STRUCT(st_manager); 158bf215546Sopenharmony_ci if (stmgr) { 159bf215546Sopenharmony_ci stmgr->screen = osmesa_create_screen(); 160bf215546Sopenharmony_ci stmgr->get_param = osmesa_st_get_param; 161bf215546Sopenharmony_ci stmgr->get_egl_image = NULL; 162bf215546Sopenharmony_ci } 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci stapi = st_gl_api_create(); 165bf215546Sopenharmony_ci} 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci/** 168bf215546Sopenharmony_ci * Create/return a singleton st_manager object. 169bf215546Sopenharmony_ci */ 170bf215546Sopenharmony_cistatic struct st_manager * 171bf215546Sopenharmony_ciget_st_manager(void) 172bf215546Sopenharmony_ci{ 173bf215546Sopenharmony_ci static once_flag create_once_flag = ONCE_FLAG_INIT; 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci call_once(&create_once_flag, create_st_manager); 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci return stmgr; 178bf215546Sopenharmony_ci} 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci/** 181bf215546Sopenharmony_ci * Create/return singleton st_api object. 182bf215546Sopenharmony_ci */ 183bf215546Sopenharmony_cistatic struct st_api * 184bf215546Sopenharmony_ciget_st_api(void) 185bf215546Sopenharmony_ci{ 186bf215546Sopenharmony_ci get_st_manager(); 187bf215546Sopenharmony_ci return stapi; 188bf215546Sopenharmony_ci} 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci/* Reads the color or depth buffer from the backing context to either the user storage 191bf215546Sopenharmony_ci * (color buffer) or our temporary (z/s) 192bf215546Sopenharmony_ci */ 193bf215546Sopenharmony_cistatic void 194bf215546Sopenharmony_ciosmesa_read_buffer(OSMesaContext osmesa, struct pipe_resource *res, void *dst, 195bf215546Sopenharmony_ci int dst_stride, bool y_up) 196bf215546Sopenharmony_ci{ 197bf215546Sopenharmony_ci struct pipe_context *pipe = osmesa->stctx->pipe; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci struct pipe_box box; 200bf215546Sopenharmony_ci u_box_2d(0, 0, res->width0, res->height0, &box); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci struct pipe_transfer *transfer = NULL; 203bf215546Sopenharmony_ci ubyte *src = pipe->texture_map(pipe, res, 0, PIPE_MAP_READ, &box, 204bf215546Sopenharmony_ci &transfer); 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci /* 207bf215546Sopenharmony_ci * Copy the color buffer from the resource to the user's buffer. 208bf215546Sopenharmony_ci */ 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci if (y_up) { 211bf215546Sopenharmony_ci /* need to flip image upside down */ 212bf215546Sopenharmony_ci dst = (ubyte *)dst + (res->height0 - 1) * dst_stride; 213bf215546Sopenharmony_ci dst_stride = -dst_stride; 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci unsigned bpp = util_format_get_blocksize(res->format); 217bf215546Sopenharmony_ci for (unsigned y = 0; y < res->height0; y++) 218bf215546Sopenharmony_ci { 219bf215546Sopenharmony_ci memcpy(dst, src, bpp * res->width0); 220bf215546Sopenharmony_ci dst = (ubyte *)dst + dst_stride; 221bf215546Sopenharmony_ci src += transfer->stride; 222bf215546Sopenharmony_ci } 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci pipe->texture_unmap(pipe, transfer); 225bf215546Sopenharmony_ci} 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci/** 229bf215546Sopenharmony_ci * Given an OSMESA_x format and a GL_y type, return the best 230bf215546Sopenharmony_ci * matching PIPE_FORMAT_z. 231bf215546Sopenharmony_ci * Note that we can't exactly match all user format/type combinations 232bf215546Sopenharmony_ci * with gallium formats. If we find this to be a problem, we can 233bf215546Sopenharmony_ci * implement more elaborate format/type conversion in the flush_front() 234bf215546Sopenharmony_ci * function. 235bf215546Sopenharmony_ci */ 236bf215546Sopenharmony_cistatic enum pipe_format 237bf215546Sopenharmony_ciosmesa_choose_format(GLenum format, GLenum type) 238bf215546Sopenharmony_ci{ 239bf215546Sopenharmony_ci switch (format) { 240bf215546Sopenharmony_ci case OSMESA_RGBA: 241bf215546Sopenharmony_ci if (type == GL_UNSIGNED_BYTE) { 242bf215546Sopenharmony_ci#if UTIL_ARCH_LITTLE_ENDIAN 243bf215546Sopenharmony_ci return PIPE_FORMAT_R8G8B8A8_UNORM; 244bf215546Sopenharmony_ci#else 245bf215546Sopenharmony_ci return PIPE_FORMAT_A8B8G8R8_UNORM; 246bf215546Sopenharmony_ci#endif 247bf215546Sopenharmony_ci } 248bf215546Sopenharmony_ci else if (type == GL_UNSIGNED_SHORT) { 249bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16B16A16_UNORM; 250bf215546Sopenharmony_ci } 251bf215546Sopenharmony_ci else if (type == GL_FLOAT) { 252bf215546Sopenharmony_ci return PIPE_FORMAT_R32G32B32A32_FLOAT; 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci else { 255bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci break; 258bf215546Sopenharmony_ci case OSMESA_BGRA: 259bf215546Sopenharmony_ci if (type == GL_UNSIGNED_BYTE) { 260bf215546Sopenharmony_ci#if UTIL_ARCH_LITTLE_ENDIAN 261bf215546Sopenharmony_ci return PIPE_FORMAT_B8G8R8A8_UNORM; 262bf215546Sopenharmony_ci#else 263bf215546Sopenharmony_ci return PIPE_FORMAT_A8R8G8B8_UNORM; 264bf215546Sopenharmony_ci#endif 265bf215546Sopenharmony_ci } 266bf215546Sopenharmony_ci else if (type == GL_UNSIGNED_SHORT) { 267bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16B16A16_UNORM; 268bf215546Sopenharmony_ci } 269bf215546Sopenharmony_ci else if (type == GL_FLOAT) { 270bf215546Sopenharmony_ci return PIPE_FORMAT_R32G32B32A32_FLOAT; 271bf215546Sopenharmony_ci } 272bf215546Sopenharmony_ci else { 273bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 274bf215546Sopenharmony_ci } 275bf215546Sopenharmony_ci break; 276bf215546Sopenharmony_ci case OSMESA_ARGB: 277bf215546Sopenharmony_ci if (type == GL_UNSIGNED_BYTE) { 278bf215546Sopenharmony_ci#if UTIL_ARCH_LITTLE_ENDIAN 279bf215546Sopenharmony_ci return PIPE_FORMAT_A8R8G8B8_UNORM; 280bf215546Sopenharmony_ci#else 281bf215546Sopenharmony_ci return PIPE_FORMAT_B8G8R8A8_UNORM; 282bf215546Sopenharmony_ci#endif 283bf215546Sopenharmony_ci } 284bf215546Sopenharmony_ci else if (type == GL_UNSIGNED_SHORT) { 285bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16B16A16_UNORM; 286bf215546Sopenharmony_ci } 287bf215546Sopenharmony_ci else if (type == GL_FLOAT) { 288bf215546Sopenharmony_ci return PIPE_FORMAT_R32G32B32A32_FLOAT; 289bf215546Sopenharmony_ci } 290bf215546Sopenharmony_ci else { 291bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 292bf215546Sopenharmony_ci } 293bf215546Sopenharmony_ci break; 294bf215546Sopenharmony_ci case OSMESA_RGB: 295bf215546Sopenharmony_ci if (type == GL_UNSIGNED_BYTE) { 296bf215546Sopenharmony_ci return PIPE_FORMAT_R8G8B8_UNORM; 297bf215546Sopenharmony_ci } 298bf215546Sopenharmony_ci else if (type == GL_UNSIGNED_SHORT) { 299bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16B16_UNORM; 300bf215546Sopenharmony_ci } 301bf215546Sopenharmony_ci else if (type == GL_FLOAT) { 302bf215546Sopenharmony_ci return PIPE_FORMAT_R32G32B32_FLOAT; 303bf215546Sopenharmony_ci } 304bf215546Sopenharmony_ci else { 305bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 306bf215546Sopenharmony_ci } 307bf215546Sopenharmony_ci break; 308bf215546Sopenharmony_ci case OSMESA_BGR: 309bf215546Sopenharmony_ci /* No gallium format for this one */ 310bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 311bf215546Sopenharmony_ci case OSMESA_RGB_565: 312bf215546Sopenharmony_ci if (type != GL_UNSIGNED_SHORT_5_6_5) 313bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 314bf215546Sopenharmony_ci return PIPE_FORMAT_B5G6R5_UNORM; 315bf215546Sopenharmony_ci default: 316bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci} 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci/** 322bf215546Sopenharmony_ci * Initialize an st_visual object. 323bf215546Sopenharmony_ci */ 324bf215546Sopenharmony_cistatic void 325bf215546Sopenharmony_ciosmesa_init_st_visual(struct st_visual *vis, 326bf215546Sopenharmony_ci enum pipe_format color_format, 327bf215546Sopenharmony_ci enum pipe_format ds_format, 328bf215546Sopenharmony_ci enum pipe_format accum_format) 329bf215546Sopenharmony_ci{ 330bf215546Sopenharmony_ci vis->buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci if (ds_format != PIPE_FORMAT_NONE) 333bf215546Sopenharmony_ci vis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; 334bf215546Sopenharmony_ci if (accum_format != PIPE_FORMAT_NONE) 335bf215546Sopenharmony_ci vis->buffer_mask |= ST_ATTACHMENT_ACCUM; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci vis->color_format = color_format; 338bf215546Sopenharmony_ci vis->depth_stencil_format = ds_format; 339bf215546Sopenharmony_ci vis->accum_format = accum_format; 340bf215546Sopenharmony_ci vis->samples = 1; 341bf215546Sopenharmony_ci} 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci/** 345bf215546Sopenharmony_ci * Return the osmesa_buffer that corresponds to an st_framebuffer_iface. 346bf215546Sopenharmony_ci */ 347bf215546Sopenharmony_cistatic inline struct osmesa_buffer * 348bf215546Sopenharmony_cistfbi_to_osbuffer(struct st_framebuffer_iface *stfbi) 349bf215546Sopenharmony_ci{ 350bf215546Sopenharmony_ci return (struct osmesa_buffer *) stfbi->st_manager_private; 351bf215546Sopenharmony_ci} 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci/** 355bf215546Sopenharmony_ci * Called via glFlush/glFinish. This is where we copy the contents 356bf215546Sopenharmony_ci * of the driver's color buffer into the user-specified buffer. 357bf215546Sopenharmony_ci */ 358bf215546Sopenharmony_cistatic bool 359bf215546Sopenharmony_ciosmesa_st_framebuffer_flush_front(struct st_context_iface *stctx, 360bf215546Sopenharmony_ci struct st_framebuffer_iface *stfbi, 361bf215546Sopenharmony_ci enum st_attachment_type statt) 362bf215546Sopenharmony_ci{ 363bf215546Sopenharmony_ci OSMesaContext osmesa = OSMesaGetCurrentContext(); 364bf215546Sopenharmony_ci struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); 365bf215546Sopenharmony_ci struct pipe_resource *res = osbuffer->textures[statt]; 366bf215546Sopenharmony_ci unsigned bpp; 367bf215546Sopenharmony_ci int dst_stride; 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci if (statt != ST_ATTACHMENT_FRONT_LEFT) 370bf215546Sopenharmony_ci return false; 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci if (osmesa->pp) { 373bf215546Sopenharmony_ci struct pipe_resource *zsbuf = NULL; 374bf215546Sopenharmony_ci unsigned i; 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci /* Find the z/stencil buffer if there is one */ 377bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(osbuffer->textures); i++) { 378bf215546Sopenharmony_ci struct pipe_resource *res = osbuffer->textures[i]; 379bf215546Sopenharmony_ci if (res) { 380bf215546Sopenharmony_ci const struct util_format_description *desc = 381bf215546Sopenharmony_ci util_format_description(res->format); 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci if (util_format_has_depth(desc)) { 384bf215546Sopenharmony_ci zsbuf = res; 385bf215546Sopenharmony_ci break; 386bf215546Sopenharmony_ci } 387bf215546Sopenharmony_ci } 388bf215546Sopenharmony_ci } 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci /* run the postprocess stage(s) */ 391bf215546Sopenharmony_ci pp_run(osmesa->pp, res, res, zsbuf); 392bf215546Sopenharmony_ci } 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci /* Snapshot the color buffer to the user's buffer. */ 395bf215546Sopenharmony_ci bpp = util_format_get_blocksize(osbuffer->visual.color_format); 396bf215546Sopenharmony_ci if (osmesa->user_row_length) 397bf215546Sopenharmony_ci dst_stride = bpp * osmesa->user_row_length; 398bf215546Sopenharmony_ci else 399bf215546Sopenharmony_ci dst_stride = bpp * osbuffer->width; 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci osmesa_read_buffer(osmesa, res, osbuffer->map, dst_stride, osmesa->y_up); 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci /* If the user has requested the Z/S buffer, then snapshot that one too. */ 404bf215546Sopenharmony_ci if (osmesa->zs) { 405bf215546Sopenharmony_ci osmesa_read_buffer(osmesa, osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL], 406bf215546Sopenharmony_ci osmesa->zs, osmesa->zs_stride, true); 407bf215546Sopenharmony_ci } 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci return true; 410bf215546Sopenharmony_ci} 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci/** 414bf215546Sopenharmony_ci * Called by the st manager to validate the framebuffer (allocate 415bf215546Sopenharmony_ci * its resources). 416bf215546Sopenharmony_ci */ 417bf215546Sopenharmony_cistatic bool 418bf215546Sopenharmony_ciosmesa_st_framebuffer_validate(struct st_context_iface *stctx, 419bf215546Sopenharmony_ci struct st_framebuffer_iface *stfbi, 420bf215546Sopenharmony_ci const enum st_attachment_type *statts, 421bf215546Sopenharmony_ci unsigned count, 422bf215546Sopenharmony_ci struct pipe_resource **out) 423bf215546Sopenharmony_ci{ 424bf215546Sopenharmony_ci struct pipe_screen *screen = get_st_manager()->screen; 425bf215546Sopenharmony_ci enum st_attachment_type i; 426bf215546Sopenharmony_ci struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); 427bf215546Sopenharmony_ci struct pipe_resource templat; 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci memset(&templat, 0, sizeof(templat)); 430bf215546Sopenharmony_ci templat.target = PIPE_TEXTURE_RECT; 431bf215546Sopenharmony_ci templat.format = 0; /* setup below */ 432bf215546Sopenharmony_ci templat.last_level = 0; 433bf215546Sopenharmony_ci templat.width0 = osbuffer->width; 434bf215546Sopenharmony_ci templat.height0 = osbuffer->height; 435bf215546Sopenharmony_ci templat.depth0 = 1; 436bf215546Sopenharmony_ci templat.array_size = 1; 437bf215546Sopenharmony_ci templat.usage = PIPE_USAGE_DEFAULT; 438bf215546Sopenharmony_ci templat.bind = 0; /* setup below */ 439bf215546Sopenharmony_ci templat.flags = 0; 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 442bf215546Sopenharmony_ci enum pipe_format format = PIPE_FORMAT_NONE; 443bf215546Sopenharmony_ci unsigned bind = 0; 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci /* 446bf215546Sopenharmony_ci * At this time, we really only need to handle the front-left color 447bf215546Sopenharmony_ci * attachment, since that's all we specified for the visual in 448bf215546Sopenharmony_ci * osmesa_init_st_visual(). 449bf215546Sopenharmony_ci */ 450bf215546Sopenharmony_ci if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) { 451bf215546Sopenharmony_ci format = osbuffer->visual.color_format; 452bf215546Sopenharmony_ci bind = PIPE_BIND_RENDER_TARGET; 453bf215546Sopenharmony_ci } 454bf215546Sopenharmony_ci else if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { 455bf215546Sopenharmony_ci format = osbuffer->visual.depth_stencil_format; 456bf215546Sopenharmony_ci bind = PIPE_BIND_DEPTH_STENCIL; 457bf215546Sopenharmony_ci } 458bf215546Sopenharmony_ci else if (statts[i] == ST_ATTACHMENT_ACCUM) { 459bf215546Sopenharmony_ci format = osbuffer->visual.accum_format; 460bf215546Sopenharmony_ci bind = PIPE_BIND_RENDER_TARGET; 461bf215546Sopenharmony_ci } 462bf215546Sopenharmony_ci else { 463bf215546Sopenharmony_ci debug_warning("Unexpected attachment type in " 464bf215546Sopenharmony_ci "osmesa_st_framebuffer_validate()"); 465bf215546Sopenharmony_ci } 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci templat.format = format; 468bf215546Sopenharmony_ci templat.bind = bind; 469bf215546Sopenharmony_ci pipe_resource_reference(&out[i], NULL); 470bf215546Sopenharmony_ci out[i] = osbuffer->textures[statts[i]] = 471bf215546Sopenharmony_ci screen->resource_create(screen, &templat); 472bf215546Sopenharmony_ci } 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci return true; 475bf215546Sopenharmony_ci} 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_cistatic uint32_t osmesa_fb_ID = 0; 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_cistatic struct st_framebuffer_iface * 480bf215546Sopenharmony_ciosmesa_create_st_framebuffer(void) 481bf215546Sopenharmony_ci{ 482bf215546Sopenharmony_ci struct st_framebuffer_iface *stfbi = CALLOC_STRUCT(st_framebuffer_iface); 483bf215546Sopenharmony_ci if (stfbi) { 484bf215546Sopenharmony_ci stfbi->flush_front = osmesa_st_framebuffer_flush_front; 485bf215546Sopenharmony_ci stfbi->validate = osmesa_st_framebuffer_validate; 486bf215546Sopenharmony_ci p_atomic_set(&stfbi->stamp, 1); 487bf215546Sopenharmony_ci stfbi->ID = p_atomic_inc_return(&osmesa_fb_ID); 488bf215546Sopenharmony_ci stfbi->state_manager = get_st_manager(); 489bf215546Sopenharmony_ci } 490bf215546Sopenharmony_ci return stfbi; 491bf215546Sopenharmony_ci} 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci 494bf215546Sopenharmony_ci/** 495bf215546Sopenharmony_ci * Create new buffer and add to linked list. 496bf215546Sopenharmony_ci */ 497bf215546Sopenharmony_cistatic struct osmesa_buffer * 498bf215546Sopenharmony_ciosmesa_create_buffer(enum pipe_format color_format, 499bf215546Sopenharmony_ci enum pipe_format ds_format, 500bf215546Sopenharmony_ci enum pipe_format accum_format) 501bf215546Sopenharmony_ci{ 502bf215546Sopenharmony_ci struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer); 503bf215546Sopenharmony_ci if (osbuffer) { 504bf215546Sopenharmony_ci osbuffer->stfb = osmesa_create_st_framebuffer(); 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_ci osbuffer->stfb->st_manager_private = osbuffer; 507bf215546Sopenharmony_ci osbuffer->stfb->visual = &osbuffer->visual; 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci osmesa_init_st_visual(&osbuffer->visual, color_format, 510bf215546Sopenharmony_ci ds_format, accum_format); 511bf215546Sopenharmony_ci } 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci return osbuffer; 514bf215546Sopenharmony_ci} 515bf215546Sopenharmony_ci 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_cistatic void 518bf215546Sopenharmony_ciosmesa_destroy_buffer(struct osmesa_buffer *osbuffer) 519bf215546Sopenharmony_ci{ 520bf215546Sopenharmony_ci /* 521bf215546Sopenharmony_ci * Notify the state manager that the associated framebuffer interface 522bf215546Sopenharmony_ci * is no longer valid. 523bf215546Sopenharmony_ci */ 524bf215546Sopenharmony_ci stapi->destroy_drawable(stapi, osbuffer->stfb); 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci FREE(osbuffer->stfb); 527bf215546Sopenharmony_ci FREE(osbuffer); 528bf215546Sopenharmony_ci} 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci/**********************************************************************/ 533bf215546Sopenharmony_ci/***** Public Functions *****/ 534bf215546Sopenharmony_ci/**********************************************************************/ 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci/** 538bf215546Sopenharmony_ci * Create an Off-Screen Mesa rendering context. The only attribute needed is 539bf215546Sopenharmony_ci * an RGBA vs Color-Index mode flag. 540bf215546Sopenharmony_ci * 541bf215546Sopenharmony_ci * Input: format - Must be GL_RGBA 542bf215546Sopenharmony_ci * sharelist - specifies another OSMesaContext with which to share 543bf215546Sopenharmony_ci * display lists. NULL indicates no sharing. 544bf215546Sopenharmony_ci * Return: an OSMesaContext or 0 if error 545bf215546Sopenharmony_ci */ 546bf215546Sopenharmony_ciGLAPI OSMesaContext GLAPIENTRY 547bf215546Sopenharmony_ciOSMesaCreateContext(GLenum format, OSMesaContext sharelist) 548bf215546Sopenharmony_ci{ 549bf215546Sopenharmony_ci return OSMesaCreateContextExt(format, 24, 8, 0, sharelist); 550bf215546Sopenharmony_ci} 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci/** 554bf215546Sopenharmony_ci * New in Mesa 3.5 555bf215546Sopenharmony_ci * 556bf215546Sopenharmony_ci * Create context and specify size of ancillary buffers. 557bf215546Sopenharmony_ci */ 558bf215546Sopenharmony_ciGLAPI OSMesaContext GLAPIENTRY 559bf215546Sopenharmony_ciOSMesaCreateContextExt(GLenum format, GLint depthBits, GLint stencilBits, 560bf215546Sopenharmony_ci GLint accumBits, OSMesaContext sharelist) 561bf215546Sopenharmony_ci{ 562bf215546Sopenharmony_ci int attribs[100], n = 0; 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci attribs[n++] = OSMESA_FORMAT; 565bf215546Sopenharmony_ci attribs[n++] = format; 566bf215546Sopenharmony_ci attribs[n++] = OSMESA_DEPTH_BITS; 567bf215546Sopenharmony_ci attribs[n++] = depthBits; 568bf215546Sopenharmony_ci attribs[n++] = OSMESA_STENCIL_BITS; 569bf215546Sopenharmony_ci attribs[n++] = stencilBits; 570bf215546Sopenharmony_ci attribs[n++] = OSMESA_ACCUM_BITS; 571bf215546Sopenharmony_ci attribs[n++] = accumBits; 572bf215546Sopenharmony_ci attribs[n++] = 0; 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci return OSMesaCreateContextAttribs(attribs, sharelist); 575bf215546Sopenharmony_ci} 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci/** 579bf215546Sopenharmony_ci * New in Mesa 11.2 580bf215546Sopenharmony_ci * 581bf215546Sopenharmony_ci * Create context with attribute list. 582bf215546Sopenharmony_ci */ 583bf215546Sopenharmony_ciGLAPI OSMesaContext GLAPIENTRY 584bf215546Sopenharmony_ciOSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist) 585bf215546Sopenharmony_ci{ 586bf215546Sopenharmony_ci OSMesaContext osmesa; 587bf215546Sopenharmony_ci struct st_context_iface *st_shared; 588bf215546Sopenharmony_ci enum st_context_error st_error = 0; 589bf215546Sopenharmony_ci struct st_context_attribs attribs; 590bf215546Sopenharmony_ci struct st_api *stapi = get_st_api(); 591bf215546Sopenharmony_ci GLenum format = GL_RGBA; 592bf215546Sopenharmony_ci int depthBits = 0, stencilBits = 0, accumBits = 0; 593bf215546Sopenharmony_ci int profile = OSMESA_COMPAT_PROFILE, version_major = 1, version_minor = 0; 594bf215546Sopenharmony_ci int i; 595bf215546Sopenharmony_ci 596bf215546Sopenharmony_ci if (sharelist) { 597bf215546Sopenharmony_ci st_shared = sharelist->stctx; 598bf215546Sopenharmony_ci } 599bf215546Sopenharmony_ci else { 600bf215546Sopenharmony_ci st_shared = NULL; 601bf215546Sopenharmony_ci } 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci for (i = 0; attribList[i]; i += 2) { 604bf215546Sopenharmony_ci switch (attribList[i]) { 605bf215546Sopenharmony_ci case OSMESA_FORMAT: 606bf215546Sopenharmony_ci format = attribList[i+1]; 607bf215546Sopenharmony_ci switch (format) { 608bf215546Sopenharmony_ci case OSMESA_COLOR_INDEX: 609bf215546Sopenharmony_ci case OSMESA_RGBA: 610bf215546Sopenharmony_ci case OSMESA_BGRA: 611bf215546Sopenharmony_ci case OSMESA_ARGB: 612bf215546Sopenharmony_ci case OSMESA_RGB: 613bf215546Sopenharmony_ci case OSMESA_BGR: 614bf215546Sopenharmony_ci case OSMESA_RGB_565: 615bf215546Sopenharmony_ci /* legal */ 616bf215546Sopenharmony_ci break; 617bf215546Sopenharmony_ci default: 618bf215546Sopenharmony_ci return NULL; 619bf215546Sopenharmony_ci } 620bf215546Sopenharmony_ci break; 621bf215546Sopenharmony_ci case OSMESA_DEPTH_BITS: 622bf215546Sopenharmony_ci depthBits = attribList[i+1]; 623bf215546Sopenharmony_ci if (depthBits < 0) 624bf215546Sopenharmony_ci return NULL; 625bf215546Sopenharmony_ci break; 626bf215546Sopenharmony_ci case OSMESA_STENCIL_BITS: 627bf215546Sopenharmony_ci stencilBits = attribList[i+1]; 628bf215546Sopenharmony_ci if (stencilBits < 0) 629bf215546Sopenharmony_ci return NULL; 630bf215546Sopenharmony_ci break; 631bf215546Sopenharmony_ci case OSMESA_ACCUM_BITS: 632bf215546Sopenharmony_ci accumBits = attribList[i+1]; 633bf215546Sopenharmony_ci if (accumBits < 0) 634bf215546Sopenharmony_ci return NULL; 635bf215546Sopenharmony_ci break; 636bf215546Sopenharmony_ci case OSMESA_PROFILE: 637bf215546Sopenharmony_ci profile = attribList[i+1]; 638bf215546Sopenharmony_ci if (profile != OSMESA_CORE_PROFILE && 639bf215546Sopenharmony_ci profile != OSMESA_COMPAT_PROFILE) 640bf215546Sopenharmony_ci return NULL; 641bf215546Sopenharmony_ci break; 642bf215546Sopenharmony_ci case OSMESA_CONTEXT_MAJOR_VERSION: 643bf215546Sopenharmony_ci version_major = attribList[i+1]; 644bf215546Sopenharmony_ci if (version_major < 1) 645bf215546Sopenharmony_ci return NULL; 646bf215546Sopenharmony_ci break; 647bf215546Sopenharmony_ci case OSMESA_CONTEXT_MINOR_VERSION: 648bf215546Sopenharmony_ci version_minor = attribList[i+1]; 649bf215546Sopenharmony_ci if (version_minor < 0) 650bf215546Sopenharmony_ci return NULL; 651bf215546Sopenharmony_ci break; 652bf215546Sopenharmony_ci case 0: 653bf215546Sopenharmony_ci /* end of list */ 654bf215546Sopenharmony_ci break; 655bf215546Sopenharmony_ci default: 656bf215546Sopenharmony_ci fprintf(stderr, "Bad attribute in OSMesaCreateContextAttribs()\n"); 657bf215546Sopenharmony_ci return NULL; 658bf215546Sopenharmony_ci } 659bf215546Sopenharmony_ci } 660bf215546Sopenharmony_ci 661bf215546Sopenharmony_ci osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); 662bf215546Sopenharmony_ci if (!osmesa) 663bf215546Sopenharmony_ci return NULL; 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_ci /* Choose depth/stencil/accum buffer formats */ 666bf215546Sopenharmony_ci if (accumBits > 0) { 667bf215546Sopenharmony_ci osmesa->accum_format = PIPE_FORMAT_R16G16B16A16_SNORM; 668bf215546Sopenharmony_ci } 669bf215546Sopenharmony_ci if (depthBits > 0 && stencilBits > 0) { 670bf215546Sopenharmony_ci osmesa->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT; 671bf215546Sopenharmony_ci } 672bf215546Sopenharmony_ci else if (stencilBits > 0) { 673bf215546Sopenharmony_ci osmesa->depth_stencil_format = PIPE_FORMAT_S8_UINT; 674bf215546Sopenharmony_ci } 675bf215546Sopenharmony_ci else if (depthBits >= 24) { 676bf215546Sopenharmony_ci osmesa->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM; 677bf215546Sopenharmony_ci } 678bf215546Sopenharmony_ci else if (depthBits >= 16) { 679bf215546Sopenharmony_ci osmesa->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; 680bf215546Sopenharmony_ci } 681bf215546Sopenharmony_ci 682bf215546Sopenharmony_ci /* 683bf215546Sopenharmony_ci * Create the rendering context 684bf215546Sopenharmony_ci */ 685bf215546Sopenharmony_ci memset(&attribs, 0, sizeof(attribs)); 686bf215546Sopenharmony_ci attribs.profile = (profile == OSMESA_CORE_PROFILE) 687bf215546Sopenharmony_ci ? ST_PROFILE_OPENGL_CORE : ST_PROFILE_DEFAULT; 688bf215546Sopenharmony_ci attribs.major = version_major; 689bf215546Sopenharmony_ci attribs.minor = version_minor; 690bf215546Sopenharmony_ci attribs.flags = 0; /* ST_CONTEXT_FLAG_x */ 691bf215546Sopenharmony_ci attribs.options.force_glsl_extensions_warn = FALSE; 692bf215546Sopenharmony_ci attribs.options.disable_blend_func_extended = FALSE; 693bf215546Sopenharmony_ci attribs.options.disable_glsl_line_continuations = FALSE; 694bf215546Sopenharmony_ci attribs.options.force_glsl_version = 0; 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci osmesa_init_st_visual(&attribs.visual, 697bf215546Sopenharmony_ci PIPE_FORMAT_NONE, 698bf215546Sopenharmony_ci osmesa->depth_stencil_format, 699bf215546Sopenharmony_ci osmesa->accum_format); 700bf215546Sopenharmony_ci 701bf215546Sopenharmony_ci osmesa->stctx = stapi->create_context(stapi, get_st_manager(), 702bf215546Sopenharmony_ci &attribs, &st_error, st_shared); 703bf215546Sopenharmony_ci if (!osmesa->stctx) { 704bf215546Sopenharmony_ci FREE(osmesa); 705bf215546Sopenharmony_ci return NULL; 706bf215546Sopenharmony_ci } 707bf215546Sopenharmony_ci 708bf215546Sopenharmony_ci osmesa->stctx->st_manager_private = osmesa; 709bf215546Sopenharmony_ci 710bf215546Sopenharmony_ci osmesa->format = format; 711bf215546Sopenharmony_ci osmesa->user_row_length = 0; 712bf215546Sopenharmony_ci osmesa->y_up = GL_TRUE; 713bf215546Sopenharmony_ci 714bf215546Sopenharmony_ci return osmesa; 715bf215546Sopenharmony_ci} 716bf215546Sopenharmony_ci 717bf215546Sopenharmony_ci 718bf215546Sopenharmony_ci 719bf215546Sopenharmony_ci/** 720bf215546Sopenharmony_ci * Destroy an Off-Screen Mesa rendering context. 721bf215546Sopenharmony_ci * 722bf215546Sopenharmony_ci * \param osmesa the context to destroy 723bf215546Sopenharmony_ci */ 724bf215546Sopenharmony_ciGLAPI void GLAPIENTRY 725bf215546Sopenharmony_ciOSMesaDestroyContext(OSMesaContext osmesa) 726bf215546Sopenharmony_ci{ 727bf215546Sopenharmony_ci if (osmesa) { 728bf215546Sopenharmony_ci pp_free(osmesa->pp); 729bf215546Sopenharmony_ci osmesa->stctx->destroy(osmesa->stctx); 730bf215546Sopenharmony_ci free(osmesa->zs); 731bf215546Sopenharmony_ci FREE(osmesa); 732bf215546Sopenharmony_ci } 733bf215546Sopenharmony_ci} 734bf215546Sopenharmony_ci 735bf215546Sopenharmony_ci 736bf215546Sopenharmony_ci/** 737bf215546Sopenharmony_ci * Bind an OSMesaContext to an image buffer. The image buffer is just a 738bf215546Sopenharmony_ci * block of memory which the client provides. Its size must be at least 739bf215546Sopenharmony_ci * as large as width*height*pixelSize. Its address should be a multiple 740bf215546Sopenharmony_ci * of 4 if using RGBA mode. 741bf215546Sopenharmony_ci * 742bf215546Sopenharmony_ci * By default, image data is stored in the order of glDrawPixels: row-major 743bf215546Sopenharmony_ci * order with the lower-left image pixel stored in the first array position 744bf215546Sopenharmony_ci * (ie. bottom-to-top). 745bf215546Sopenharmony_ci * 746bf215546Sopenharmony_ci * If the context's viewport hasn't been initialized yet, it will now be 747bf215546Sopenharmony_ci * initialized to (0,0,width,height). 748bf215546Sopenharmony_ci * 749bf215546Sopenharmony_ci * Input: osmesa - the rendering context 750bf215546Sopenharmony_ci * buffer - the image buffer memory 751bf215546Sopenharmony_ci * type - data type for pixel components 752bf215546Sopenharmony_ci * GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT 753bf215546Sopenharmony_ci * or GL_FLOAT. 754bf215546Sopenharmony_ci * width, height - size of image buffer in pixels, at least 1 755bf215546Sopenharmony_ci * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa, 756bf215546Sopenharmony_ci * invalid type, invalid size, etc. 757bf215546Sopenharmony_ci */ 758bf215546Sopenharmony_ciGLAPI GLboolean GLAPIENTRY 759bf215546Sopenharmony_ciOSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type, 760bf215546Sopenharmony_ci GLsizei width, GLsizei height) 761bf215546Sopenharmony_ci{ 762bf215546Sopenharmony_ci struct st_api *stapi = get_st_api(); 763bf215546Sopenharmony_ci enum pipe_format color_format; 764bf215546Sopenharmony_ci 765bf215546Sopenharmony_ci if (!osmesa && !buffer) { 766bf215546Sopenharmony_ci stapi->make_current(stapi, NULL, NULL, NULL); 767bf215546Sopenharmony_ci return GL_TRUE; 768bf215546Sopenharmony_ci } 769bf215546Sopenharmony_ci 770bf215546Sopenharmony_ci if (!osmesa || !buffer || width < 1 || height < 1) { 771bf215546Sopenharmony_ci return GL_FALSE; 772bf215546Sopenharmony_ci } 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_ci color_format = osmesa_choose_format(osmesa->format, type); 775bf215546Sopenharmony_ci if (color_format == PIPE_FORMAT_NONE) { 776bf215546Sopenharmony_ci fprintf(stderr, "OSMesaMakeCurrent(unsupported format/type)\n"); 777bf215546Sopenharmony_ci return GL_FALSE; 778bf215546Sopenharmony_ci } 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_ci /* See if we already have a buffer that uses these pixel formats */ 781bf215546Sopenharmony_ci if (osmesa->current_buffer && 782bf215546Sopenharmony_ci (osmesa->current_buffer->visual.color_format != color_format || 783bf215546Sopenharmony_ci osmesa->current_buffer->visual.depth_stencil_format != osmesa->depth_stencil_format || 784bf215546Sopenharmony_ci osmesa->current_buffer->visual.accum_format != osmesa->accum_format || 785bf215546Sopenharmony_ci osmesa->current_buffer->width != width || 786bf215546Sopenharmony_ci osmesa->current_buffer->height != height)) { 787bf215546Sopenharmony_ci osmesa_destroy_buffer(osmesa->current_buffer); 788bf215546Sopenharmony_ci osmesa->current_buffer = NULL; 789bf215546Sopenharmony_ci } 790bf215546Sopenharmony_ci 791bf215546Sopenharmony_ci if (!osmesa->current_buffer) { 792bf215546Sopenharmony_ci osmesa->current_buffer = osmesa_create_buffer(color_format, 793bf215546Sopenharmony_ci osmesa->depth_stencil_format, 794bf215546Sopenharmony_ci osmesa->accum_format); 795bf215546Sopenharmony_ci } 796bf215546Sopenharmony_ci 797bf215546Sopenharmony_ci struct osmesa_buffer *osbuffer = osmesa->current_buffer; 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci osbuffer->width = width; 800bf215546Sopenharmony_ci osbuffer->height = height; 801bf215546Sopenharmony_ci osbuffer->map = buffer; 802bf215546Sopenharmony_ci 803bf215546Sopenharmony_ci osmesa->type = type; 804bf215546Sopenharmony_ci 805bf215546Sopenharmony_ci stapi->make_current(stapi, osmesa->stctx, osbuffer->stfb, osbuffer->stfb); 806bf215546Sopenharmony_ci 807bf215546Sopenharmony_ci /* XXX: We should probably load the current color value into the buffer here 808bf215546Sopenharmony_ci * to match classic swrast behavior (context's fb starts with the contents of 809bf215546Sopenharmony_ci * your pixel buffer). 810bf215546Sopenharmony_ci */ 811bf215546Sopenharmony_ci 812bf215546Sopenharmony_ci if (!osmesa->ever_used) { 813bf215546Sopenharmony_ci /* one-time init, just postprocessing for now */ 814bf215546Sopenharmony_ci boolean any_pp_enabled = FALSE; 815bf215546Sopenharmony_ci unsigned i; 816bf215546Sopenharmony_ci 817bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(osmesa->pp_enabled); i++) { 818bf215546Sopenharmony_ci if (osmesa->pp_enabled[i]) { 819bf215546Sopenharmony_ci any_pp_enabled = TRUE; 820bf215546Sopenharmony_ci break; 821bf215546Sopenharmony_ci } 822bf215546Sopenharmony_ci } 823bf215546Sopenharmony_ci 824bf215546Sopenharmony_ci if (any_pp_enabled) { 825bf215546Sopenharmony_ci osmesa->pp = pp_init(osmesa->stctx->pipe, 826bf215546Sopenharmony_ci osmesa->pp_enabled, 827bf215546Sopenharmony_ci osmesa->stctx->cso_context, 828bf215546Sopenharmony_ci osmesa->stctx); 829bf215546Sopenharmony_ci 830bf215546Sopenharmony_ci pp_init_fbos(osmesa->pp, width, height); 831bf215546Sopenharmony_ci } 832bf215546Sopenharmony_ci 833bf215546Sopenharmony_ci osmesa->ever_used = TRUE; 834bf215546Sopenharmony_ci } 835bf215546Sopenharmony_ci 836bf215546Sopenharmony_ci return GL_TRUE; 837bf215546Sopenharmony_ci} 838bf215546Sopenharmony_ci 839bf215546Sopenharmony_ci 840bf215546Sopenharmony_ci 841bf215546Sopenharmony_ciGLAPI OSMesaContext GLAPIENTRY 842bf215546Sopenharmony_ciOSMesaGetCurrentContext(void) 843bf215546Sopenharmony_ci{ 844bf215546Sopenharmony_ci struct st_api *stapi = get_st_api(); 845bf215546Sopenharmony_ci struct st_context_iface *st = stapi->get_current(stapi); 846bf215546Sopenharmony_ci return st ? (OSMesaContext) st->st_manager_private : NULL; 847bf215546Sopenharmony_ci} 848bf215546Sopenharmony_ci 849bf215546Sopenharmony_ci 850bf215546Sopenharmony_ci 851bf215546Sopenharmony_ciGLAPI void GLAPIENTRY 852bf215546Sopenharmony_ciOSMesaPixelStore(GLint pname, GLint value) 853bf215546Sopenharmony_ci{ 854bf215546Sopenharmony_ci OSMesaContext osmesa = OSMesaGetCurrentContext(); 855bf215546Sopenharmony_ci 856bf215546Sopenharmony_ci switch (pname) { 857bf215546Sopenharmony_ci case OSMESA_ROW_LENGTH: 858bf215546Sopenharmony_ci osmesa->user_row_length = value; 859bf215546Sopenharmony_ci break; 860bf215546Sopenharmony_ci case OSMESA_Y_UP: 861bf215546Sopenharmony_ci osmesa->y_up = value ? GL_TRUE : GL_FALSE; 862bf215546Sopenharmony_ci break; 863bf215546Sopenharmony_ci default: 864bf215546Sopenharmony_ci fprintf(stderr, "Invalid pname in OSMesaPixelStore()\n"); 865bf215546Sopenharmony_ci return; 866bf215546Sopenharmony_ci } 867bf215546Sopenharmony_ci} 868bf215546Sopenharmony_ci 869bf215546Sopenharmony_ci 870bf215546Sopenharmony_ciGLAPI void GLAPIENTRY 871bf215546Sopenharmony_ciOSMesaGetIntegerv(GLint pname, GLint *value) 872bf215546Sopenharmony_ci{ 873bf215546Sopenharmony_ci OSMesaContext osmesa = OSMesaGetCurrentContext(); 874bf215546Sopenharmony_ci struct osmesa_buffer *osbuffer = osmesa ? osmesa->current_buffer : NULL; 875bf215546Sopenharmony_ci 876bf215546Sopenharmony_ci switch (pname) { 877bf215546Sopenharmony_ci case OSMESA_WIDTH: 878bf215546Sopenharmony_ci *value = osbuffer ? osbuffer->width : 0; 879bf215546Sopenharmony_ci return; 880bf215546Sopenharmony_ci case OSMESA_HEIGHT: 881bf215546Sopenharmony_ci *value = osbuffer ? osbuffer->height : 0; 882bf215546Sopenharmony_ci return; 883bf215546Sopenharmony_ci case OSMESA_FORMAT: 884bf215546Sopenharmony_ci *value = osmesa->format; 885bf215546Sopenharmony_ci return; 886bf215546Sopenharmony_ci case OSMESA_TYPE: 887bf215546Sopenharmony_ci /* current color buffer's data type */ 888bf215546Sopenharmony_ci *value = osmesa->type; 889bf215546Sopenharmony_ci return; 890bf215546Sopenharmony_ci case OSMESA_ROW_LENGTH: 891bf215546Sopenharmony_ci *value = osmesa->user_row_length; 892bf215546Sopenharmony_ci return; 893bf215546Sopenharmony_ci case OSMESA_Y_UP: 894bf215546Sopenharmony_ci *value = osmesa->y_up; 895bf215546Sopenharmony_ci return; 896bf215546Sopenharmony_ci case OSMESA_MAX_WIDTH: 897bf215546Sopenharmony_ci FALLTHROUGH; 898bf215546Sopenharmony_ci case OSMESA_MAX_HEIGHT: 899bf215546Sopenharmony_ci { 900bf215546Sopenharmony_ci struct pipe_screen *screen = get_st_manager()->screen; 901bf215546Sopenharmony_ci *value = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_SIZE); 902bf215546Sopenharmony_ci } 903bf215546Sopenharmony_ci return; 904bf215546Sopenharmony_ci default: 905bf215546Sopenharmony_ci fprintf(stderr, "Invalid pname in OSMesaGetIntegerv()\n"); 906bf215546Sopenharmony_ci return; 907bf215546Sopenharmony_ci } 908bf215546Sopenharmony_ci} 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci 911bf215546Sopenharmony_ci/** 912bf215546Sopenharmony_ci * Return information about the depth buffer associated with an OSMesa context. 913bf215546Sopenharmony_ci * Input: c - the OSMesa context 914bf215546Sopenharmony_ci * Output: width, height - size of buffer in pixels 915bf215546Sopenharmony_ci * bytesPerValue - bytes per depth value (2 or 4) 916bf215546Sopenharmony_ci * buffer - pointer to depth buffer values 917bf215546Sopenharmony_ci * Return: GL_TRUE or GL_FALSE to indicate success or failure. 918bf215546Sopenharmony_ci */ 919bf215546Sopenharmony_ciGLAPI GLboolean GLAPIENTRY 920bf215546Sopenharmony_ciOSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height, 921bf215546Sopenharmony_ci GLint *bytesPerValue, void **buffer) 922bf215546Sopenharmony_ci{ 923bf215546Sopenharmony_ci struct osmesa_buffer *osbuffer = c->current_buffer; 924bf215546Sopenharmony_ci struct pipe_resource *res = osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL]; 925bf215546Sopenharmony_ci 926bf215546Sopenharmony_ci if (!res) { 927bf215546Sopenharmony_ci *width = 0; 928bf215546Sopenharmony_ci *height = 0; 929bf215546Sopenharmony_ci *bytesPerValue = 0; 930bf215546Sopenharmony_ci *buffer = NULL; 931bf215546Sopenharmony_ci return GL_FALSE; 932bf215546Sopenharmony_ci } 933bf215546Sopenharmony_ci 934bf215546Sopenharmony_ci *width = res->width0; 935bf215546Sopenharmony_ci *height = res->height0; 936bf215546Sopenharmony_ci *bytesPerValue = util_format_get_blocksize(res->format); 937bf215546Sopenharmony_ci 938bf215546Sopenharmony_ci if (!c->zs) { 939bf215546Sopenharmony_ci c->zs_stride = *width * *bytesPerValue; 940bf215546Sopenharmony_ci c->zs = calloc(c->zs_stride, *height); 941bf215546Sopenharmony_ci if (!c->zs) 942bf215546Sopenharmony_ci return GL_FALSE; 943bf215546Sopenharmony_ci 944bf215546Sopenharmony_ci osmesa_read_buffer(c, res, c->zs, c->zs_stride, true); 945bf215546Sopenharmony_ci } 946bf215546Sopenharmony_ci 947bf215546Sopenharmony_ci *buffer = c->zs; 948bf215546Sopenharmony_ci 949bf215546Sopenharmony_ci return GL_TRUE; 950bf215546Sopenharmony_ci} 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_ci 953bf215546Sopenharmony_ci/** 954bf215546Sopenharmony_ci * Return the color buffer associated with an OSMesa context. 955bf215546Sopenharmony_ci * Input: c - the OSMesa context 956bf215546Sopenharmony_ci * Output: width, height - size of buffer in pixels 957bf215546Sopenharmony_ci * format - the pixel format (OSMESA_FORMAT) 958bf215546Sopenharmony_ci * buffer - pointer to color buffer values 959bf215546Sopenharmony_ci * Return: GL_TRUE or GL_FALSE to indicate success or failure. 960bf215546Sopenharmony_ci */ 961bf215546Sopenharmony_ciGLAPI GLboolean GLAPIENTRY 962bf215546Sopenharmony_ciOSMesaGetColorBuffer(OSMesaContext osmesa, GLint *width, 963bf215546Sopenharmony_ci GLint *height, GLint *format, void **buffer) 964bf215546Sopenharmony_ci{ 965bf215546Sopenharmony_ci struct osmesa_buffer *osbuffer = osmesa->current_buffer; 966bf215546Sopenharmony_ci 967bf215546Sopenharmony_ci if (osbuffer) { 968bf215546Sopenharmony_ci *width = osbuffer->width; 969bf215546Sopenharmony_ci *height = osbuffer->height; 970bf215546Sopenharmony_ci *format = osmesa->format; 971bf215546Sopenharmony_ci *buffer = osbuffer->map; 972bf215546Sopenharmony_ci return GL_TRUE; 973bf215546Sopenharmony_ci } 974bf215546Sopenharmony_ci else { 975bf215546Sopenharmony_ci *width = 0; 976bf215546Sopenharmony_ci *height = 0; 977bf215546Sopenharmony_ci *format = 0; 978bf215546Sopenharmony_ci *buffer = 0; 979bf215546Sopenharmony_ci return GL_FALSE; 980bf215546Sopenharmony_ci } 981bf215546Sopenharmony_ci} 982bf215546Sopenharmony_ci 983bf215546Sopenharmony_ci 984bf215546Sopenharmony_cistruct name_function 985bf215546Sopenharmony_ci{ 986bf215546Sopenharmony_ci const char *Name; 987bf215546Sopenharmony_ci OSMESAproc Function; 988bf215546Sopenharmony_ci}; 989bf215546Sopenharmony_ci 990bf215546Sopenharmony_cistatic struct name_function functions[] = { 991bf215546Sopenharmony_ci { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext }, 992bf215546Sopenharmony_ci { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt }, 993bf215546Sopenharmony_ci { "OSMesaCreateContextAttribs", (OSMESAproc) OSMesaCreateContextAttribs }, 994bf215546Sopenharmony_ci { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext }, 995bf215546Sopenharmony_ci { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent }, 996bf215546Sopenharmony_ci { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext }, 997bf215546Sopenharmony_ci { "OSMesaPixelStore", (OSMESAproc) OSMesaPixelStore }, 998bf215546Sopenharmony_ci { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv }, 999bf215546Sopenharmony_ci { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer }, 1000bf215546Sopenharmony_ci { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer }, 1001bf215546Sopenharmony_ci { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress }, 1002bf215546Sopenharmony_ci { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp }, 1003bf215546Sopenharmony_ci { "OSMesaPostprocess", (OSMESAproc) OSMesaPostprocess }, 1004bf215546Sopenharmony_ci { NULL, NULL } 1005bf215546Sopenharmony_ci}; 1006bf215546Sopenharmony_ci 1007bf215546Sopenharmony_ci 1008bf215546Sopenharmony_ciGLAPI OSMESAproc GLAPIENTRY 1009bf215546Sopenharmony_ciOSMesaGetProcAddress(const char *funcName) 1010bf215546Sopenharmony_ci{ 1011bf215546Sopenharmony_ci int i; 1012bf215546Sopenharmony_ci for (i = 0; functions[i].Name; i++) { 1013bf215546Sopenharmony_ci if (strcmp(functions[i].Name, funcName) == 0) 1014bf215546Sopenharmony_ci return functions[i].Function; 1015bf215546Sopenharmony_ci } 1016bf215546Sopenharmony_ci return _glapi_get_proc_address(funcName); 1017bf215546Sopenharmony_ci} 1018bf215546Sopenharmony_ci 1019bf215546Sopenharmony_ci 1020bf215546Sopenharmony_ciGLAPI void GLAPIENTRY 1021bf215546Sopenharmony_ciOSMesaColorClamp(GLboolean enable) 1022bf215546Sopenharmony_ci{ 1023bf215546Sopenharmony_ci extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp); 1024bf215546Sopenharmony_ci 1025bf215546Sopenharmony_ci _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, 1026bf215546Sopenharmony_ci enable ? GL_TRUE : GL_FIXED_ONLY_ARB); 1027bf215546Sopenharmony_ci} 1028bf215546Sopenharmony_ci 1029bf215546Sopenharmony_ci 1030bf215546Sopenharmony_ciGLAPI void GLAPIENTRY 1031bf215546Sopenharmony_ciOSMesaPostprocess(OSMesaContext osmesa, const char *filter, 1032bf215546Sopenharmony_ci unsigned enable_value) 1033bf215546Sopenharmony_ci{ 1034bf215546Sopenharmony_ci if (!osmesa->ever_used) { 1035bf215546Sopenharmony_ci /* We can only enable/disable postprocess filters before a context 1036bf215546Sopenharmony_ci * is made current for the first time. 1037bf215546Sopenharmony_ci */ 1038bf215546Sopenharmony_ci unsigned i; 1039bf215546Sopenharmony_ci 1040bf215546Sopenharmony_ci for (i = 0; i < PP_FILTERS; i++) { 1041bf215546Sopenharmony_ci if (strcmp(pp_filters[i].name, filter) == 0) { 1042bf215546Sopenharmony_ci osmesa->pp_enabled[i] = enable_value; 1043bf215546Sopenharmony_ci return; 1044bf215546Sopenharmony_ci } 1045bf215546Sopenharmony_ci } 1046bf215546Sopenharmony_ci debug_warning("OSMesaPostprocess(unknown filter)\n"); 1047bf215546Sopenharmony_ci } 1048bf215546Sopenharmony_ci else { 1049bf215546Sopenharmony_ci debug_warning("Calling OSMesaPostprocess() after OSMesaMakeCurrent()\n"); 1050bf215546Sopenharmony_ci } 1051bf215546Sopenharmony_ci} 1052