1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg 26848b8605Smrg/* 27848b8605Smrg * Off-Screen Mesa rendering / Rendering into client memory space 28848b8605Smrg * 29848b8605Smrg * Note on thread safety: this driver is thread safe. All 30848b8605Smrg * functions are reentrant. The notion of current context is 31848b8605Smrg * managed by the core _mesa_make_current() and _mesa_get_current_context() 32848b8605Smrg * functions. Those functions are thread-safe. 33848b8605Smrg */ 34848b8605Smrg 35848b8605Smrg 36b8e80941Smrg#include <stdio.h> 37848b8605Smrg#include "main/glheader.h" 38848b8605Smrg#include "GL/osmesa.h" 39848b8605Smrg#include "main/api_exec.h" 40848b8605Smrg#include "main/context.h" 41848b8605Smrg#include "main/extensions.h" 42848b8605Smrg#include "main/formats.h" 43848b8605Smrg#include "main/framebuffer.h" 44848b8605Smrg#include "main/imports.h" 45848b8605Smrg#include "main/macros.h" 46848b8605Smrg#include "main/mipmap.h" 47848b8605Smrg#include "main/mtypes.h" 48848b8605Smrg#include "main/renderbuffer.h" 49848b8605Smrg#include "main/version.h" 50848b8605Smrg#include "main/vtxfmt.h" 51848b8605Smrg#include "swrast/swrast.h" 52848b8605Smrg#include "swrast_setup/swrast_setup.h" 53848b8605Smrg#include "swrast/s_context.h" 54848b8605Smrg#include "swrast/s_lines.h" 55848b8605Smrg#include "swrast/s_renderbuffer.h" 56848b8605Smrg#include "swrast/s_triangle.h" 57848b8605Smrg#include "tnl/tnl.h" 58848b8605Smrg#include "tnl/t_context.h" 59848b8605Smrg#include "tnl/t_pipeline.h" 60848b8605Smrg#include "drivers/common/driverfuncs.h" 61848b8605Smrg#include "drivers/common/meta.h" 62848b8605Smrg#include "vbo/vbo.h" 63848b8605Smrg 64848b8605Smrg 65848b8605Smrg#define OSMESA_RENDERBUFFER_CLASS 0x053 66848b8605Smrg 67848b8605Smrg 68848b8605Smrg/** 69848b8605Smrg * OSMesa rendering context, derived from core Mesa struct gl_context. 70848b8605Smrg */ 71848b8605Smrgstruct osmesa_context 72848b8605Smrg{ 73848b8605Smrg struct gl_context mesa; /*< Base class - this must be first */ 74848b8605Smrg struct gl_config *gl_visual; /*< Describes the buffers */ 75848b8605Smrg struct swrast_renderbuffer *srb; /*< The user's colorbuffer */ 76848b8605Smrg struct gl_framebuffer *gl_buffer; /*< The framebuffer, containing user's rb */ 77848b8605Smrg GLenum format; /*< User-specified context format */ 78848b8605Smrg GLint userRowLength; /*< user-specified number of pixels per row */ 79848b8605Smrg GLint rInd, gInd, bInd, aInd;/*< index offsets for RGBA formats */ 80848b8605Smrg GLvoid *rowaddr[SWRAST_MAX_HEIGHT]; /*< address of first pixel in each image row */ 81848b8605Smrg GLboolean yup; /*< TRUE -> Y increases upward */ 82848b8605Smrg /*< FALSE -> Y increases downward */ 83848b8605Smrg GLenum DataType; 84848b8605Smrg}; 85848b8605Smrg 86848b8605Smrg 87b8e80941Smrgstatic inline OSMesaContext 88848b8605SmrgOSMESA_CONTEXT(struct gl_context *ctx) 89848b8605Smrg{ 90848b8605Smrg /* Just cast, since we're using structure containment */ 91848b8605Smrg return (OSMesaContext) ctx; 92848b8605Smrg} 93848b8605Smrg 94848b8605Smrg 95848b8605Smrg/**********************************************************************/ 96848b8605Smrg/*** Private Device Driver Functions ***/ 97848b8605Smrg/**********************************************************************/ 98848b8605Smrg 99848b8605Smrg 100848b8605Smrgstatic const GLubyte * 101848b8605Smrgget_string( struct gl_context *ctx, GLenum name ) 102848b8605Smrg{ 103848b8605Smrg (void) ctx; 104848b8605Smrg switch (name) { 105848b8605Smrg case GL_RENDERER: 106848b8605Smrg#if CHAN_BITS == 32 107848b8605Smrg return (const GLubyte *) "Mesa OffScreen32"; 108848b8605Smrg#elif CHAN_BITS == 16 109848b8605Smrg return (const GLubyte *) "Mesa OffScreen16"; 110848b8605Smrg#else 111848b8605Smrg return (const GLubyte *) "Mesa OffScreen"; 112848b8605Smrg#endif 113848b8605Smrg default: 114848b8605Smrg return NULL; 115848b8605Smrg } 116848b8605Smrg} 117848b8605Smrg 118848b8605Smrg 119848b8605Smrgstatic void 120b8e80941Smrgosmesa_update_state(struct gl_context *ctx, GLuint new_state) 121848b8605Smrg{ 122b8e80941Smrg if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT)) 123b8e80941Smrg _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer); 124b8e80941Smrg 125848b8605Smrg /* easy - just propogate */ 126848b8605Smrg _swrast_InvalidateState( ctx, new_state ); 127848b8605Smrg _swsetup_InvalidateState( ctx, new_state ); 128848b8605Smrg _tnl_InvalidateState( ctx, new_state ); 129848b8605Smrg} 130848b8605Smrg 131b8e80941Smrgstatic void 132b8e80941Smrgosmesa_update_state_wrapper(struct gl_context *ctx) 133b8e80941Smrg{ 134b8e80941Smrg osmesa_update_state(ctx, ctx->NewState); 135b8e80941Smrg} 136848b8605Smrg 137848b8605Smrg 138848b8605Smrg/** 139848b8605Smrg * Macros for optimized line/triangle rendering. 140848b8605Smrg * Only for 8-bit channel, RGBA, BGRA, ARGB formats. 141848b8605Smrg */ 142848b8605Smrg 143848b8605Smrg#define PACK_RGBA(DST, R, G, B, A) \ 144848b8605Smrgdo { \ 145848b8605Smrg (DST)[osmesa->rInd] = R; \ 146848b8605Smrg (DST)[osmesa->gInd] = G; \ 147848b8605Smrg (DST)[osmesa->bInd] = B; \ 148848b8605Smrg (DST)[osmesa->aInd] = A; \ 149848b8605Smrg} while (0) 150848b8605Smrg 151848b8605Smrg#define PIXELADDR4(X,Y) ((GLchan *) osmesa->rowaddr[Y] + 4 * (X)) 152848b8605Smrg 153848b8605Smrg 154848b8605Smrg/** 155848b8605Smrg * Draw a flat-shaded, RGB line into an osmesa buffer. 156848b8605Smrg */ 157848b8605Smrg#define NAME flat_rgba_line 158848b8605Smrg#define CLIP_HACK 1 159848b8605Smrg#define SETUP_CODE \ 160848b8605Smrg const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 161848b8605Smrg const GLchan *color = vert1->color; 162848b8605Smrg 163848b8605Smrg#define PLOT(X, Y) \ 164848b8605Smrgdo { \ 165848b8605Smrg GLchan *p = PIXELADDR4(X, Y); \ 166848b8605Smrg PACK_RGBA(p, color[0], color[1], color[2], color[3]); \ 167848b8605Smrg} while (0) 168848b8605Smrg 169848b8605Smrg#include "swrast/s_linetemp.h" 170848b8605Smrg 171848b8605Smrg 172848b8605Smrg 173848b8605Smrg/** 174848b8605Smrg * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer. 175848b8605Smrg */ 176848b8605Smrg#define NAME flat_rgba_z_line 177848b8605Smrg#define CLIP_HACK 1 178848b8605Smrg#define INTERP_Z 1 179848b8605Smrg#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 180848b8605Smrg#define SETUP_CODE \ 181848b8605Smrg const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 182848b8605Smrg const GLchan *color = vert1->color; 183848b8605Smrg 184848b8605Smrg#define PLOT(X, Y) \ 185848b8605Smrgdo { \ 186848b8605Smrg if (Z < *zPtr) { \ 187848b8605Smrg GLchan *p = PIXELADDR4(X, Y); \ 188848b8605Smrg PACK_RGBA(p, color[RCOMP], color[GCOMP], \ 189848b8605Smrg color[BCOMP], color[ACOMP]); \ 190848b8605Smrg *zPtr = Z; \ 191848b8605Smrg } \ 192848b8605Smrg} while (0) 193848b8605Smrg 194848b8605Smrg#include "swrast/s_linetemp.h" 195848b8605Smrg 196848b8605Smrg 197848b8605Smrg 198848b8605Smrg/** 199848b8605Smrg * Analyze context state to see if we can provide a fast line drawing 200848b8605Smrg * function. Otherwise, return NULL. 201848b8605Smrg */ 202848b8605Smrgstatic swrast_line_func 203848b8605Smrgosmesa_choose_line_function( struct gl_context *ctx ) 204848b8605Smrg{ 205848b8605Smrg const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 206848b8605Smrg const SWcontext *swrast = SWRAST_CONTEXT(ctx); 207848b8605Smrg 208848b8605Smrg if (ctx->DrawBuffer && 209848b8605Smrg ctx->DrawBuffer->Visual.redBits == 32) { 210848b8605Smrg /* the special-case line functions in this file don't work 211848b8605Smrg * for float color channels. 212848b8605Smrg */ 213848b8605Smrg return NULL; 214848b8605Smrg } 215848b8605Smrg 216848b8605Smrg if (ctx->RenderMode != GL_RENDER || 217848b8605Smrg ctx->Texture._MaxEnabledTexImageUnit == -1 || 218848b8605Smrg ctx->Light.ShadeModel != GL_FLAT || 219848b8605Smrg ctx->Line.Width != 1.0F || 220848b8605Smrg ctx->Line.StippleFlag || 221848b8605Smrg ctx->Line.SmoothFlag) { 222848b8605Smrg return NULL; 223848b8605Smrg } 224848b8605Smrg 225848b8605Smrg if (osmesa->format != OSMESA_RGBA && 226848b8605Smrg osmesa->format != OSMESA_BGRA && 227848b8605Smrg osmesa->format != OSMESA_ARGB) { 228848b8605Smrg return NULL; 229848b8605Smrg } 230848b8605Smrg 231848b8605Smrg if (swrast->_RasterMask == DEPTH_BIT 232848b8605Smrg && ctx->Depth.Func == GL_LESS 233848b8605Smrg && ctx->Depth.Mask == GL_TRUE 234848b8605Smrg && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { 235848b8605Smrg return flat_rgba_z_line; 236848b8605Smrg } 237848b8605Smrg 238848b8605Smrg if (swrast->_RasterMask == 0) { 239848b8605Smrg return flat_rgba_line; 240848b8605Smrg } 241848b8605Smrg 242848b8605Smrg return (swrast_line_func) NULL; 243848b8605Smrg} 244848b8605Smrg 245848b8605Smrg 246848b8605Smrg/**********************************************************************/ 247848b8605Smrg/***** Optimized triangle rendering *****/ 248848b8605Smrg/**********************************************************************/ 249848b8605Smrg 250848b8605Smrg 251848b8605Smrg/* 252848b8605Smrg * Smooth-shaded, z-less triangle, RGBA color. 253848b8605Smrg */ 254848b8605Smrg#define NAME smooth_rgba_z_triangle 255848b8605Smrg#define INTERP_Z 1 256848b8605Smrg#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 257848b8605Smrg#define INTERP_RGB 1 258848b8605Smrg#define INTERP_ALPHA 1 259848b8605Smrg#define SETUP_CODE \ 260848b8605Smrg const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 261848b8605Smrg#define RENDER_SPAN( span ) { \ 262848b8605Smrg GLuint i; \ 263848b8605Smrg GLchan *img = PIXELADDR4(span.x, span.y); \ 264848b8605Smrg for (i = 0; i < span.end; i++, img += 4) { \ 265848b8605Smrg const GLuint z = FixedToDepth(span.z); \ 266848b8605Smrg if (z < zRow[i]) { \ 267848b8605Smrg PACK_RGBA(img, FixedToChan(span.red), \ 268848b8605Smrg FixedToChan(span.green), FixedToChan(span.blue), \ 269848b8605Smrg FixedToChan(span.alpha)); \ 270848b8605Smrg zRow[i] = z; \ 271848b8605Smrg } \ 272848b8605Smrg span.red += span.redStep; \ 273848b8605Smrg span.green += span.greenStep; \ 274848b8605Smrg span.blue += span.blueStep; \ 275848b8605Smrg span.alpha += span.alphaStep; \ 276848b8605Smrg span.z += span.zStep; \ 277848b8605Smrg } \ 278848b8605Smrg} 279848b8605Smrg#include "swrast/s_tritemp.h" 280848b8605Smrg 281848b8605Smrg 282848b8605Smrg 283848b8605Smrg/* 284848b8605Smrg * Flat-shaded, z-less triangle, RGBA color. 285848b8605Smrg */ 286848b8605Smrg#define NAME flat_rgba_z_triangle 287848b8605Smrg#define INTERP_Z 1 288848b8605Smrg#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 289848b8605Smrg#define SETUP_CODE \ 290848b8605Smrg const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 291848b8605Smrg GLuint pixel; \ 292848b8605Smrg PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1], \ 293848b8605Smrg v2->color[2], v2->color[3]); 294848b8605Smrg 295848b8605Smrg#define RENDER_SPAN( span ) { \ 296848b8605Smrg GLuint i; \ 297848b8605Smrg GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \ 298848b8605Smrg for (i = 0; i < span.end; i++) { \ 299848b8605Smrg const GLuint z = FixedToDepth(span.z); \ 300848b8605Smrg if (z < zRow[i]) { \ 301848b8605Smrg img[i] = pixel; \ 302848b8605Smrg zRow[i] = z; \ 303848b8605Smrg } \ 304848b8605Smrg span.z += span.zStep; \ 305848b8605Smrg } \ 306848b8605Smrg} 307848b8605Smrg 308848b8605Smrg#include "swrast/s_tritemp.h" 309848b8605Smrg 310848b8605Smrg 311848b8605Smrg 312848b8605Smrg/** 313848b8605Smrg * Return pointer to an optimized triangle function if possible. 314848b8605Smrg */ 315848b8605Smrgstatic swrast_tri_func 316848b8605Smrgosmesa_choose_triangle_function( struct gl_context *ctx ) 317848b8605Smrg{ 318848b8605Smrg const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 319848b8605Smrg const SWcontext *swrast = SWRAST_CONTEXT(ctx); 320848b8605Smrg 321848b8605Smrg if (ctx->DrawBuffer && 322848b8605Smrg ctx->DrawBuffer->Visual.redBits == 32) { 323848b8605Smrg /* the special-case triangle functions in this file don't work 324848b8605Smrg * for float color channels. 325848b8605Smrg */ 326848b8605Smrg return NULL; 327848b8605Smrg } 328848b8605Smrg 329848b8605Smrg if (ctx->RenderMode != GL_RENDER || 330848b8605Smrg ctx->Polygon.SmoothFlag || 331848b8605Smrg ctx->Polygon.StippleFlag || 332848b8605Smrg ctx->Texture._MaxEnabledTexImageUnit != -1) { 333848b8605Smrg return NULL; 334848b8605Smrg } 335848b8605Smrg 336848b8605Smrg if (osmesa->format != OSMESA_RGBA && 337848b8605Smrg osmesa->format != OSMESA_BGRA && 338848b8605Smrg osmesa->format != OSMESA_ARGB) { 339848b8605Smrg return NULL; 340848b8605Smrg } 341848b8605Smrg 342848b8605Smrg if (ctx->Polygon.CullFlag && 343848b8605Smrg ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { 344848b8605Smrg return NULL; 345848b8605Smrg } 346848b8605Smrg 347848b8605Smrg if (swrast->_RasterMask == DEPTH_BIT && 348848b8605Smrg ctx->Depth.Func == GL_LESS && 349848b8605Smrg ctx->Depth.Mask == GL_TRUE && 350848b8605Smrg ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { 351848b8605Smrg if (ctx->Light.ShadeModel == GL_SMOOTH) { 352848b8605Smrg return smooth_rgba_z_triangle; 353848b8605Smrg } 354848b8605Smrg else { 355848b8605Smrg return flat_rgba_z_triangle; 356848b8605Smrg } 357848b8605Smrg } 358848b8605Smrg 359848b8605Smrg return NULL; 360848b8605Smrg} 361848b8605Smrg 362848b8605Smrg 363848b8605Smrg 364848b8605Smrg/* Override for the swrast triangle-selection function. Try to use one 365848b8605Smrg * of our internal triangle functions, otherwise fall back to the 366848b8605Smrg * standard swrast functions. 367848b8605Smrg */ 368848b8605Smrgstatic void 369848b8605Smrgosmesa_choose_triangle( struct gl_context *ctx ) 370848b8605Smrg{ 371848b8605Smrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 372848b8605Smrg 373848b8605Smrg swrast->Triangle = osmesa_choose_triangle_function( ctx ); 374848b8605Smrg if (!swrast->Triangle) 375848b8605Smrg _swrast_choose_triangle( ctx ); 376848b8605Smrg} 377848b8605Smrg 378848b8605Smrgstatic void 379848b8605Smrgosmesa_choose_line( struct gl_context *ctx ) 380848b8605Smrg{ 381848b8605Smrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 382848b8605Smrg 383848b8605Smrg swrast->Line = osmesa_choose_line_function( ctx ); 384848b8605Smrg if (!swrast->Line) 385848b8605Smrg _swrast_choose_line( ctx ); 386848b8605Smrg} 387848b8605Smrg 388848b8605Smrg 389848b8605Smrg 390848b8605Smrg/** 391848b8605Smrg * Recompute the values of the context's rowaddr array. 392848b8605Smrg */ 393848b8605Smrgstatic void 394848b8605Smrgcompute_row_addresses( OSMesaContext osmesa ) 395848b8605Smrg{ 396848b8605Smrg GLint bytesPerRow, i; 397848b8605Smrg GLubyte *origin = (GLubyte *) osmesa->srb->Buffer; 398848b8605Smrg GLint rowlength; /* in pixels */ 399848b8605Smrg GLint height = osmesa->srb->Base.Height; 400848b8605Smrg 401848b8605Smrg if (osmesa->userRowLength) 402848b8605Smrg rowlength = osmesa->userRowLength; 403848b8605Smrg else 404848b8605Smrg rowlength = osmesa->srb->Base.Width; 405848b8605Smrg 406848b8605Smrg bytesPerRow = rowlength * _mesa_get_format_bytes(osmesa->srb->Base.Format); 407848b8605Smrg 408848b8605Smrg if (osmesa->yup) { 409848b8605Smrg /* Y=0 is bottom line of window */ 410848b8605Smrg for (i = 0; i < height; i++) { 411848b8605Smrg osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + i * bytesPerRow); 412848b8605Smrg } 413848b8605Smrg } 414848b8605Smrg else { 415848b8605Smrg /* Y=0 is top line of window */ 416848b8605Smrg for (i = 0; i < height; i++) { 417848b8605Smrg GLint j = height - i - 1; 418848b8605Smrg osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + j * bytesPerRow); 419848b8605Smrg } 420848b8605Smrg } 421848b8605Smrg} 422848b8605Smrg 423848b8605Smrg 424848b8605Smrg 425848b8605Smrg/** 426848b8605Smrg * Don't use _mesa_delete_renderbuffer since we can't free rb->Buffer. 427848b8605Smrg */ 428848b8605Smrgstatic void 429848b8605Smrgosmesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) 430848b8605Smrg{ 431848b8605Smrg _mesa_delete_renderbuffer(ctx, rb); 432848b8605Smrg} 433848b8605Smrg 434848b8605Smrg 435848b8605Smrg/** 436848b8605Smrg * Allocate renderbuffer storage. We don't actually allocate any storage 437848b8605Smrg * since we're using a user-provided buffer. 438848b8605Smrg * Just set up all the gl_renderbuffer methods. 439848b8605Smrg */ 440848b8605Smrgstatic GLboolean 441848b8605Smrgosmesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, 442848b8605Smrg GLenum internalFormat, GLuint width, GLuint height) 443848b8605Smrg{ 444848b8605Smrg const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 445848b8605Smrg 446848b8605Smrg /* Note: we can ignoring internalFormat for "window-system" renderbuffers */ 447848b8605Smrg (void) internalFormat; 448848b8605Smrg 449848b8605Smrg /* Given the user-provided format and type, figure out which MESA_FORMAT_x 450848b8605Smrg * to use. 451848b8605Smrg * XXX There aren't Mesa formats for all the possible combinations here! 452848b8605Smrg * XXX Specifically, there's only RGBA-order 16-bit/channel and float 453848b8605Smrg * XXX formats. 454848b8605Smrg * XXX The 8-bit/channel formats should all be OK. 455848b8605Smrg */ 456848b8605Smrg if (osmesa->format == OSMESA_RGBA) { 457848b8605Smrg if (osmesa->DataType == GL_UNSIGNED_BYTE) { 458848b8605Smrg if (_mesa_little_endian()) 459848b8605Smrg rb->Format = MESA_FORMAT_R8G8B8A8_UNORM; 460848b8605Smrg else 461848b8605Smrg rb->Format = MESA_FORMAT_A8B8G8R8_UNORM; 462848b8605Smrg } 463848b8605Smrg else if (osmesa->DataType == GL_UNSIGNED_SHORT) { 464848b8605Smrg rb->Format = MESA_FORMAT_RGBA_UNORM16; 465848b8605Smrg } 466848b8605Smrg else { 467848b8605Smrg rb->Format = MESA_FORMAT_RGBA_FLOAT32; 468848b8605Smrg } 469848b8605Smrg } 470848b8605Smrg else if (osmesa->format == OSMESA_BGRA) { 471848b8605Smrg if (osmesa->DataType == GL_UNSIGNED_BYTE) { 472848b8605Smrg if (_mesa_little_endian()) 473848b8605Smrg rb->Format = MESA_FORMAT_B8G8R8A8_UNORM; 474848b8605Smrg else 475848b8605Smrg rb->Format = MESA_FORMAT_A8R8G8B8_UNORM; 476848b8605Smrg } 477848b8605Smrg else if (osmesa->DataType == GL_UNSIGNED_SHORT) { 478848b8605Smrg _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLushort"); 479848b8605Smrg rb->Format = MESA_FORMAT_RGBA_UNORM16; /* not exactly right */ 480848b8605Smrg } 481848b8605Smrg else { 482848b8605Smrg _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLfloat"); 483848b8605Smrg rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */ 484848b8605Smrg } 485848b8605Smrg } 486848b8605Smrg else if (osmesa->format == OSMESA_ARGB) { 487848b8605Smrg if (osmesa->DataType == GL_UNSIGNED_BYTE) { 488848b8605Smrg if (_mesa_little_endian()) 489848b8605Smrg rb->Format = MESA_FORMAT_A8R8G8B8_UNORM; 490848b8605Smrg else 491848b8605Smrg rb->Format = MESA_FORMAT_B8G8R8A8_UNORM; 492848b8605Smrg } 493848b8605Smrg else if (osmesa->DataType == GL_UNSIGNED_SHORT) { 494848b8605Smrg _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLushort"); 495848b8605Smrg rb->Format = MESA_FORMAT_RGBA_UNORM16; /* not exactly right */ 496848b8605Smrg } 497848b8605Smrg else { 498848b8605Smrg _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLfloat"); 499848b8605Smrg rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */ 500848b8605Smrg } 501848b8605Smrg } 502848b8605Smrg else if (osmesa->format == OSMESA_RGB) { 503848b8605Smrg if (osmesa->DataType == GL_UNSIGNED_BYTE) { 504848b8605Smrg rb->Format = MESA_FORMAT_BGR_UNORM8; 505848b8605Smrg } 506848b8605Smrg else if (osmesa->DataType == GL_UNSIGNED_SHORT) { 507848b8605Smrg _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLushort"); 508848b8605Smrg rb->Format = MESA_FORMAT_RGBA_UNORM16; /* not exactly right */ 509848b8605Smrg } 510848b8605Smrg else { 511848b8605Smrg _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLfloat"); 512848b8605Smrg rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */ 513848b8605Smrg } 514848b8605Smrg } 515848b8605Smrg else if (osmesa->format == OSMESA_BGR) { 516848b8605Smrg if (osmesa->DataType == GL_UNSIGNED_BYTE) { 517848b8605Smrg rb->Format = MESA_FORMAT_RGB_UNORM8; 518848b8605Smrg } 519848b8605Smrg else if (osmesa->DataType == GL_UNSIGNED_SHORT) { 520848b8605Smrg _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLushort"); 521848b8605Smrg rb->Format = MESA_FORMAT_RGBA_UNORM16; /* not exactly right */ 522848b8605Smrg } 523848b8605Smrg else { 524848b8605Smrg _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLfloat"); 525848b8605Smrg rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */ 526848b8605Smrg } 527848b8605Smrg } 528848b8605Smrg else if (osmesa->format == OSMESA_RGB_565) { 529b8e80941Smrg assert(osmesa->DataType == GL_UNSIGNED_BYTE); 530848b8605Smrg rb->Format = MESA_FORMAT_B5G6R5_UNORM; 531848b8605Smrg } 532848b8605Smrg else { 533848b8605Smrg _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage"); 534848b8605Smrg } 535848b8605Smrg 536848b8605Smrg rb->Width = width; 537848b8605Smrg rb->Height = height; 538848b8605Smrg 539848b8605Smrg compute_row_addresses( osmesa ); 540848b8605Smrg 541848b8605Smrg return GL_TRUE; 542848b8605Smrg} 543848b8605Smrg 544848b8605Smrg 545848b8605Smrg/** 546848b8605Smrg * Allocate a new renderbuffer to describe the user-provided color buffer. 547848b8605Smrg */ 548848b8605Smrgstatic struct swrast_renderbuffer * 549848b8605Smrgnew_osmesa_renderbuffer(struct gl_context *ctx, GLenum format, GLenum type) 550848b8605Smrg{ 551848b8605Smrg const GLuint name = 0; 552848b8605Smrg struct swrast_renderbuffer *srb = CALLOC_STRUCT(swrast_renderbuffer); 553848b8605Smrg 554848b8605Smrg if (srb) { 555848b8605Smrg _mesa_init_renderbuffer(&srb->Base, name); 556848b8605Smrg 557848b8605Smrg srb->Base.ClassID = OSMESA_RENDERBUFFER_CLASS; 558848b8605Smrg srb->Base.Delete = osmesa_delete_renderbuffer; 559848b8605Smrg srb->Base.AllocStorage = osmesa_renderbuffer_storage; 560848b8605Smrg 561848b8605Smrg srb->Base.InternalFormat = GL_RGBA; 562848b8605Smrg srb->Base._BaseFormat = GL_RGBA; 563848b8605Smrg 564848b8605Smrg return srb; 565848b8605Smrg } 566848b8605Smrg return NULL; 567848b8605Smrg} 568848b8605Smrg 569848b8605Smrg 570848b8605Smrg 571848b8605Smrgstatic void 572848b8605Smrgosmesa_MapRenderbuffer(struct gl_context *ctx, 573848b8605Smrg struct gl_renderbuffer *rb, 574848b8605Smrg GLuint x, GLuint y, GLuint w, GLuint h, 575848b8605Smrg GLbitfield mode, 576b8e80941Smrg GLubyte **mapOut, GLint *rowStrideOut, 577b8e80941Smrg bool flip_y) 578848b8605Smrg{ 579848b8605Smrg const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 580848b8605Smrg 581848b8605Smrg if (rb->ClassID == OSMESA_RENDERBUFFER_CLASS) { 582848b8605Smrg /* this is an OSMesa renderbuffer which wraps user memory */ 583848b8605Smrg struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); 584848b8605Smrg const GLuint bpp = _mesa_get_format_bytes(rb->Format); 585848b8605Smrg GLint rowStride; /* in bytes */ 586848b8605Smrg 587848b8605Smrg if (osmesa->userRowLength) 588848b8605Smrg rowStride = osmesa->userRowLength * bpp; 589848b8605Smrg else 590848b8605Smrg rowStride = rb->Width * bpp; 591848b8605Smrg 592848b8605Smrg if (!osmesa->yup) { 593848b8605Smrg /* Y=0 is top line of window */ 594848b8605Smrg y = rb->Height - y - 1; 595848b8605Smrg *rowStrideOut = -rowStride; 596848b8605Smrg } 597848b8605Smrg else { 598848b8605Smrg *rowStrideOut = rowStride; 599848b8605Smrg } 600848b8605Smrg 601848b8605Smrg *mapOut = (GLubyte *) srb->Buffer + y * rowStride + x * bpp; 602848b8605Smrg } 603848b8605Smrg else { 604848b8605Smrg _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode, 605b8e80941Smrg mapOut, rowStrideOut, flip_y); 606848b8605Smrg } 607848b8605Smrg} 608848b8605Smrg 609848b8605Smrg 610848b8605Smrgstatic void 611848b8605Smrgosmesa_UnmapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) 612848b8605Smrg{ 613848b8605Smrg if (rb->ClassID == OSMESA_RENDERBUFFER_CLASS) { 614848b8605Smrg /* no-op */ 615848b8605Smrg } 616848b8605Smrg else { 617848b8605Smrg _swrast_unmap_soft_renderbuffer(ctx, rb); 618848b8605Smrg } 619848b8605Smrg} 620848b8605Smrg 621848b8605Smrg 622848b8605Smrg/**********************************************************************/ 623848b8605Smrg/***** Public Functions *****/ 624848b8605Smrg/**********************************************************************/ 625848b8605Smrg 626848b8605Smrg 627848b8605Smrg/** 628848b8605Smrg * Create an Off-Screen Mesa rendering context. The only attribute needed is 629848b8605Smrg * an RGBA vs Color-Index mode flag. 630848b8605Smrg * 631848b8605Smrg * Input: format - Must be GL_RGBA 632848b8605Smrg * sharelist - specifies another OSMesaContext with which to share 633848b8605Smrg * display lists. NULL indicates no sharing. 634848b8605Smrg * Return: an OSMesaContext or 0 if error 635848b8605Smrg */ 636848b8605SmrgGLAPI OSMesaContext GLAPIENTRY 637848b8605SmrgOSMesaCreateContext( GLenum format, OSMesaContext sharelist ) 638848b8605Smrg{ 639848b8605Smrg return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS, 640848b8605Smrg 8, 0, sharelist); 641848b8605Smrg} 642848b8605Smrg 643848b8605Smrg 644848b8605Smrg 645848b8605Smrg/** 646848b8605Smrg * New in Mesa 3.5 647848b8605Smrg * 648848b8605Smrg * Create context and specify size of ancillary buffers. 649848b8605Smrg */ 650848b8605SmrgGLAPI OSMesaContext GLAPIENTRY 651848b8605SmrgOSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, 652848b8605Smrg GLint accumBits, OSMesaContext sharelist ) 653b8e80941Smrg{ 654b8e80941Smrg int attribs[100], n = 0; 655b8e80941Smrg 656b8e80941Smrg attribs[n++] = OSMESA_FORMAT; 657b8e80941Smrg attribs[n++] = format; 658b8e80941Smrg attribs[n++] = OSMESA_DEPTH_BITS; 659b8e80941Smrg attribs[n++] = depthBits; 660b8e80941Smrg attribs[n++] = OSMESA_STENCIL_BITS; 661b8e80941Smrg attribs[n++] = stencilBits; 662b8e80941Smrg attribs[n++] = OSMESA_ACCUM_BITS; 663b8e80941Smrg attribs[n++] = accumBits; 664b8e80941Smrg attribs[n++] = 0; 665b8e80941Smrg 666b8e80941Smrg return OSMesaCreateContextAttribs(attribs, sharelist); 667b8e80941Smrg} 668b8e80941Smrg 669b8e80941Smrg 670b8e80941Smrg/** 671b8e80941Smrg * New in Mesa 11.2 672b8e80941Smrg * 673b8e80941Smrg * Create context with attribute list. 674b8e80941Smrg */ 675b8e80941SmrgGLAPI OSMesaContext GLAPIENTRY 676b8e80941SmrgOSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist) 677848b8605Smrg{ 678848b8605Smrg OSMesaContext osmesa; 679848b8605Smrg struct dd_function_table functions; 680848b8605Smrg GLint rind, gind, bind, aind; 681848b8605Smrg GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0; 682b8e80941Smrg GLenum format = OSMESA_RGBA; 683b8e80941Smrg GLint depthBits = 0, stencilBits = 0, accumBits = 0; 684b8e80941Smrg int profile = OSMESA_COMPAT_PROFILE, version_major = 1, version_minor = 0; 685b8e80941Smrg gl_api api_profile = API_OPENGL_COMPAT; 686b8e80941Smrg int i; 687b8e80941Smrg 688b8e80941Smrg for (i = 0; attribList[i]; i += 2) { 689b8e80941Smrg switch (attribList[i]) { 690b8e80941Smrg case OSMESA_FORMAT: 691b8e80941Smrg format = attribList[i+1]; 692b8e80941Smrg switch (format) { 693b8e80941Smrg case OSMESA_COLOR_INDEX: 694b8e80941Smrg case OSMESA_RGBA: 695b8e80941Smrg case OSMESA_BGRA: 696b8e80941Smrg case OSMESA_ARGB: 697b8e80941Smrg case OSMESA_RGB: 698b8e80941Smrg case OSMESA_BGR: 699b8e80941Smrg case OSMESA_RGB_565: 700b8e80941Smrg /* legal */ 701b8e80941Smrg break; 702b8e80941Smrg default: 703b8e80941Smrg return NULL; 704b8e80941Smrg } 705b8e80941Smrg break; 706b8e80941Smrg case OSMESA_DEPTH_BITS: 707b8e80941Smrg depthBits = attribList[i+1]; 708b8e80941Smrg if (depthBits < 0) 709b8e80941Smrg return NULL; 710b8e80941Smrg break; 711b8e80941Smrg case OSMESA_STENCIL_BITS: 712b8e80941Smrg stencilBits = attribList[i+1]; 713b8e80941Smrg if (stencilBits < 0) 714b8e80941Smrg return NULL; 715b8e80941Smrg break; 716b8e80941Smrg case OSMESA_ACCUM_BITS: 717b8e80941Smrg accumBits = attribList[i+1]; 718b8e80941Smrg if (accumBits < 0) 719b8e80941Smrg return NULL; 720b8e80941Smrg break; 721b8e80941Smrg case OSMESA_PROFILE: 722b8e80941Smrg profile = attribList[i+1]; 723b8e80941Smrg if (profile == OSMESA_COMPAT_PROFILE) 724b8e80941Smrg api_profile = API_OPENGL_COMPAT; 725b8e80941Smrg else if (profile == OSMESA_CORE_PROFILE) 726b8e80941Smrg api_profile = API_OPENGL_CORE; 727b8e80941Smrg else 728b8e80941Smrg return NULL; 729b8e80941Smrg break; 730b8e80941Smrg case OSMESA_CONTEXT_MAJOR_VERSION: 731b8e80941Smrg version_major = attribList[i+1]; 732b8e80941Smrg if (version_major < 1) 733b8e80941Smrg return NULL; 734b8e80941Smrg break; 735b8e80941Smrg case OSMESA_CONTEXT_MINOR_VERSION: 736b8e80941Smrg version_minor = attribList[i+1]; 737b8e80941Smrg if (version_minor < 0) 738b8e80941Smrg return NULL; 739b8e80941Smrg break; 740b8e80941Smrg case 0: 741b8e80941Smrg /* end of list */ 742b8e80941Smrg break; 743b8e80941Smrg default: 744b8e80941Smrg fprintf(stderr, "Bad attribute in OSMesaCreateContextAttribs()\n"); 745b8e80941Smrg return NULL; 746b8e80941Smrg } 747b8e80941Smrg } 748848b8605Smrg 749848b8605Smrg rind = gind = bind = aind = 0; 750848b8605Smrg if (format==OSMESA_RGBA) { 751848b8605Smrg redBits = CHAN_BITS; 752848b8605Smrg greenBits = CHAN_BITS; 753848b8605Smrg blueBits = CHAN_BITS; 754848b8605Smrg alphaBits = CHAN_BITS; 755848b8605Smrg rind = 0; 756848b8605Smrg gind = 1; 757848b8605Smrg bind = 2; 758848b8605Smrg aind = 3; 759848b8605Smrg } 760848b8605Smrg else if (format==OSMESA_BGRA) { 761848b8605Smrg redBits = CHAN_BITS; 762848b8605Smrg greenBits = CHAN_BITS; 763848b8605Smrg blueBits = CHAN_BITS; 764848b8605Smrg alphaBits = CHAN_BITS; 765848b8605Smrg bind = 0; 766848b8605Smrg gind = 1; 767848b8605Smrg rind = 2; 768848b8605Smrg aind = 3; 769848b8605Smrg } 770848b8605Smrg else if (format==OSMESA_ARGB) { 771848b8605Smrg redBits = CHAN_BITS; 772848b8605Smrg greenBits = CHAN_BITS; 773848b8605Smrg blueBits = CHAN_BITS; 774848b8605Smrg alphaBits = CHAN_BITS; 775848b8605Smrg aind = 0; 776848b8605Smrg rind = 1; 777848b8605Smrg gind = 2; 778848b8605Smrg bind = 3; 779848b8605Smrg } 780848b8605Smrg else if (format==OSMESA_RGB) { 781848b8605Smrg redBits = CHAN_BITS; 782848b8605Smrg greenBits = CHAN_BITS; 783848b8605Smrg blueBits = CHAN_BITS; 784848b8605Smrg alphaBits = 0; 785848b8605Smrg rind = 0; 786848b8605Smrg gind = 1; 787848b8605Smrg bind = 2; 788848b8605Smrg } 789848b8605Smrg else if (format==OSMESA_BGR) { 790848b8605Smrg redBits = CHAN_BITS; 791848b8605Smrg greenBits = CHAN_BITS; 792848b8605Smrg blueBits = CHAN_BITS; 793848b8605Smrg alphaBits = 0; 794848b8605Smrg rind = 2; 795848b8605Smrg gind = 1; 796848b8605Smrg bind = 0; 797848b8605Smrg } 798848b8605Smrg#if CHAN_TYPE == GL_UNSIGNED_BYTE 799848b8605Smrg else if (format==OSMESA_RGB_565) { 800848b8605Smrg redBits = 5; 801848b8605Smrg greenBits = 6; 802848b8605Smrg blueBits = 5; 803848b8605Smrg alphaBits = 0; 804848b8605Smrg rind = 0; /* not used */ 805848b8605Smrg gind = 0; 806848b8605Smrg bind = 0; 807848b8605Smrg } 808848b8605Smrg#endif 809848b8605Smrg else { 810848b8605Smrg return NULL; 811848b8605Smrg } 812848b8605Smrg 813848b8605Smrg osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); 814848b8605Smrg if (osmesa) { 815848b8605Smrg osmesa->gl_visual = _mesa_create_visual( GL_FALSE, /* double buffer */ 816848b8605Smrg GL_FALSE, /* stereo */ 817848b8605Smrg redBits, 818848b8605Smrg greenBits, 819848b8605Smrg blueBits, 820848b8605Smrg alphaBits, 821848b8605Smrg depthBits, 822848b8605Smrg stencilBits, 823848b8605Smrg accumBits, 824848b8605Smrg accumBits, 825848b8605Smrg accumBits, 826848b8605Smrg alphaBits ? accumBits : 0, 827848b8605Smrg 1 /* num samples */ 828848b8605Smrg ); 829848b8605Smrg if (!osmesa->gl_visual) { 830848b8605Smrg free(osmesa); 831848b8605Smrg return NULL; 832848b8605Smrg } 833848b8605Smrg 834848b8605Smrg /* Initialize device driver function table */ 835848b8605Smrg _mesa_init_driver_functions(&functions); 836b8e80941Smrg _tnl_init_driver_draw_function(&functions); 837848b8605Smrg /* override with our functions */ 838848b8605Smrg functions.GetString = get_string; 839b8e80941Smrg functions.UpdateState = osmesa_update_state_wrapper; 840848b8605Smrg 841848b8605Smrg if (!_mesa_initialize_context(&osmesa->mesa, 842b8e80941Smrg api_profile, 843848b8605Smrg osmesa->gl_visual, 844848b8605Smrg sharelist ? &sharelist->mesa 845848b8605Smrg : (struct gl_context *) NULL, 846848b8605Smrg &functions)) { 847848b8605Smrg _mesa_destroy_visual( osmesa->gl_visual ); 848848b8605Smrg free(osmesa); 849848b8605Smrg return NULL; 850848b8605Smrg } 851848b8605Smrg 852848b8605Smrg _mesa_enable_sw_extensions(&(osmesa->mesa)); 853848b8605Smrg 854848b8605Smrg osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual); 855848b8605Smrg if (!osmesa->gl_buffer) { 856848b8605Smrg _mesa_destroy_visual( osmesa->gl_visual ); 857b8e80941Smrg _mesa_free_context_data(&osmesa->mesa, true); 858848b8605Smrg free(osmesa); 859848b8605Smrg return NULL; 860848b8605Smrg } 861848b8605Smrg 862848b8605Smrg /* Create depth/stencil/accum buffers. We'll create the color 863848b8605Smrg * buffer later in OSMesaMakeCurrent(). 864848b8605Smrg */ 865848b8605Smrg _swrast_add_soft_renderbuffers(osmesa->gl_buffer, 866848b8605Smrg GL_FALSE, /* color */ 867848b8605Smrg osmesa->gl_visual->haveDepthBuffer, 868848b8605Smrg osmesa->gl_visual->haveStencilBuffer, 869848b8605Smrg osmesa->gl_visual->haveAccumBuffer, 870848b8605Smrg GL_FALSE, /* alpha */ 871848b8605Smrg GL_FALSE /* aux */ ); 872848b8605Smrg 873848b8605Smrg osmesa->format = format; 874848b8605Smrg osmesa->userRowLength = 0; 875848b8605Smrg osmesa->yup = GL_TRUE; 876848b8605Smrg osmesa->rInd = rind; 877848b8605Smrg osmesa->gInd = gind; 878848b8605Smrg osmesa->bInd = bind; 879848b8605Smrg osmesa->aInd = aind; 880848b8605Smrg 881848b8605Smrg _mesa_meta_init(&osmesa->mesa); 882848b8605Smrg 883848b8605Smrg /* Initialize the software rasterizer and helper modules. */ 884848b8605Smrg { 885848b8605Smrg struct gl_context *ctx = &osmesa->mesa; 886848b8605Smrg SWcontext *swrast; 887848b8605Smrg TNLcontext *tnl; 888848b8605Smrg 889848b8605Smrg if (!_swrast_CreateContext( ctx ) || 890848b8605Smrg !_vbo_CreateContext( ctx ) || 891848b8605Smrg !_tnl_CreateContext( ctx ) || 892848b8605Smrg !_swsetup_CreateContext( ctx )) { 893848b8605Smrg _mesa_destroy_visual(osmesa->gl_visual); 894b8e80941Smrg _mesa_free_context_data(ctx, true); 895848b8605Smrg free(osmesa); 896848b8605Smrg return NULL; 897848b8605Smrg } 898848b8605Smrg 899848b8605Smrg _swsetup_Wakeup( ctx ); 900848b8605Smrg 901848b8605Smrg /* use default TCL pipeline */ 902848b8605Smrg tnl = TNL_CONTEXT(ctx); 903848b8605Smrg tnl->Driver.RunPipeline = _tnl_run_pipeline; 904848b8605Smrg 905848b8605Smrg ctx->Driver.MapRenderbuffer = osmesa_MapRenderbuffer; 906848b8605Smrg ctx->Driver.UnmapRenderbuffer = osmesa_UnmapRenderbuffer; 907848b8605Smrg 908848b8605Smrg ctx->Driver.GenerateMipmap = _mesa_generate_mipmap; 909848b8605Smrg 910848b8605Smrg /* Extend the software rasterizer with our optimized line and triangle 911848b8605Smrg * drawing functions. 912848b8605Smrg */ 913848b8605Smrg swrast = SWRAST_CONTEXT( ctx ); 914848b8605Smrg swrast->choose_line = osmesa_choose_line; 915848b8605Smrg swrast->choose_triangle = osmesa_choose_triangle; 916848b8605Smrg 917b8e80941Smrg _mesa_override_extensions(ctx); 918848b8605Smrg _mesa_compute_version(ctx); 919848b8605Smrg 920b8e80941Smrg if (ctx->Version < version_major * 10 + version_minor) { 921b8e80941Smrg _mesa_destroy_visual(osmesa->gl_visual); 922b8e80941Smrg _mesa_free_context_data(ctx, true); 923b8e80941Smrg free(osmesa); 924b8e80941Smrg return NULL; 925b8e80941Smrg } 926b8e80941Smrg 927848b8605Smrg /* Exec table initialization requires the version to be computed */ 928848b8605Smrg _mesa_initialize_dispatch_tables(ctx); 929848b8605Smrg _mesa_initialize_vbo_vtxfmt(ctx); 930848b8605Smrg } 931848b8605Smrg } 932848b8605Smrg return osmesa; 933848b8605Smrg} 934848b8605Smrg 935848b8605Smrg 936848b8605Smrg/** 937848b8605Smrg * Destroy an Off-Screen Mesa rendering context. 938848b8605Smrg * 939848b8605Smrg * \param osmesa the context to destroy 940848b8605Smrg */ 941848b8605SmrgGLAPI void GLAPIENTRY 942848b8605SmrgOSMesaDestroyContext( OSMesaContext osmesa ) 943848b8605Smrg{ 944848b8605Smrg if (osmesa) { 945848b8605Smrg if (osmesa->srb) 946848b8605Smrg _mesa_reference_renderbuffer((struct gl_renderbuffer **) &osmesa->srb, NULL); 947848b8605Smrg 948848b8605Smrg _mesa_meta_free( &osmesa->mesa ); 949848b8605Smrg 950848b8605Smrg _swsetup_DestroyContext( &osmesa->mesa ); 951848b8605Smrg _tnl_DestroyContext( &osmesa->mesa ); 952848b8605Smrg _vbo_DestroyContext( &osmesa->mesa ); 953848b8605Smrg _swrast_DestroyContext( &osmesa->mesa ); 954848b8605Smrg 955848b8605Smrg _mesa_destroy_visual( osmesa->gl_visual ); 956848b8605Smrg _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL ); 957848b8605Smrg 958b8e80941Smrg _mesa_free_context_data(&osmesa->mesa, true); 959848b8605Smrg free( osmesa ); 960848b8605Smrg } 961848b8605Smrg} 962848b8605Smrg 963848b8605Smrg 964848b8605Smrg/** 965848b8605Smrg * Bind an OSMesaContext to an image buffer. The image buffer is just a 966848b8605Smrg * block of memory which the client provides. Its size must be at least 967848b8605Smrg * as large as width*height*sizeof(type). Its address should be a multiple 968848b8605Smrg * of 4 if using RGBA mode. 969848b8605Smrg * 970848b8605Smrg * Image data is stored in the order of glDrawPixels: row-major order 971848b8605Smrg * with the lower-left image pixel stored in the first array position 972848b8605Smrg * (ie. bottom-to-top). 973848b8605Smrg * 974848b8605Smrg * If the context's viewport hasn't been initialized yet, it will now be 975848b8605Smrg * initialized to (0,0,width,height). 976848b8605Smrg * 977b8e80941Smrg * If both the context and the buffer are null, the current context will be 978b8e80941Smrg * unbound. 979b8e80941Smrg * 980848b8605Smrg * Input: osmesa - the rendering context 981848b8605Smrg * buffer - the image buffer memory 982848b8605Smrg * type - data type for pixel components 983848b8605Smrg * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5 984848b8605Smrg * are supported. But if Mesa's been compiled with CHAN_BITS==16 985848b8605Smrg * then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. And if 986848b8605Smrg * Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT, 987848b8605Smrg * GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. 988848b8605Smrg * width, height - size of image buffer in pixels, at least 1 989848b8605Smrg * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa, 990848b8605Smrg * invalid buffer address, invalid type, width<1, height<1, 991848b8605Smrg * width>internal limit or height>internal limit. 992848b8605Smrg */ 993848b8605SmrgGLAPI GLboolean GLAPIENTRY 994848b8605SmrgOSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type, 995848b8605Smrg GLsizei width, GLsizei height ) 996848b8605Smrg{ 997b8e80941Smrg if (!osmesa && !buffer) { 998b8e80941Smrg return _mesa_make_current(NULL, NULL, NULL); 999b8e80941Smrg } 1000b8e80941Smrg 1001848b8605Smrg if (!osmesa || !buffer || 1002848b8605Smrg width < 1 || height < 1 || 1003848b8605Smrg width > SWRAST_MAX_WIDTH || height > SWRAST_MAX_HEIGHT) { 1004848b8605Smrg return GL_FALSE; 1005848b8605Smrg } 1006848b8605Smrg 1007848b8605Smrg if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) { 1008848b8605Smrg return GL_FALSE; 1009848b8605Smrg } 1010848b8605Smrg 1011848b8605Smrg#if 0 1012848b8605Smrg if (!(type == GL_UNSIGNED_BYTE || 1013848b8605Smrg (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) || 1014848b8605Smrg (type == GL_FLOAT && CHAN_BITS == 32))) { 1015848b8605Smrg /* i.e. is sizeof(type) * 8 > CHAN_BITS? */ 1016848b8605Smrg return GL_FALSE; 1017848b8605Smrg } 1018848b8605Smrg#endif 1019848b8605Smrg 1020848b8605Smrg osmesa_update_state( &osmesa->mesa, 0 ); 1021848b8605Smrg 1022848b8605Smrg /* Create a front/left color buffer which wraps the user-provided buffer. 1023848b8605Smrg * There is no back color buffer. 1024848b8605Smrg * If the user tries to use a 8, 16 or 32-bit/channel buffer that 1025848b8605Smrg * doesn't match what Mesa was compiled for (CHAN_BITS) the 1026b8e80941Smrg * _mesa_attach_and_reference_rb() function will create a "wrapper" 1027b8e80941Smrg * renderbuffer that converts rendering from CHAN_BITS to the 1028b8e80941Smrg * user-requested channel size. 1029848b8605Smrg */ 1030848b8605Smrg if (!osmesa->srb) { 1031848b8605Smrg osmesa->srb = new_osmesa_renderbuffer(&osmesa->mesa, osmesa->format, type); 1032848b8605Smrg _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT); 1033b8e80941Smrg _mesa_attach_and_reference_rb(osmesa->gl_buffer, BUFFER_FRONT_LEFT, 1034b8e80941Smrg &osmesa->srb->Base); 1035848b8605Smrg assert(osmesa->srb->Base.RefCount == 2); 1036848b8605Smrg } 1037848b8605Smrg 1038848b8605Smrg osmesa->DataType = type; 1039848b8605Smrg 1040848b8605Smrg /* Set renderbuffer fields. Set width/height = 0 to force 1041848b8605Smrg * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer() 1042848b8605Smrg */ 1043848b8605Smrg osmesa->srb->Buffer = buffer; 1044848b8605Smrg osmesa->srb->Base.Width = osmesa->srb->Base.Height = 0; 1045848b8605Smrg 1046848b8605Smrg /* Set the framebuffer's size. This causes the 1047848b8605Smrg * osmesa_renderbuffer_storage() function to get called. 1048848b8605Smrg */ 1049848b8605Smrg _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height); 1050848b8605Smrg 1051848b8605Smrg _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer ); 1052848b8605Smrg 1053848b8605Smrg /* Remove renderbuffer attachment, then re-add. This installs the 1054848b8605Smrg * renderbuffer adaptor/wrapper if needed (for bpp conversion). 1055848b8605Smrg */ 1056848b8605Smrg _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT); 1057b8e80941Smrg _mesa_attach_and_reference_rb(osmesa->gl_buffer, BUFFER_FRONT_LEFT, 1058b8e80941Smrg &osmesa->srb->Base); 1059848b8605Smrg 1060848b8605Smrg 1061848b8605Smrg /* this updates the visual's red/green/blue/alphaBits fields */ 1062848b8605Smrg _mesa_update_framebuffer_visual(&osmesa->mesa, osmesa->gl_buffer); 1063848b8605Smrg 1064848b8605Smrg /* update the framebuffer size */ 1065848b8605Smrg _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height); 1066848b8605Smrg 1067848b8605Smrg return GL_TRUE; 1068848b8605Smrg} 1069848b8605Smrg 1070848b8605Smrg 1071848b8605Smrg 1072848b8605SmrgGLAPI OSMesaContext GLAPIENTRY 1073848b8605SmrgOSMesaGetCurrentContext( void ) 1074848b8605Smrg{ 1075848b8605Smrg struct gl_context *ctx = _mesa_get_current_context(); 1076848b8605Smrg if (ctx) 1077848b8605Smrg return (OSMesaContext) ctx; 1078848b8605Smrg else 1079848b8605Smrg return NULL; 1080848b8605Smrg} 1081848b8605Smrg 1082848b8605Smrg 1083848b8605Smrg 1084848b8605SmrgGLAPI void GLAPIENTRY 1085848b8605SmrgOSMesaPixelStore( GLint pname, GLint value ) 1086848b8605Smrg{ 1087848b8605Smrg OSMesaContext osmesa = OSMesaGetCurrentContext(); 1088848b8605Smrg 1089848b8605Smrg switch (pname) { 1090848b8605Smrg case OSMESA_ROW_LENGTH: 1091848b8605Smrg if (value<0) { 1092848b8605Smrg _mesa_error( &osmesa->mesa, GL_INVALID_VALUE, 1093848b8605Smrg "OSMesaPixelStore(value)" ); 1094848b8605Smrg return; 1095848b8605Smrg } 1096848b8605Smrg osmesa->userRowLength = value; 1097848b8605Smrg break; 1098848b8605Smrg case OSMESA_Y_UP: 1099848b8605Smrg osmesa->yup = value ? GL_TRUE : GL_FALSE; 1100848b8605Smrg break; 1101848b8605Smrg default: 1102848b8605Smrg _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); 1103848b8605Smrg return; 1104848b8605Smrg } 1105848b8605Smrg 1106848b8605Smrg compute_row_addresses( osmesa ); 1107848b8605Smrg} 1108848b8605Smrg 1109848b8605Smrg 1110848b8605SmrgGLAPI void GLAPIENTRY 1111848b8605SmrgOSMesaGetIntegerv( GLint pname, GLint *value ) 1112848b8605Smrg{ 1113848b8605Smrg OSMesaContext osmesa = OSMesaGetCurrentContext(); 1114848b8605Smrg 1115848b8605Smrg switch (pname) { 1116848b8605Smrg case OSMESA_WIDTH: 1117848b8605Smrg if (osmesa->gl_buffer) 1118848b8605Smrg *value = osmesa->gl_buffer->Width; 1119848b8605Smrg else 1120848b8605Smrg *value = 0; 1121848b8605Smrg return; 1122848b8605Smrg case OSMESA_HEIGHT: 1123848b8605Smrg if (osmesa->gl_buffer) 1124848b8605Smrg *value = osmesa->gl_buffer->Height; 1125848b8605Smrg else 1126848b8605Smrg *value = 0; 1127848b8605Smrg return; 1128848b8605Smrg case OSMESA_FORMAT: 1129848b8605Smrg *value = osmesa->format; 1130848b8605Smrg return; 1131848b8605Smrg case OSMESA_TYPE: 1132848b8605Smrg /* current color buffer's data type */ 1133848b8605Smrg *value = osmesa->DataType; 1134848b8605Smrg return; 1135848b8605Smrg case OSMESA_ROW_LENGTH: 1136848b8605Smrg *value = osmesa->userRowLength; 1137848b8605Smrg return; 1138848b8605Smrg case OSMESA_Y_UP: 1139848b8605Smrg *value = osmesa->yup; 1140848b8605Smrg return; 1141848b8605Smrg case OSMESA_MAX_WIDTH: 1142848b8605Smrg *value = SWRAST_MAX_WIDTH; 1143848b8605Smrg return; 1144848b8605Smrg case OSMESA_MAX_HEIGHT: 1145848b8605Smrg *value = SWRAST_MAX_HEIGHT; 1146848b8605Smrg return; 1147848b8605Smrg default: 1148848b8605Smrg _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)"); 1149848b8605Smrg return; 1150848b8605Smrg } 1151848b8605Smrg} 1152848b8605Smrg 1153848b8605Smrg 1154848b8605Smrg/** 1155848b8605Smrg * Return the depth buffer associated with an OSMesa context. 1156848b8605Smrg * Input: c - the OSMesa context 1157848b8605Smrg * Output: width, height - size of buffer in pixels 1158848b8605Smrg * bytesPerValue - bytes per depth value (2 or 4) 1159848b8605Smrg * buffer - pointer to depth buffer values 1160848b8605Smrg * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1161848b8605Smrg */ 1162848b8605SmrgGLAPI GLboolean GLAPIENTRY 1163848b8605SmrgOSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, 1164848b8605Smrg GLint *bytesPerValue, void **buffer ) 1165848b8605Smrg{ 1166848b8605Smrg struct swrast_renderbuffer *srb = NULL; 1167848b8605Smrg 1168848b8605Smrg if (c->gl_buffer) 1169848b8605Smrg srb = swrast_renderbuffer(c->gl_buffer-> 1170848b8605Smrg Attachment[BUFFER_DEPTH].Renderbuffer); 1171848b8605Smrg 1172848b8605Smrg if (!srb || !srb->Buffer) { 1173848b8605Smrg *width = 0; 1174848b8605Smrg *height = 0; 1175848b8605Smrg *bytesPerValue = 0; 1176848b8605Smrg *buffer = 0; 1177848b8605Smrg return GL_FALSE; 1178848b8605Smrg } 1179848b8605Smrg else { 1180848b8605Smrg *width = srb->Base.Width; 1181848b8605Smrg *height = srb->Base.Height; 1182848b8605Smrg if (c->gl_visual->depthBits <= 16) 1183848b8605Smrg *bytesPerValue = sizeof(GLushort); 1184848b8605Smrg else 1185848b8605Smrg *bytesPerValue = sizeof(GLuint); 1186848b8605Smrg *buffer = (void *) srb->Buffer; 1187848b8605Smrg return GL_TRUE; 1188848b8605Smrg } 1189848b8605Smrg} 1190848b8605Smrg 1191848b8605Smrg 1192848b8605Smrg/** 1193848b8605Smrg * Return the color buffer associated with an OSMesa context. 1194848b8605Smrg * Input: c - the OSMesa context 1195848b8605Smrg * Output: width, height - size of buffer in pixels 1196848b8605Smrg * format - the pixel format (OSMESA_FORMAT) 1197848b8605Smrg * buffer - pointer to color buffer values 1198848b8605Smrg * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1199848b8605Smrg */ 1200848b8605SmrgGLAPI GLboolean GLAPIENTRY 1201848b8605SmrgOSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width, 1202848b8605Smrg GLint *height, GLint *format, void **buffer ) 1203848b8605Smrg{ 1204848b8605Smrg if (osmesa->srb && osmesa->srb->Buffer) { 1205848b8605Smrg *width = osmesa->srb->Base.Width; 1206848b8605Smrg *height = osmesa->srb->Base.Height; 1207848b8605Smrg *format = osmesa->format; 1208848b8605Smrg *buffer = (void *) osmesa->srb->Buffer; 1209848b8605Smrg return GL_TRUE; 1210848b8605Smrg } 1211848b8605Smrg else { 1212848b8605Smrg *width = 0; 1213848b8605Smrg *height = 0; 1214848b8605Smrg *format = 0; 1215848b8605Smrg *buffer = 0; 1216848b8605Smrg return GL_FALSE; 1217848b8605Smrg } 1218848b8605Smrg} 1219848b8605Smrg 1220848b8605Smrg 1221848b8605Smrgstruct name_function 1222848b8605Smrg{ 1223848b8605Smrg const char *Name; 1224848b8605Smrg OSMESAproc Function; 1225848b8605Smrg}; 1226848b8605Smrg 1227848b8605Smrgstatic struct name_function functions[] = { 1228848b8605Smrg { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext }, 1229848b8605Smrg { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt }, 1230b8e80941Smrg { "OSMesaCreateContextAttribs", (OSMESAproc) OSMesaCreateContextAttribs }, 1231848b8605Smrg { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext }, 1232848b8605Smrg { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent }, 1233848b8605Smrg { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext }, 1234b8e80941Smrg { "OSMesaPixelStore", (OSMESAproc) OSMesaPixelStore }, 1235848b8605Smrg { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv }, 1236848b8605Smrg { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer }, 1237848b8605Smrg { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer }, 1238848b8605Smrg { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress }, 1239848b8605Smrg { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp }, 1240848b8605Smrg { "OSMesaPostprocess", (OSMESAproc) OSMesaPostprocess }, 1241848b8605Smrg { NULL, NULL } 1242848b8605Smrg}; 1243848b8605Smrg 1244848b8605Smrg 1245848b8605SmrgGLAPI OSMESAproc GLAPIENTRY 1246848b8605SmrgOSMesaGetProcAddress( const char *funcName ) 1247848b8605Smrg{ 1248848b8605Smrg int i; 1249848b8605Smrg for (i = 0; functions[i].Name; i++) { 1250848b8605Smrg if (strcmp(functions[i].Name, funcName) == 0) 1251848b8605Smrg return functions[i].Function; 1252848b8605Smrg } 1253848b8605Smrg return _glapi_get_proc_address(funcName); 1254848b8605Smrg} 1255848b8605Smrg 1256848b8605Smrg 1257848b8605SmrgGLAPI void GLAPIENTRY 1258848b8605SmrgOSMesaColorClamp(GLboolean enable) 1259848b8605Smrg{ 1260848b8605Smrg OSMesaContext osmesa = OSMesaGetCurrentContext(); 1261848b8605Smrg 1262848b8605Smrg if (enable == GL_TRUE) { 1263848b8605Smrg osmesa->mesa.Color.ClampFragmentColor = GL_TRUE; 1264848b8605Smrg } 1265848b8605Smrg else { 1266848b8605Smrg osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB; 1267848b8605Smrg } 1268848b8605Smrg} 1269848b8605Smrg 1270848b8605Smrg 1271848b8605SmrgGLAPI void GLAPIENTRY 1272848b8605SmrgOSMesaPostprocess(OSMesaContext osmesa, const char *filter, 1273848b8605Smrg unsigned enable_value) 1274848b8605Smrg{ 1275848b8605Smrg fprintf(stderr, 1276848b8605Smrg "OSMesaPostProcess() is only available with gallium drivers\n"); 1277848b8605Smrg} 1278848b8605Smrg 1279848b8605Smrg 1280848b8605Smrg 1281848b8605Smrg/** 1282848b8605Smrg * When GLX_INDIRECT_RENDERING is defined, some symbols are missing in 1283848b8605Smrg * libglapi.a. We need to define them here. 1284848b8605Smrg */ 1285848b8605Smrg#ifdef GLX_INDIRECT_RENDERING 1286848b8605Smrg 1287848b8605Smrg#define GL_GLEXT_PROTOTYPES 1288848b8605Smrg#include "GL/gl.h" 1289848b8605Smrg#include "glapi/glapi.h" 1290b8e80941Smrg#include "glapitable.h" 1291848b8605Smrg 1292848b8605Smrg#if defined(USE_MGL_NAMESPACE) 1293848b8605Smrg#define NAME(func) mgl##func 1294848b8605Smrg#else 1295848b8605Smrg#define NAME(func) gl##func 1296848b8605Smrg#endif 1297848b8605Smrg 1298848b8605Smrg#define DISPATCH(FUNC, ARGS, MESSAGE) \ 1299848b8605Smrg GET_DISPATCH()->FUNC ARGS 1300848b8605Smrg 1301848b8605Smrg#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \ 1302848b8605Smrg return GET_DISPATCH()->FUNC ARGS 1303848b8605Smrg 1304848b8605Smrg/* skip normal ones */ 1305848b8605Smrg#define _GLAPI_SKIP_NORMAL_ENTRY_POINTS 1306b8e80941Smrg#include "glapitemp.h" 1307848b8605Smrg 1308848b8605Smrg#endif /* GLX_INDIRECT_RENDERING */ 1309