1848b8605Smrg/* 2848b8605Smrg * Copyright (c) 2013 Brian Paul All Rights Reserved. 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Software"), 6848b8605Smrg * to deal in the Software without restriction, including without limitation 7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 9848b8605Smrg * Software is furnished to do so, subject to the following conditions: 10848b8605Smrg * 11848b8605Smrg * The above copyright notice and this permission notice shall be included 12848b8605Smrg * in all copies or substantial portions of the Software. 13848b8605Smrg * 14848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 21848b8605Smrg */ 22848b8605Smrg 23848b8605Smrg 24848b8605Smrg/* 25848b8605Smrg * Off-Screen rendering into client memory. 26848b8605Smrg * State tracker for gallium (for softpipe and llvmpipe) 27848b8605Smrg * 28848b8605Smrg * Notes: 29848b8605Smrg * 30848b8605Smrg * If Gallium is built with LLVM support we use the llvmpipe driver. 31848b8605Smrg * Otherwise we use softpipe. The GALLIUM_DRIVER environment variable 32848b8605Smrg * may be set to "softpipe" or "llvmpipe" to override. 33848b8605Smrg * 34848b8605Smrg * With softpipe we could render directly into the user's buffer by using a 35b8e80941Smrg * display target resource. However, softpipe doesn't support "upside-down" 36848b8605Smrg * rendering which would be needed for the OSMESA_Y_UP=TRUE case. 37848b8605Smrg * 38848b8605Smrg * With llvmpipe we could only render directly into the user's buffer when its 39848b8605Smrg * width and height is a multiple of the tile size (64 pixels). 40848b8605Smrg * 41848b8605Smrg * Because of these constraints we always render into ordinary resources then 42848b8605Smrg * copy the results to the user's buffer in the flush_front() function which 43848b8605Smrg * is called when the app calls glFlush/Finish. 44848b8605Smrg * 45848b8605Smrg * In general, the OSMesa interface is pretty ugly and not a good match 46848b8605Smrg * for Gallium. But we're interested in doing the best we can to preserve 47848b8605Smrg * application portability. With a little work we could come up with a 48848b8605Smrg * much nicer, new off-screen Gallium interface... 49848b8605Smrg */ 50848b8605Smrg 51848b8605Smrg 52b8e80941Smrg#include <stdio.h> 53848b8605Smrg#include "GL/osmesa.h" 54848b8605Smrg 55848b8605Smrg#include "glapi/glapi.h" /* for OSMesaGetProcAddress below */ 56848b8605Smrg 57848b8605Smrg#include "pipe/p_context.h" 58848b8605Smrg#include "pipe/p_screen.h" 59848b8605Smrg#include "pipe/p_state.h" 60848b8605Smrg 61848b8605Smrg#include "util/u_atomic.h" 62848b8605Smrg#include "util/u_box.h" 63848b8605Smrg#include "util/u_debug.h" 64848b8605Smrg#include "util/u_format.h" 65b8e80941Smrg#include "util/u_inlines.h" 66848b8605Smrg#include "util/u_memory.h" 67848b8605Smrg 68848b8605Smrg#include "postprocess/filters.h" 69848b8605Smrg#include "postprocess/postprocess.h" 70848b8605Smrg 71848b8605Smrg#include "state_tracker/st_api.h" 72848b8605Smrg#include "state_tracker/st_gl_api.h" 73848b8605Smrg 74848b8605Smrg 75848b8605Smrg 76848b8605Smrgextern struct pipe_screen * 77848b8605Smrgosmesa_create_screen(void); 78848b8605Smrg 79848b8605Smrg 80848b8605Smrg 81848b8605Smrgstruct osmesa_buffer 82848b8605Smrg{ 83848b8605Smrg struct st_framebuffer_iface *stfb; 84848b8605Smrg struct st_visual visual; 85848b8605Smrg unsigned width, height; 86848b8605Smrg 87848b8605Smrg struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; 88848b8605Smrg 89848b8605Smrg void *map; 90848b8605Smrg 91848b8605Smrg struct osmesa_buffer *next; /**< next in linked list */ 92848b8605Smrg}; 93848b8605Smrg 94848b8605Smrg 95848b8605Smrgstruct osmesa_context 96848b8605Smrg{ 97848b8605Smrg struct st_context_iface *stctx; 98848b8605Smrg 99848b8605Smrg boolean ever_used; /*< Has this context ever been current? */ 100848b8605Smrg 101848b8605Smrg struct osmesa_buffer *current_buffer; 102848b8605Smrg 103848b8605Smrg enum pipe_format depth_stencil_format, accum_format; 104848b8605Smrg 105848b8605Smrg GLenum format; /*< User-specified context format */ 106848b8605Smrg GLenum type; /*< Buffer's data type */ 107848b8605Smrg GLint user_row_length; /*< user-specified number of pixels per row */ 108848b8605Smrg GLboolean y_up; /*< TRUE -> Y increases upward */ 109848b8605Smrg /*< FALSE -> Y increases downward */ 110848b8605Smrg 111848b8605Smrg /** Which postprocessing filters are enabled. */ 112848b8605Smrg unsigned pp_enabled[PP_FILTERS]; 113848b8605Smrg struct pp_queue_t *pp; 114848b8605Smrg}; 115848b8605Smrg 116848b8605Smrg 117848b8605Smrg/** 118848b8605Smrg * Linked list of all osmesa_buffers. 119848b8605Smrg * We can re-use an osmesa_buffer from one OSMesaMakeCurrent() call to 120848b8605Smrg * the next unless the color/depth/stencil/accum formats change. 121848b8605Smrg * We have to do this to be compatible with the original OSMesa implementation 122848b8605Smrg * because some apps call OSMesaMakeCurrent() several times during rendering 123848b8605Smrg * a frame. 124848b8605Smrg */ 125848b8605Smrgstatic struct osmesa_buffer *BufferList = NULL; 126848b8605Smrg 127848b8605Smrg 128848b8605Smrg/** 129848b8605Smrg * Called from the ST manager. 130848b8605Smrg */ 131848b8605Smrgstatic int 132848b8605Smrgosmesa_st_get_param(struct st_manager *smapi, enum st_manager_param param) 133848b8605Smrg{ 134848b8605Smrg /* no-op */ 135848b8605Smrg return 0; 136848b8605Smrg} 137848b8605Smrg 138848b8605Smrg 139848b8605Smrg/** 140848b8605Smrg * Create/return singleton st_api object. 141848b8605Smrg */ 142848b8605Smrgstatic struct st_api * 143848b8605Smrgget_st_api(void) 144848b8605Smrg{ 145848b8605Smrg static struct st_api *stapi = NULL; 146848b8605Smrg if (!stapi) { 147848b8605Smrg stapi = st_gl_api_create(); 148848b8605Smrg } 149848b8605Smrg return stapi; 150848b8605Smrg} 151848b8605Smrg 152848b8605Smrg 153848b8605Smrg/** 154848b8605Smrg * Create/return a singleton st_manager object. 155848b8605Smrg */ 156848b8605Smrgstatic struct st_manager * 157848b8605Smrgget_st_manager(void) 158848b8605Smrg{ 159848b8605Smrg static struct st_manager *stmgr = NULL; 160848b8605Smrg if (!stmgr) { 161848b8605Smrg stmgr = CALLOC_STRUCT(st_manager); 162848b8605Smrg if (stmgr) { 163848b8605Smrg stmgr->screen = osmesa_create_screen(); 164848b8605Smrg stmgr->get_param = osmesa_st_get_param; 165848b8605Smrg stmgr->get_egl_image = NULL; 166848b8605Smrg } 167848b8605Smrg } 168848b8605Smrg return stmgr; 169848b8605Smrg} 170848b8605Smrg 171848b8605Smrg 172b8e80941Smrgstatic inline boolean 173848b8605Smrglittle_endian(void) 174848b8605Smrg{ 175848b8605Smrg const unsigned ui = 1; 176848b8605Smrg return *((const char *) &ui); 177848b8605Smrg} 178848b8605Smrg 179848b8605Smrg 180848b8605Smrg/** 181848b8605Smrg * Given an OSMESA_x format and a GL_y type, return the best 182848b8605Smrg * matching PIPE_FORMAT_z. 183848b8605Smrg * Note that we can't exactly match all user format/type combinations 184848b8605Smrg * with gallium formats. If we find this to be a problem, we can 185848b8605Smrg * implement more elaborate format/type conversion in the flush_front() 186848b8605Smrg * function. 187848b8605Smrg */ 188848b8605Smrgstatic enum pipe_format 189848b8605Smrgosmesa_choose_format(GLenum format, GLenum type) 190848b8605Smrg{ 191848b8605Smrg switch (format) { 192848b8605Smrg case OSMESA_RGBA: 193848b8605Smrg if (type == GL_UNSIGNED_BYTE) { 194848b8605Smrg if (little_endian()) 195848b8605Smrg return PIPE_FORMAT_R8G8B8A8_UNORM; 196848b8605Smrg else 197848b8605Smrg return PIPE_FORMAT_A8B8G8R8_UNORM; 198848b8605Smrg } 199848b8605Smrg else if (type == GL_UNSIGNED_SHORT) { 200848b8605Smrg return PIPE_FORMAT_R16G16B16A16_UNORM; 201848b8605Smrg } 202848b8605Smrg else if (type == GL_FLOAT) { 203848b8605Smrg return PIPE_FORMAT_R32G32B32A32_FLOAT; 204848b8605Smrg } 205848b8605Smrg else { 206848b8605Smrg return PIPE_FORMAT_NONE; 207848b8605Smrg } 208848b8605Smrg break; 209848b8605Smrg case OSMESA_BGRA: 210848b8605Smrg if (type == GL_UNSIGNED_BYTE) { 211848b8605Smrg if (little_endian()) 212848b8605Smrg return PIPE_FORMAT_B8G8R8A8_UNORM; 213848b8605Smrg else 214848b8605Smrg return PIPE_FORMAT_A8R8G8B8_UNORM; 215848b8605Smrg } 216848b8605Smrg else if (type == GL_UNSIGNED_SHORT) { 217848b8605Smrg return PIPE_FORMAT_R16G16B16A16_UNORM; 218848b8605Smrg } 219848b8605Smrg else if (type == GL_FLOAT) { 220848b8605Smrg return PIPE_FORMAT_R32G32B32A32_FLOAT; 221848b8605Smrg } 222848b8605Smrg else { 223848b8605Smrg return PIPE_FORMAT_NONE; 224848b8605Smrg } 225848b8605Smrg break; 226848b8605Smrg case OSMESA_ARGB: 227848b8605Smrg if (type == GL_UNSIGNED_BYTE) { 228848b8605Smrg if (little_endian()) 229848b8605Smrg return PIPE_FORMAT_A8R8G8B8_UNORM; 230848b8605Smrg else 231848b8605Smrg return PIPE_FORMAT_B8G8R8A8_UNORM; 232848b8605Smrg } 233848b8605Smrg else if (type == GL_UNSIGNED_SHORT) { 234848b8605Smrg return PIPE_FORMAT_R16G16B16A16_UNORM; 235848b8605Smrg } 236848b8605Smrg else if (type == GL_FLOAT) { 237848b8605Smrg return PIPE_FORMAT_R32G32B32A32_FLOAT; 238848b8605Smrg } 239848b8605Smrg else { 240848b8605Smrg return PIPE_FORMAT_NONE; 241848b8605Smrg } 242848b8605Smrg break; 243848b8605Smrg case OSMESA_RGB: 244848b8605Smrg if (type == GL_UNSIGNED_BYTE) { 245848b8605Smrg return PIPE_FORMAT_R8G8B8_UNORM; 246848b8605Smrg } 247848b8605Smrg else if (type == GL_UNSIGNED_SHORT) { 248848b8605Smrg return PIPE_FORMAT_R16G16B16_UNORM; 249848b8605Smrg } 250848b8605Smrg else if (type == GL_FLOAT) { 251848b8605Smrg return PIPE_FORMAT_R32G32B32_FLOAT; 252848b8605Smrg } 253848b8605Smrg else { 254848b8605Smrg return PIPE_FORMAT_NONE; 255848b8605Smrg } 256848b8605Smrg break; 257848b8605Smrg case OSMESA_BGR: 258848b8605Smrg /* No gallium format for this one */ 259848b8605Smrg return PIPE_FORMAT_NONE; 260848b8605Smrg case OSMESA_RGB_565: 261848b8605Smrg return PIPE_FORMAT_B5G6R5_UNORM; 262848b8605Smrg default: 263848b8605Smrg ; /* fall-through */ 264848b8605Smrg } 265848b8605Smrg return PIPE_FORMAT_NONE; 266848b8605Smrg} 267848b8605Smrg 268848b8605Smrg 269848b8605Smrg/** 270848b8605Smrg * Initialize an st_visual object. 271848b8605Smrg */ 272848b8605Smrgstatic void 273848b8605Smrgosmesa_init_st_visual(struct st_visual *vis, 274848b8605Smrg enum pipe_format color_format, 275848b8605Smrg enum pipe_format ds_format, 276848b8605Smrg enum pipe_format accum_format) 277848b8605Smrg{ 278848b8605Smrg vis->buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; 279848b8605Smrg 280848b8605Smrg if (ds_format != PIPE_FORMAT_NONE) 281848b8605Smrg vis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; 282848b8605Smrg if (accum_format != PIPE_FORMAT_NONE) 283848b8605Smrg vis->buffer_mask |= ST_ATTACHMENT_ACCUM; 284848b8605Smrg 285848b8605Smrg vis->color_format = color_format; 286848b8605Smrg vis->depth_stencil_format = ds_format; 287848b8605Smrg vis->accum_format = accum_format; 288848b8605Smrg vis->samples = 1; 289848b8605Smrg vis->render_buffer = ST_ATTACHMENT_FRONT_LEFT; 290848b8605Smrg} 291848b8605Smrg 292848b8605Smrg 293848b8605Smrg/** 294848b8605Smrg * Return the osmesa_buffer that corresponds to an st_framebuffer_iface. 295848b8605Smrg */ 296b8e80941Smrgstatic inline struct osmesa_buffer * 297848b8605Smrgstfbi_to_osbuffer(struct st_framebuffer_iface *stfbi) 298848b8605Smrg{ 299848b8605Smrg return (struct osmesa_buffer *) stfbi->st_manager_private; 300848b8605Smrg} 301848b8605Smrg 302848b8605Smrg 303848b8605Smrg/** 304848b8605Smrg * Called via glFlush/glFinish. This is where we copy the contents 305848b8605Smrg * of the driver's color buffer into the user-specified buffer. 306848b8605Smrg */ 307848b8605Smrgstatic boolean 308848b8605Smrgosmesa_st_framebuffer_flush_front(struct st_context_iface *stctx, 309848b8605Smrg struct st_framebuffer_iface *stfbi, 310848b8605Smrg enum st_attachment_type statt) 311848b8605Smrg{ 312848b8605Smrg OSMesaContext osmesa = OSMesaGetCurrentContext(); 313848b8605Smrg struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); 314848b8605Smrg struct pipe_context *pipe = stctx->pipe; 315848b8605Smrg struct pipe_resource *res = osbuffer->textures[statt]; 316848b8605Smrg struct pipe_transfer *transfer = NULL; 317848b8605Smrg struct pipe_box box; 318848b8605Smrg void *map; 319848b8605Smrg ubyte *src, *dst; 320848b8605Smrg unsigned y, bytes, bpp; 321848b8605Smrg int dst_stride; 322848b8605Smrg 323848b8605Smrg if (osmesa->pp) { 324848b8605Smrg struct pipe_resource *zsbuf = NULL; 325848b8605Smrg unsigned i; 326848b8605Smrg 327848b8605Smrg /* Find the z/stencil buffer if there is one */ 328b8e80941Smrg for (i = 0; i < ARRAY_SIZE(osbuffer->textures); i++) { 329848b8605Smrg struct pipe_resource *res = osbuffer->textures[i]; 330848b8605Smrg if (res) { 331848b8605Smrg const struct util_format_description *desc = 332848b8605Smrg util_format_description(res->format); 333848b8605Smrg 334848b8605Smrg if (util_format_has_depth(desc)) { 335848b8605Smrg zsbuf = res; 336848b8605Smrg break; 337848b8605Smrg } 338848b8605Smrg } 339848b8605Smrg } 340848b8605Smrg 341848b8605Smrg /* run the postprocess stage(s) */ 342848b8605Smrg pp_run(osmesa->pp, res, res, zsbuf); 343848b8605Smrg } 344848b8605Smrg 345848b8605Smrg u_box_2d(0, 0, res->width0, res->height0, &box); 346848b8605Smrg 347848b8605Smrg map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, 348848b8605Smrg &transfer); 349848b8605Smrg 350848b8605Smrg /* 351848b8605Smrg * Copy the color buffer from the resource to the user's buffer. 352848b8605Smrg */ 353848b8605Smrg bpp = util_format_get_blocksize(osbuffer->visual.color_format); 354848b8605Smrg src = map; 355848b8605Smrg dst = osbuffer->map; 356848b8605Smrg if (osmesa->user_row_length) 357848b8605Smrg dst_stride = bpp * osmesa->user_row_length; 358848b8605Smrg else 359848b8605Smrg dst_stride = bpp * osbuffer->width; 360848b8605Smrg bytes = bpp * res->width0; 361848b8605Smrg 362848b8605Smrg if (osmesa->y_up) { 363848b8605Smrg /* need to flip image upside down */ 364848b8605Smrg dst = dst + (res->height0 - 1) * dst_stride; 365848b8605Smrg dst_stride = -dst_stride; 366848b8605Smrg } 367848b8605Smrg 368848b8605Smrg for (y = 0; y < res->height0; y++) { 369848b8605Smrg memcpy(dst, src, bytes); 370848b8605Smrg dst += dst_stride; 371848b8605Smrg src += transfer->stride; 372848b8605Smrg } 373848b8605Smrg 374848b8605Smrg pipe->transfer_unmap(pipe, transfer); 375848b8605Smrg 376848b8605Smrg return TRUE; 377848b8605Smrg} 378848b8605Smrg 379848b8605Smrg 380848b8605Smrg/** 381848b8605Smrg * Called by the st manager to validate the framebuffer (allocate 382848b8605Smrg * its resources). 383848b8605Smrg */ 384848b8605Smrgstatic boolean 385848b8605Smrgosmesa_st_framebuffer_validate(struct st_context_iface *stctx, 386848b8605Smrg struct st_framebuffer_iface *stfbi, 387848b8605Smrg const enum st_attachment_type *statts, 388848b8605Smrg unsigned count, 389848b8605Smrg struct pipe_resource **out) 390848b8605Smrg{ 391848b8605Smrg struct pipe_screen *screen = get_st_manager()->screen; 392848b8605Smrg enum st_attachment_type i; 393848b8605Smrg struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi); 394848b8605Smrg struct pipe_resource templat; 395848b8605Smrg 396848b8605Smrg memset(&templat, 0, sizeof(templat)); 397848b8605Smrg templat.target = PIPE_TEXTURE_RECT; 398848b8605Smrg templat.format = 0; /* setup below */ 399848b8605Smrg templat.last_level = 0; 400848b8605Smrg templat.width0 = osbuffer->width; 401848b8605Smrg templat.height0 = osbuffer->height; 402848b8605Smrg templat.depth0 = 1; 403848b8605Smrg templat.array_size = 1; 404848b8605Smrg templat.usage = PIPE_USAGE_DEFAULT; 405848b8605Smrg templat.bind = 0; /* setup below */ 406848b8605Smrg templat.flags = 0; 407848b8605Smrg 408848b8605Smrg for (i = 0; i < count; i++) { 409848b8605Smrg enum pipe_format format = PIPE_FORMAT_NONE; 410848b8605Smrg unsigned bind = 0; 411848b8605Smrg 412848b8605Smrg /* 413848b8605Smrg * At this time, we really only need to handle the front-left color 414848b8605Smrg * attachment, since that's all we specified for the visual in 415848b8605Smrg * osmesa_init_st_visual(). 416848b8605Smrg */ 417848b8605Smrg if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) { 418848b8605Smrg format = osbuffer->visual.color_format; 419848b8605Smrg bind = PIPE_BIND_RENDER_TARGET; 420848b8605Smrg } 421848b8605Smrg else if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { 422848b8605Smrg format = osbuffer->visual.depth_stencil_format; 423848b8605Smrg bind = PIPE_BIND_DEPTH_STENCIL; 424848b8605Smrg } 425848b8605Smrg else if (statts[i] == ST_ATTACHMENT_ACCUM) { 426848b8605Smrg format = osbuffer->visual.accum_format; 427848b8605Smrg bind = PIPE_BIND_RENDER_TARGET; 428848b8605Smrg } 429848b8605Smrg else { 430848b8605Smrg debug_warning("Unexpected attachment type in " 431848b8605Smrg "osmesa_st_framebuffer_validate()"); 432848b8605Smrg } 433848b8605Smrg 434848b8605Smrg templat.format = format; 435848b8605Smrg templat.bind = bind; 436b8e80941Smrg pipe_resource_reference(&out[i], NULL); 437b8e80941Smrg out[i] = osbuffer->textures[statts[i]] = 438848b8605Smrg screen->resource_create(screen, &templat); 439848b8605Smrg } 440848b8605Smrg 441848b8605Smrg return TRUE; 442848b8605Smrg} 443848b8605Smrg 444b8e80941Smrgstatic uint32_t osmesa_fb_ID = 0; 445848b8605Smrg 446848b8605Smrgstatic struct st_framebuffer_iface * 447848b8605Smrgosmesa_create_st_framebuffer(void) 448848b8605Smrg{ 449848b8605Smrg struct st_framebuffer_iface *stfbi = CALLOC_STRUCT(st_framebuffer_iface); 450848b8605Smrg if (stfbi) { 451848b8605Smrg stfbi->flush_front = osmesa_st_framebuffer_flush_front; 452848b8605Smrg stfbi->validate = osmesa_st_framebuffer_validate; 453848b8605Smrg p_atomic_set(&stfbi->stamp, 1); 454b8e80941Smrg stfbi->ID = p_atomic_inc_return(&osmesa_fb_ID); 455b8e80941Smrg stfbi->state_manager = get_st_manager(); 456848b8605Smrg } 457848b8605Smrg return stfbi; 458848b8605Smrg} 459848b8605Smrg 460848b8605Smrg 461848b8605Smrg/** 462848b8605Smrg * Create new buffer and add to linked list. 463848b8605Smrg */ 464848b8605Smrgstatic struct osmesa_buffer * 465848b8605Smrgosmesa_create_buffer(enum pipe_format color_format, 466848b8605Smrg enum pipe_format ds_format, 467848b8605Smrg enum pipe_format accum_format) 468848b8605Smrg{ 469848b8605Smrg struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer); 470848b8605Smrg if (osbuffer) { 471848b8605Smrg osbuffer->stfb = osmesa_create_st_framebuffer(); 472848b8605Smrg 473848b8605Smrg osbuffer->stfb->st_manager_private = osbuffer; 474848b8605Smrg osbuffer->stfb->visual = &osbuffer->visual; 475848b8605Smrg 476848b8605Smrg osmesa_init_st_visual(&osbuffer->visual, color_format, 477848b8605Smrg ds_format, accum_format); 478848b8605Smrg 479848b8605Smrg /* insert into linked list */ 480848b8605Smrg osbuffer->next = BufferList; 481848b8605Smrg BufferList = osbuffer; 482848b8605Smrg } 483848b8605Smrg 484848b8605Smrg return osbuffer; 485848b8605Smrg} 486848b8605Smrg 487848b8605Smrg 488848b8605Smrg/** 489848b8605Smrg * Search linked list for a buffer with matching pixel formats and size. 490848b8605Smrg */ 491848b8605Smrgstatic struct osmesa_buffer * 492848b8605Smrgosmesa_find_buffer(enum pipe_format color_format, 493848b8605Smrg enum pipe_format ds_format, 494848b8605Smrg enum pipe_format accum_format, 495848b8605Smrg GLsizei width, GLsizei height) 496848b8605Smrg{ 497848b8605Smrg struct osmesa_buffer *b; 498848b8605Smrg 499848b8605Smrg /* Check if we already have a suitable buffer for the given formats */ 500848b8605Smrg for (b = BufferList; b; b = b->next) { 501848b8605Smrg if (b->visual.color_format == color_format && 502848b8605Smrg b->visual.depth_stencil_format == ds_format && 503848b8605Smrg b->visual.accum_format == accum_format && 504848b8605Smrg b->width == width && 505848b8605Smrg b->height == height) { 506848b8605Smrg return b; 507848b8605Smrg } 508848b8605Smrg } 509848b8605Smrg return NULL; 510848b8605Smrg} 511848b8605Smrg 512848b8605Smrg 513848b8605Smrgstatic void 514848b8605Smrgosmesa_destroy_buffer(struct osmesa_buffer *osbuffer) 515848b8605Smrg{ 516b8e80941Smrg struct st_api *stapi = get_st_api(); 517b8e80941Smrg 518b8e80941Smrg /* 519b8e80941Smrg * Notify the state manager that the associated framebuffer interface 520b8e80941Smrg * is no longer valid. 521b8e80941Smrg */ 522b8e80941Smrg stapi->destroy_drawable(stapi, osbuffer->stfb); 523b8e80941Smrg 524848b8605Smrg FREE(osbuffer->stfb); 525848b8605Smrg FREE(osbuffer); 526848b8605Smrg} 527848b8605Smrg 528848b8605Smrg 529848b8605Smrg 530848b8605Smrg/**********************************************************************/ 531848b8605Smrg/***** Public Functions *****/ 532848b8605Smrg/**********************************************************************/ 533848b8605Smrg 534848b8605Smrg 535848b8605Smrg/** 536848b8605Smrg * Create an Off-Screen Mesa rendering context. The only attribute needed is 537848b8605Smrg * an RGBA vs Color-Index mode flag. 538848b8605Smrg * 539848b8605Smrg * Input: format - Must be GL_RGBA 540848b8605Smrg * sharelist - specifies another OSMesaContext with which to share 541848b8605Smrg * display lists. NULL indicates no sharing. 542848b8605Smrg * Return: an OSMesaContext or 0 if error 543848b8605Smrg */ 544848b8605SmrgGLAPI OSMesaContext GLAPIENTRY 545848b8605SmrgOSMesaCreateContext(GLenum format, OSMesaContext sharelist) 546848b8605Smrg{ 547848b8605Smrg return OSMesaCreateContextExt(format, 24, 8, 0, sharelist); 548848b8605Smrg} 549848b8605Smrg 550848b8605Smrg 551848b8605Smrg/** 552848b8605Smrg * New in Mesa 3.5 553848b8605Smrg * 554848b8605Smrg * Create context and specify size of ancillary buffers. 555848b8605Smrg */ 556848b8605SmrgGLAPI OSMesaContext GLAPIENTRY 557848b8605SmrgOSMesaCreateContextExt(GLenum format, GLint depthBits, GLint stencilBits, 558848b8605Smrg GLint accumBits, OSMesaContext sharelist) 559b8e80941Smrg{ 560b8e80941Smrg int attribs[100], n = 0; 561b8e80941Smrg 562b8e80941Smrg attribs[n++] = OSMESA_FORMAT; 563b8e80941Smrg attribs[n++] = format; 564b8e80941Smrg attribs[n++] = OSMESA_DEPTH_BITS; 565b8e80941Smrg attribs[n++] = depthBits; 566b8e80941Smrg attribs[n++] = OSMESA_STENCIL_BITS; 567b8e80941Smrg attribs[n++] = stencilBits; 568b8e80941Smrg attribs[n++] = OSMESA_ACCUM_BITS; 569b8e80941Smrg attribs[n++] = accumBits; 570b8e80941Smrg attribs[n++] = 0; 571b8e80941Smrg 572b8e80941Smrg return OSMesaCreateContextAttribs(attribs, sharelist); 573b8e80941Smrg} 574b8e80941Smrg 575b8e80941Smrg 576b8e80941Smrg/** 577b8e80941Smrg * New in Mesa 11.2 578b8e80941Smrg * 579b8e80941Smrg * Create context with attribute list. 580b8e80941Smrg */ 581b8e80941SmrgGLAPI OSMesaContext GLAPIENTRY 582b8e80941SmrgOSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist) 583848b8605Smrg{ 584848b8605Smrg OSMesaContext osmesa; 585848b8605Smrg struct st_context_iface *st_shared; 586848b8605Smrg enum st_context_error st_error = 0; 587848b8605Smrg struct st_context_attribs attribs; 588848b8605Smrg struct st_api *stapi = get_st_api(); 589b8e80941Smrg GLenum format = GL_RGBA; 590b8e80941Smrg int depthBits = 0, stencilBits = 0, accumBits = 0; 591b8e80941Smrg int profile = OSMESA_COMPAT_PROFILE, version_major = 1, version_minor = 0; 592b8e80941Smrg int i; 593848b8605Smrg 594848b8605Smrg if (sharelist) { 595848b8605Smrg st_shared = sharelist->stctx; 596848b8605Smrg } 597848b8605Smrg else { 598848b8605Smrg st_shared = NULL; 599848b8605Smrg } 600848b8605Smrg 601b8e80941Smrg for (i = 0; attribList[i]; i += 2) { 602b8e80941Smrg switch (attribList[i]) { 603b8e80941Smrg case OSMESA_FORMAT: 604b8e80941Smrg format = attribList[i+1]; 605b8e80941Smrg switch (format) { 606b8e80941Smrg case OSMESA_COLOR_INDEX: 607b8e80941Smrg case OSMESA_RGBA: 608b8e80941Smrg case OSMESA_BGRA: 609b8e80941Smrg case OSMESA_ARGB: 610b8e80941Smrg case OSMESA_RGB: 611b8e80941Smrg case OSMESA_BGR: 612b8e80941Smrg case OSMESA_RGB_565: 613b8e80941Smrg /* legal */ 614b8e80941Smrg break; 615b8e80941Smrg default: 616b8e80941Smrg return NULL; 617b8e80941Smrg } 618b8e80941Smrg break; 619b8e80941Smrg case OSMESA_DEPTH_BITS: 620b8e80941Smrg depthBits = attribList[i+1]; 621b8e80941Smrg if (depthBits < 0) 622b8e80941Smrg return NULL; 623b8e80941Smrg break; 624b8e80941Smrg case OSMESA_STENCIL_BITS: 625b8e80941Smrg stencilBits = attribList[i+1]; 626b8e80941Smrg if (stencilBits < 0) 627b8e80941Smrg return NULL; 628b8e80941Smrg break; 629b8e80941Smrg case OSMESA_ACCUM_BITS: 630b8e80941Smrg accumBits = attribList[i+1]; 631b8e80941Smrg if (accumBits < 0) 632b8e80941Smrg return NULL; 633b8e80941Smrg break; 634b8e80941Smrg case OSMESA_PROFILE: 635b8e80941Smrg profile = attribList[i+1]; 636b8e80941Smrg if (profile != OSMESA_CORE_PROFILE && 637b8e80941Smrg profile != OSMESA_COMPAT_PROFILE) 638b8e80941Smrg return NULL; 639b8e80941Smrg break; 640b8e80941Smrg case OSMESA_CONTEXT_MAJOR_VERSION: 641b8e80941Smrg version_major = attribList[i+1]; 642b8e80941Smrg if (version_major < 1) 643b8e80941Smrg return NULL; 644b8e80941Smrg break; 645b8e80941Smrg case OSMESA_CONTEXT_MINOR_VERSION: 646b8e80941Smrg version_minor = attribList[i+1]; 647b8e80941Smrg if (version_minor < 0) 648b8e80941Smrg return NULL; 649b8e80941Smrg break; 650b8e80941Smrg case 0: 651b8e80941Smrg /* end of list */ 652b8e80941Smrg break; 653b8e80941Smrg default: 654b8e80941Smrg fprintf(stderr, "Bad attribute in OSMesaCreateContextAttribs()\n"); 655b8e80941Smrg return NULL; 656b8e80941Smrg } 657b8e80941Smrg } 658b8e80941Smrg 659848b8605Smrg osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); 660848b8605Smrg if (!osmesa) 661848b8605Smrg return NULL; 662848b8605Smrg 663848b8605Smrg /* Choose depth/stencil/accum buffer formats */ 664848b8605Smrg if (accumBits > 0) { 665848b8605Smrg osmesa->accum_format = PIPE_FORMAT_R16G16B16A16_SNORM; 666848b8605Smrg } 667848b8605Smrg if (depthBits > 0 && stencilBits > 0) { 668848b8605Smrg osmesa->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT; 669848b8605Smrg } 670848b8605Smrg else if (stencilBits > 0) { 671848b8605Smrg osmesa->depth_stencil_format = PIPE_FORMAT_S8_UINT; 672848b8605Smrg } 673848b8605Smrg else if (depthBits >= 24) { 674848b8605Smrg osmesa->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM; 675848b8605Smrg } 676848b8605Smrg else if (depthBits >= 16) { 677848b8605Smrg osmesa->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; 678848b8605Smrg } 679848b8605Smrg 680848b8605Smrg /* 681848b8605Smrg * Create the rendering context 682848b8605Smrg */ 683b8e80941Smrg memset(&attribs, 0, sizeof(attribs)); 684b8e80941Smrg attribs.profile = (profile == OSMESA_CORE_PROFILE) 685b8e80941Smrg ? ST_PROFILE_OPENGL_CORE : ST_PROFILE_DEFAULT; 686b8e80941Smrg attribs.major = version_major; 687b8e80941Smrg attribs.minor = version_minor; 688848b8605Smrg attribs.flags = 0; /* ST_CONTEXT_FLAG_x */ 689848b8605Smrg attribs.options.force_glsl_extensions_warn = FALSE; 690848b8605Smrg attribs.options.disable_blend_func_extended = FALSE; 691848b8605Smrg attribs.options.disable_glsl_line_continuations = FALSE; 692848b8605Smrg attribs.options.force_glsl_version = 0; 693848b8605Smrg 694848b8605Smrg osmesa_init_st_visual(&attribs.visual, 695848b8605Smrg PIPE_FORMAT_R8G8B8A8_UNORM, 696848b8605Smrg osmesa->depth_stencil_format, 697848b8605Smrg osmesa->accum_format); 698848b8605Smrg 699848b8605Smrg osmesa->stctx = stapi->create_context(stapi, get_st_manager(), 700848b8605Smrg &attribs, &st_error, st_shared); 701848b8605Smrg if (!osmesa->stctx) { 702848b8605Smrg FREE(osmesa); 703848b8605Smrg return NULL; 704848b8605Smrg } 705848b8605Smrg 706848b8605Smrg osmesa->stctx->st_manager_private = osmesa; 707848b8605Smrg 708848b8605Smrg osmesa->format = format; 709848b8605Smrg osmesa->user_row_length = 0; 710848b8605Smrg osmesa->y_up = GL_TRUE; 711848b8605Smrg 712848b8605Smrg return osmesa; 713848b8605Smrg} 714848b8605Smrg 715848b8605Smrg 716b8e80941Smrg 717848b8605Smrg/** 718848b8605Smrg * Destroy an Off-Screen Mesa rendering context. 719848b8605Smrg * 720848b8605Smrg * \param osmesa the context to destroy 721848b8605Smrg */ 722848b8605SmrgGLAPI void GLAPIENTRY 723848b8605SmrgOSMesaDestroyContext(OSMesaContext osmesa) 724848b8605Smrg{ 725848b8605Smrg if (osmesa) { 726848b8605Smrg pp_free(osmesa->pp); 727848b8605Smrg osmesa->stctx->destroy(osmesa->stctx); 728848b8605Smrg FREE(osmesa); 729848b8605Smrg } 730848b8605Smrg} 731848b8605Smrg 732848b8605Smrg 733848b8605Smrg/** 734848b8605Smrg * Bind an OSMesaContext to an image buffer. The image buffer is just a 735848b8605Smrg * block of memory which the client provides. Its size must be at least 736848b8605Smrg * as large as width*height*pixelSize. Its address should be a multiple 737848b8605Smrg * of 4 if using RGBA mode. 738848b8605Smrg * 739848b8605Smrg * By default, image data is stored in the order of glDrawPixels: row-major 740848b8605Smrg * order with the lower-left image pixel stored in the first array position 741848b8605Smrg * (ie. bottom-to-top). 742848b8605Smrg * 743848b8605Smrg * If the context's viewport hasn't been initialized yet, it will now be 744848b8605Smrg * initialized to (0,0,width,height). 745848b8605Smrg * 746848b8605Smrg * Input: osmesa - the rendering context 747848b8605Smrg * buffer - the image buffer memory 748848b8605Smrg * type - data type for pixel components 749848b8605Smrg * GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT 750848b8605Smrg * or GL_FLOAT. 751848b8605Smrg * width, height - size of image buffer in pixels, at least 1 752848b8605Smrg * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa, 753848b8605Smrg * invalid type, invalid size, etc. 754848b8605Smrg */ 755848b8605SmrgGLAPI GLboolean GLAPIENTRY 756848b8605SmrgOSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type, 757848b8605Smrg GLsizei width, GLsizei height) 758848b8605Smrg{ 759848b8605Smrg struct st_api *stapi = get_st_api(); 760848b8605Smrg struct osmesa_buffer *osbuffer; 761848b8605Smrg enum pipe_format color_format; 762848b8605Smrg 763848b8605Smrg if (!osmesa || !buffer || width < 1 || height < 1) { 764848b8605Smrg return GL_FALSE; 765848b8605Smrg } 766848b8605Smrg 767848b8605Smrg if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) { 768848b8605Smrg return GL_FALSE; 769848b8605Smrg } 770848b8605Smrg 771848b8605Smrg color_format = osmesa_choose_format(osmesa->format, type); 772848b8605Smrg if (color_format == PIPE_FORMAT_NONE) { 773848b8605Smrg fprintf(stderr, "OSMesaMakeCurrent(unsupported format/type)\n"); 774848b8605Smrg return GL_FALSE; 775848b8605Smrg } 776848b8605Smrg 777848b8605Smrg /* See if we already have a buffer that uses these pixel formats */ 778848b8605Smrg osbuffer = osmesa_find_buffer(color_format, 779848b8605Smrg osmesa->depth_stencil_format, 780848b8605Smrg osmesa->accum_format, width, height); 781848b8605Smrg if (!osbuffer) { 782848b8605Smrg /* Existing buffer found, create new buffer */ 783848b8605Smrg osbuffer = osmesa_create_buffer(color_format, 784848b8605Smrg osmesa->depth_stencil_format, 785848b8605Smrg osmesa->accum_format); 786848b8605Smrg } 787848b8605Smrg 788848b8605Smrg osbuffer->width = width; 789848b8605Smrg osbuffer->height = height; 790848b8605Smrg osbuffer->map = buffer; 791848b8605Smrg 792848b8605Smrg /* XXX unused for now */ 793848b8605Smrg (void) osmesa_destroy_buffer; 794848b8605Smrg 795848b8605Smrg osmesa->current_buffer = osbuffer; 796848b8605Smrg osmesa->type = type; 797848b8605Smrg 798848b8605Smrg stapi->make_current(stapi, osmesa->stctx, osbuffer->stfb, osbuffer->stfb); 799848b8605Smrg 800848b8605Smrg if (!osmesa->ever_used) { 801848b8605Smrg /* one-time init, just postprocessing for now */ 802848b8605Smrg boolean any_pp_enabled = FALSE; 803848b8605Smrg unsigned i; 804848b8605Smrg 805b8e80941Smrg for (i = 0; i < ARRAY_SIZE(osmesa->pp_enabled); i++) { 806848b8605Smrg if (osmesa->pp_enabled[i]) { 807848b8605Smrg any_pp_enabled = TRUE; 808848b8605Smrg break; 809848b8605Smrg } 810848b8605Smrg } 811848b8605Smrg 812848b8605Smrg if (any_pp_enabled) { 813848b8605Smrg osmesa->pp = pp_init(osmesa->stctx->pipe, 814848b8605Smrg osmesa->pp_enabled, 815848b8605Smrg osmesa->stctx->cso_context); 816848b8605Smrg 817848b8605Smrg pp_init_fbos(osmesa->pp, width, height); 818848b8605Smrg } 819848b8605Smrg 820848b8605Smrg osmesa->ever_used = TRUE; 821848b8605Smrg } 822848b8605Smrg 823848b8605Smrg return GL_TRUE; 824848b8605Smrg} 825848b8605Smrg 826848b8605Smrg 827848b8605Smrg 828848b8605SmrgGLAPI OSMesaContext GLAPIENTRY 829848b8605SmrgOSMesaGetCurrentContext(void) 830848b8605Smrg{ 831848b8605Smrg struct st_api *stapi = get_st_api(); 832848b8605Smrg struct st_context_iface *st = stapi->get_current(stapi); 833848b8605Smrg return st ? (OSMesaContext) st->st_manager_private : NULL; 834848b8605Smrg} 835848b8605Smrg 836848b8605Smrg 837848b8605Smrg 838848b8605SmrgGLAPI void GLAPIENTRY 839848b8605SmrgOSMesaPixelStore(GLint pname, GLint value) 840848b8605Smrg{ 841848b8605Smrg OSMesaContext osmesa = OSMesaGetCurrentContext(); 842848b8605Smrg 843848b8605Smrg switch (pname) { 844848b8605Smrg case OSMESA_ROW_LENGTH: 845848b8605Smrg osmesa->user_row_length = value; 846848b8605Smrg break; 847848b8605Smrg case OSMESA_Y_UP: 848848b8605Smrg osmesa->y_up = value ? GL_TRUE : GL_FALSE; 849848b8605Smrg break; 850848b8605Smrg default: 851848b8605Smrg fprintf(stderr, "Invalid pname in OSMesaPixelStore()\n"); 852848b8605Smrg return; 853848b8605Smrg } 854848b8605Smrg} 855848b8605Smrg 856848b8605Smrg 857848b8605SmrgGLAPI void GLAPIENTRY 858848b8605SmrgOSMesaGetIntegerv(GLint pname, GLint *value) 859848b8605Smrg{ 860848b8605Smrg OSMesaContext osmesa = OSMesaGetCurrentContext(); 861848b8605Smrg struct osmesa_buffer *osbuffer = osmesa ? osmesa->current_buffer : NULL; 862848b8605Smrg 863848b8605Smrg switch (pname) { 864848b8605Smrg case OSMESA_WIDTH: 865848b8605Smrg *value = osbuffer ? osbuffer->width : 0; 866848b8605Smrg return; 867848b8605Smrg case OSMESA_HEIGHT: 868848b8605Smrg *value = osbuffer ? osbuffer->height : 0; 869848b8605Smrg return; 870848b8605Smrg case OSMESA_FORMAT: 871848b8605Smrg *value = osmesa->format; 872848b8605Smrg return; 873848b8605Smrg case OSMESA_TYPE: 874848b8605Smrg /* current color buffer's data type */ 875848b8605Smrg *value = osmesa->type; 876848b8605Smrg return; 877848b8605Smrg case OSMESA_ROW_LENGTH: 878848b8605Smrg *value = osmesa->user_row_length; 879848b8605Smrg return; 880848b8605Smrg case OSMESA_Y_UP: 881848b8605Smrg *value = osmesa->y_up; 882848b8605Smrg return; 883848b8605Smrg case OSMESA_MAX_WIDTH: 884848b8605Smrg /* fall-through */ 885848b8605Smrg case OSMESA_MAX_HEIGHT: 886848b8605Smrg { 887848b8605Smrg struct pipe_screen *screen = get_st_manager()->screen; 888848b8605Smrg int maxLevels = screen->get_param(screen, 889848b8605Smrg PIPE_CAP_MAX_TEXTURE_2D_LEVELS); 890848b8605Smrg *value = 1 << (maxLevels - 1); 891848b8605Smrg } 892848b8605Smrg return; 893848b8605Smrg default: 894848b8605Smrg fprintf(stderr, "Invalid pname in OSMesaGetIntegerv()\n"); 895848b8605Smrg return; 896848b8605Smrg } 897848b8605Smrg} 898848b8605Smrg 899848b8605Smrg 900848b8605Smrg/** 901848b8605Smrg * Return information about the depth buffer associated with an OSMesa context. 902848b8605Smrg * Input: c - the OSMesa context 903848b8605Smrg * Output: width, height - size of buffer in pixels 904848b8605Smrg * bytesPerValue - bytes per depth value (2 or 4) 905848b8605Smrg * buffer - pointer to depth buffer values 906848b8605Smrg * Return: GL_TRUE or GL_FALSE to indicate success or failure. 907848b8605Smrg */ 908848b8605SmrgGLAPI GLboolean GLAPIENTRY 909848b8605SmrgOSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height, 910848b8605Smrg GLint *bytesPerValue, void **buffer) 911848b8605Smrg{ 912848b8605Smrg struct osmesa_buffer *osbuffer = c->current_buffer; 913848b8605Smrg struct pipe_context *pipe = c->stctx->pipe; 914848b8605Smrg struct pipe_resource *res = osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL]; 915848b8605Smrg struct pipe_transfer *transfer = NULL; 916848b8605Smrg struct pipe_box box; 917848b8605Smrg 918848b8605Smrg /* 919848b8605Smrg * Note: we can't really implement this function with gallium as 920848b8605Smrg * we did for swrast. We can't just map the resource and leave it 921848b8605Smrg * mapped (and there's no OSMesaUnmapDepthBuffer() function) so 922848b8605Smrg * we unmap the buffer here and return a 'stale' pointer. This should 923848b8605Smrg * actually be OK in most cases where the caller of this function 924848b8605Smrg * immediately uses the pointer. 925848b8605Smrg */ 926848b8605Smrg 927848b8605Smrg u_box_2d(0, 0, res->width0, res->height0, &box); 928848b8605Smrg 929848b8605Smrg *buffer = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, 930848b8605Smrg &transfer); 931848b8605Smrg if (!*buffer) { 932848b8605Smrg return GL_FALSE; 933848b8605Smrg } 934848b8605Smrg 935848b8605Smrg *width = res->width0; 936848b8605Smrg *height = res->height0; 937848b8605Smrg *bytesPerValue = util_format_get_blocksize(res->format); 938848b8605Smrg 939848b8605Smrg pipe->transfer_unmap(pipe, transfer); 940848b8605Smrg 941848b8605Smrg return GL_TRUE; 942848b8605Smrg} 943848b8605Smrg 944848b8605Smrg 945848b8605Smrg/** 946848b8605Smrg * Return the color buffer associated with an OSMesa context. 947848b8605Smrg * Input: c - the OSMesa context 948848b8605Smrg * Output: width, height - size of buffer in pixels 949848b8605Smrg * format - the pixel format (OSMESA_FORMAT) 950848b8605Smrg * buffer - pointer to color buffer values 951848b8605Smrg * Return: GL_TRUE or GL_FALSE to indicate success or failure. 952848b8605Smrg */ 953848b8605SmrgGLAPI GLboolean GLAPIENTRY 954848b8605SmrgOSMesaGetColorBuffer(OSMesaContext osmesa, GLint *width, 955848b8605Smrg GLint *height, GLint *format, void **buffer) 956848b8605Smrg{ 957848b8605Smrg struct osmesa_buffer *osbuffer = osmesa->current_buffer; 958848b8605Smrg 959848b8605Smrg if (osbuffer) { 960848b8605Smrg *width = osbuffer->width; 961848b8605Smrg *height = osbuffer->height; 962848b8605Smrg *format = osmesa->format; 963848b8605Smrg *buffer = osbuffer->map; 964848b8605Smrg return GL_TRUE; 965848b8605Smrg } 966848b8605Smrg else { 967848b8605Smrg *width = 0; 968848b8605Smrg *height = 0; 969848b8605Smrg *format = 0; 970848b8605Smrg *buffer = 0; 971848b8605Smrg return GL_FALSE; 972848b8605Smrg } 973848b8605Smrg} 974848b8605Smrg 975848b8605Smrg 976848b8605Smrgstruct name_function 977848b8605Smrg{ 978848b8605Smrg const char *Name; 979848b8605Smrg OSMESAproc Function; 980848b8605Smrg}; 981848b8605Smrg 982848b8605Smrgstatic struct name_function functions[] = { 983848b8605Smrg { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext }, 984848b8605Smrg { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt }, 985b8e80941Smrg { "OSMesaCreateContextAttribs", (OSMESAproc) OSMesaCreateContextAttribs }, 986848b8605Smrg { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext }, 987848b8605Smrg { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent }, 988848b8605Smrg { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext }, 989b8e80941Smrg { "OSMesaPixelStore", (OSMESAproc) OSMesaPixelStore }, 990848b8605Smrg { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv }, 991848b8605Smrg { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer }, 992848b8605Smrg { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer }, 993848b8605Smrg { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress }, 994848b8605Smrg { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp }, 995848b8605Smrg { "OSMesaPostprocess", (OSMESAproc) OSMesaPostprocess }, 996848b8605Smrg { NULL, NULL } 997848b8605Smrg}; 998848b8605Smrg 999848b8605Smrg 1000848b8605SmrgGLAPI OSMESAproc GLAPIENTRY 1001848b8605SmrgOSMesaGetProcAddress(const char *funcName) 1002848b8605Smrg{ 1003848b8605Smrg int i; 1004848b8605Smrg for (i = 0; functions[i].Name; i++) { 1005848b8605Smrg if (strcmp(functions[i].Name, funcName) == 0) 1006848b8605Smrg return functions[i].Function; 1007848b8605Smrg } 1008848b8605Smrg return _glapi_get_proc_address(funcName); 1009848b8605Smrg} 1010848b8605Smrg 1011848b8605Smrg 1012848b8605SmrgGLAPI void GLAPIENTRY 1013848b8605SmrgOSMesaColorClamp(GLboolean enable) 1014848b8605Smrg{ 1015848b8605Smrg extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp); 1016848b8605Smrg 1017848b8605Smrg _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, 1018848b8605Smrg enable ? GL_TRUE : GL_FIXED_ONLY_ARB); 1019848b8605Smrg} 1020848b8605Smrg 1021848b8605Smrg 1022848b8605SmrgGLAPI void GLAPIENTRY 1023848b8605SmrgOSMesaPostprocess(OSMesaContext osmesa, const char *filter, 1024848b8605Smrg unsigned enable_value) 1025848b8605Smrg{ 1026848b8605Smrg if (!osmesa->ever_used) { 1027848b8605Smrg /* We can only enable/disable postprocess filters before a context 1028848b8605Smrg * is made current for the first time. 1029848b8605Smrg */ 1030848b8605Smrg unsigned i; 1031848b8605Smrg 1032848b8605Smrg for (i = 0; i < PP_FILTERS; i++) { 1033848b8605Smrg if (strcmp(pp_filters[i].name, filter) == 0) { 1034848b8605Smrg osmesa->pp_enabled[i] = enable_value; 1035848b8605Smrg return; 1036848b8605Smrg } 1037848b8605Smrg } 1038848b8605Smrg debug_warning("OSMesaPostprocess(unknown filter)\n"); 1039848b8605Smrg } 1040848b8605Smrg else { 1041848b8605Smrg debug_warning("Calling OSMesaPostprocess() after OSMesaMakeCurrent()\n"); 1042848b8605Smrg } 1043848b8605Smrg} 1044