1/* 2 * Copyright 2006-2011, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jérôme Duval, korli@users.berlios.de 7 * Philippe Houdoin, philippe.houdoin@free.fr 8 * Artur Wyszynski, harakash@gmail.com 9 * Alexander von Gluck, kallisti5@unixzen.com 10 */ 11/* 12 * Mesa 3-D graphics library 13 * Version: 6.1 14 * 15 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. 16 */ 17 18 19#include "MesaSoftwareRenderer.h" 20 21#include <Autolock.h> 22#include <DirectWindowPrivate.h> 23#include <GraphicsDefs.h> 24#include <Screen.h> 25#include <stdio.h> 26#include <string.h> 27 28extern "C" { 29#include "extensions.h" 30#include "drivers/common/driverfuncs.h" 31#include "drivers/common/meta.h" 32#include "main/colormac.h" 33#include "main/cpuinfo.h" 34#include "main/buffers.h" 35#include "main/formats.h" 36#include "main/framebuffer.h" 37#include "main/renderbuffer.h" 38#include "swrast/swrast.h" 39#include "swrast_setup/swrast_setup.h" 40#include "tnl/tnl.h" 41#include "tnl/t_context.h" 42#include "tnl/t_pipeline.h" 43#include "vbo/vbo.h" 44 45 46//#define TRACE_SOFTGL 47#ifdef TRACE_SOFTGL 48# define TRACE(x...) printf("MesaSoftwareRenderer: " x) 49# define CALLED() printf("MesaSoftwareRenderer: %s\n", __PRETTY_FUNCTION__) 50#else 51# define TRACE(x...) 52# define CALLED() 53#endif 54 55#define ERROR(x...) printf("MesaSoftwareRenderer: " x) 56} 57 58 59extern const char* color_space_name(color_space space); 60 61 62// BeOS component ordering for B_RGBA32 bitmap format 63#if B_HOST_IS_LENDIAN 64#define BE_RCOMP 2 65#define BE_GCOMP 1 66#define BE_BCOMP 0 67#define BE_ACOMP 3 68#else 69// Big Endian B_RGBA32 bitmap format 70#define BE_RCOMP 1 71#define BE_GCOMP 2 72#define BE_BCOMP 3 73#define BE_ACOMP 0 74#endif 75 76 77/**********************************************************************/ 78/***** Read/write spans/arrays of pixels *****/ 79/**********************************************************************/ 80extern "C" { 81 82/* 32-bit RGBA */ 83#define NAME(PREFIX) PREFIX##_RGBA32 84#define RB_TYPE GLubyte 85#define SPAN_VARS \ 86 MesaSoftwareRenderer* mr = (MesaSoftwareRenderer*)ctx->DriverCtx; 87#define INIT_PIXEL_PTR(P, X, Y) \ 88 GLubyte* P = ((GLubyte**)mr->GetRows())[Y] + (X) * 4 89#define INC_PIXEL_PTR(P) P += 4 90#define STORE_PIXEL(DST, X, Y, VALUE) \ 91 DST[BE_RCOMP] = VALUE[RCOMP]; \ 92 DST[BE_GCOMP] = VALUE[GCOMP]; \ 93 DST[BE_BCOMP] = VALUE[BCOMP]; \ 94 DST[BE_ACOMP] = VALUE[ACOMP] 95#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ 96 DST[BE_RCOMP] = VALUE[RCOMP]; \ 97 DST[BE_GCOMP] = VALUE[GCOMP]; \ 98 DST[BE_BCOMP] = VALUE[BCOMP]; \ 99 DST[BE_ACOMP] = 255 100#define FETCH_PIXEL(DST, SRC) \ 101 DST[RCOMP] = SRC[BE_RCOMP]; \ 102 DST[GCOMP] = SRC[BE_GCOMP]; \ 103 DST[BCOMP] = SRC[BE_BCOMP]; \ 104 DST[ACOMP] = SRC[BE_ACOMP] 105#include "swrast/s_spantemp.h" 106 107/* 32-bit RGB */ 108#define NAME(PREFIX) PREFIX##_RGB32 109#define RB_TYPE GLubyte 110#define SPAN_VARS \ 111 MesaSoftwareRenderer* mr = (MesaSoftwareRenderer*)ctx->DriverCtx; 112#define INIT_PIXEL_PTR(P, X, Y) \ 113 GLuint* P = (GLuint*)(((GLubyte**)mr->GetRows())[Y] + (X) * 4) 114#define INC_PIXEL_PTR(P) P += 1 115#define STORE_PIXEL(DST, X, Y, VALUE) \ 116 *DST = ( ((VALUE[RCOMP]) << 16) | \ 117 ((VALUE[GCOMP]) << 8) | \ 118 ((VALUE[BCOMP]) ) ) 119#define FETCH_PIXEL(DST, SRC) \ 120 DST[RCOMP] = ((*SRC & 0x00ff0000) >> 16); \ 121 DST[GCOMP] = ((*SRC & 0x0000ff00) >> 8); \ 122 DST[BCOMP] = ((*SRC & 0x000000ff)); \ 123 DST[ACOMP] = 0xff; 124#include "swrast/s_spantemp.h" 125 126/* 24-bit RGB */ 127#define NAME(PREFIX) PREFIX##_RGB24 128#define RB_TYPE GLubyte 129#define SPAN_VARS \ 130 MesaSoftwareRenderer* mr = (MesaSoftwareRenderer*)ctx->DriverCtx; 131#define INIT_PIXEL_PTR(P, X, Y) \ 132 GLubyte* P = ((GLubyte**)mr->GetRows())[Y] + (X) * 3 133#define INC_PIXEL_PTR(P) P += 3 134#define STORE_PIXEL(DST, X, Y, VALUE) \ 135 DST[BE_RCOMP] = VALUE[RCOMP]; \ 136 DST[BE_GCOMP] = VALUE[GCOMP]; \ 137 DST[BE_BCOMP] = VALUE[BCOMP]; 138#define FETCH_PIXEL(DST, SRC) \ 139 DST[RCOMP] = SRC[BE_RCOMP]; \ 140 DST[GCOMP] = SRC[BE_GCOMP]; \ 141 DST[BCOMP] = SRC[BE_BCOMP]; \ 142 DST[ACOMP] = 0xff; 143#include "swrast/s_spantemp.h" 144 145/* 16-bit RGB */ 146#define NAME(PREFIX) PREFIX##_RGB16 147#define RB_TYPE GLubyte 148#define SPAN_VARS \ 149 MesaSoftwareRenderer* mr = (MesaSoftwareRenderer*)ctx->DriverCtx; 150#define INIT_PIXEL_PTR(P, X, Y) \ 151 GLushort* P = (GLushort*)(((GLubyte**)mr->GetRows())[Y] + (X) * 2) 152#define INC_PIXEL_PTR(P) P += 1 153#define STORE_PIXEL(DST, X, Y, VALUE) \ 154 *DST = ( (((VALUE[RCOMP]) & 0xf8) << 8) | \ 155 (((VALUE[GCOMP]) & 0xfc) << 3) | \ 156 (((VALUE[BCOMP]) ) >> 3) ) 157#define FETCH_PIXEL(DST, SRC) \ 158 DST[RCOMP] = ((*SRC & 0xf800) >> 8); \ 159 DST[GCOMP] = ((*SRC & 0x07e0) >> 3); \ 160 DST[BCOMP] = ((*SRC & 0x001f) << 3); \ 161 DST[ACOMP] = 0xff 162#include "swrast/s_spantemp.h" 163 164/* 15-bit RGB */ 165#define NAME(PREFIX) PREFIX##_RGB15 166#define RB_TYPE GLubyte 167#define SPAN_VARS \ 168 MesaSoftwareRenderer* mr = (MesaSoftwareRenderer*)ctx->DriverCtx; 169#define INIT_PIXEL_PTR(P, X, Y) \ 170 GLushort* P = (GLushort*)(((GLubyte**)mr->GetRows())[Y] + (X) * 2) 171#define INC_PIXEL_PTR(P) P += 1 172#define STORE_PIXEL(DST, X, Y, VALUE) \ 173 *DST = ( (((VALUE[RCOMP]) & 0xf8) << 7) | \ 174 (((VALUE[GCOMP]) & 0xf8) << 2) | \ 175 (((VALUE[BCOMP]) ) >> 3) ) 176#define FETCH_PIXEL(DST, SRC) \ 177 DST[RCOMP] = ((*SRC & 0x7c00) >> 7); \ 178 DST[GCOMP] = ((*SRC & 0x03e0) >> 2); \ 179 DST[BCOMP] = ((*SRC & 0x001f) << 3); \ 180 DST[ACOMP] = 0xff 181#include "swrast/s_spantemp.h" 182} 183 184 185extern "C" _EXPORT BGLRenderer* 186instantiate_gl_renderer(BGLView* view, ulong options, 187 BGLDispatcher* dispatcher) 188{ 189 return new MesaSoftwareRenderer(view, options, dispatcher); 190} 191 192 193MesaSoftwareRenderer::MesaSoftwareRenderer(BGLView* view, ulong options, 194 BGLDispatcher* dispatcher) 195 : BGLRenderer(view, options, dispatcher), 196 fBitmap(NULL), 197 fDirectModeEnabled(false), 198 fInfo(NULL), 199 fInfoLocker("info locker"), 200 fContext(NULL), 201 fVisual(NULL), 202 fFrameBuffer(NULL), 203 fFrontRenderBuffer(NULL), 204 fBackRenderBuffer(NULL), 205 fColorSpace(B_NO_COLOR_SPACE) 206{ 207 CALLED(); 208 209 fClearColor[BE_RCOMP] = 0; 210 fClearColor[BE_GCOMP] = 0; 211 fClearColor[BE_BCOMP] = 0; 212 fClearColor[BE_ACOMP] = 0; 213 214 fClearIndex = 0; 215 216 fColorSpace = BScreen(GLView()->Window()).ColorSpace(); 217 218 // We force single buffering for the time being 219 options &= ~BGL_DOUBLE; 220 221 const GLboolean rgbFlag = ((options & BGL_INDEX) == 0); 222 const GLboolean alphaFlag = ((options & BGL_ALPHA) == BGL_ALPHA); 223 const GLboolean dblFlag = ((options & BGL_DOUBLE) == BGL_DOUBLE); 224 const GLboolean stereoFlag = false; 225 const GLint depth = (options & BGL_DEPTH) ? 16 : 0; 226 const GLint stencil = (options & BGL_STENCIL) ? 8 : 0; 227 const GLint accum = (options & BGL_ACCUM) ? 16 : 0; 228 const GLint red = rgbFlag ? 8 : 0; 229 const GLint green = rgbFlag ? 8 : 0; 230 const GLint blue = rgbFlag ? 8 : 0; 231 const GLint alpha = alphaFlag ? 8 : 0; 232 233 fOptions = options; // | BGL_INDIRECT; 234 struct dd_function_table functions; 235 236 fVisual = _mesa_create_visual(dblFlag, stereoFlag, red, green, 237 blue, alpha, depth, stencil, accum, accum, accum, 238 alpha ? accum : 0, 1); 239 240 // Initialize device driver function table 241 _mesa_init_driver_functions(&functions); 242 243 functions.GetString = _GetString; 244 functions.UpdateState = _UpdateState; 245 functions.GetBufferSize = NULL; 246 functions.Error = _Error; 247 functions.Viewport = _Viewport; 248 functions.Flush = _Flush; 249 250 // create core context 251 fContext = _mesa_create_context(fVisual, NULL, &functions, this); 252 253 if (!fContext) { 254 ERROR("%s: Failed to create Mesa context!\n", __func__); 255 _mesa_destroy_visual(fVisual); 256 return; 257 } 258 259 /* Initialize the software rasterizer and helper modules. */ 260 _swrast_CreateContext(fContext); 261 _vbo_CreateContext(fContext); 262 _tnl_CreateContext(fContext); 263 _swsetup_CreateContext(fContext); 264 _swsetup_Wakeup(fContext); 265 266 // Use default TCL pipeline 267 TNL_CONTEXT(fContext)->Driver.RunPipeline = _tnl_run_pipeline; 268 269 _mesa_meta_init(fContext); 270 _mesa_enable_sw_extensions(fContext); 271 _mesa_enable_1_3_extensions(fContext); 272 _mesa_enable_1_4_extensions(fContext); 273 _mesa_enable_1_5_extensions(fContext); 274 _mesa_enable_2_0_extensions(fContext); 275 _mesa_enable_2_1_extensions(fContext); 276 277 // create core framebuffer 278 fFrameBuffer = (struct msr_framebuffer*)calloc(1, 279 sizeof(*fFrameBuffer)); 280 if (fFrameBuffer == NULL) { 281 ERROR("%s: Unable to calloc GL FrameBuffer!\n", __func__); 282 _mesa_destroy_visual(fVisual); 283 return; 284 } 285 _mesa_initialize_window_framebuffer(&fFrameBuffer->base, fVisual); 286 287 // Setup front render buffer 288 fFrontRenderBuffer = _NewRenderBuffer(true); 289 if (fFrontRenderBuffer == NULL) { 290 ERROR("%s: FrontRenderBuffer is requested but unallocated!\n", 291 __func__); 292 _mesa_destroy_visual(fVisual); 293 free(fFrameBuffer); 294 return; 295 } 296 _mesa_add_renderbuffer(&fFrameBuffer->base, BUFFER_FRONT_LEFT, 297 &fFrontRenderBuffer->base); 298 299 // Setup back render buffer (if requested) 300 if (fVisual->doubleBufferMode) { 301 fBackRenderBuffer = _NewRenderBuffer(false); 302 if (fBackRenderBuffer == NULL) { 303 ERROR("%s: BackRenderBuffer is requested but unallocated!\n", 304 __func__); 305 _mesa_destroy_visual(fVisual); 306 free(fFrameBuffer); 307 return; 308 } 309 _mesa_add_renderbuffer(&fFrameBuffer->base, BUFFER_BACK_LEFT, 310 &fBackRenderBuffer->base); 311 } 312 313 _mesa_add_soft_renderbuffers(&fFrameBuffer->base, GL_FALSE, 314 fVisual->haveDepthBuffer, fVisual->haveStencilBuffer, 315 fVisual->haveAccumBuffer, alphaFlag, GL_FALSE); 316 317 BRect bounds = view->Bounds(); 318 fWidth = fNewWidth = (GLint)bounds.Width(); 319 fHeight = fNewHeight = (GLint)bounds.Height(); 320 321 // some stupid applications (Quake2) don't even think about calling LockGL() 322 // before using glGetString and its glGet*() friends... 323 // so make sure there is at least a valid context. 324 325 if (!_mesa_get_current_context()) { 326 LockGL(); 327 // not needed, we don't have a looper yet: UnlockLooper(); 328 } 329} 330 331 332MesaSoftwareRenderer::~MesaSoftwareRenderer() 333{ 334 CALLED(); 335 _swsetup_DestroyContext(fContext); 336 _swrast_DestroyContext(fContext); 337 _tnl_DestroyContext(fContext); 338 _vbo_DestroyContext(fContext); 339 _mesa_destroy_visual(fVisual); 340 _mesa_destroy_framebuffer(&fFrameBuffer->base); 341 _mesa_destroy_context(fContext); 342 343 free(fInfo); 344 free(fFrameBuffer); 345 346 delete fBitmap; 347} 348 349 350void 351MesaSoftwareRenderer::LockGL() 352{ 353 CALLED(); 354 BGLRenderer::LockGL(); 355 356 _mesa_make_current(fContext, &fFrameBuffer->base, &fFrameBuffer->base); 357 358 color_space colorSpace = BScreen(GLView()->Window()).ColorSpace(); 359 360 BAutolock lock(fInfoLocker); 361 if (fDirectModeEnabled && fInfo != NULL) { 362 fNewWidth = fInfo->window_bounds.right 363 - fInfo->window_bounds.left + 1; 364 fNewHeight = fInfo->window_bounds.bottom 365 - fInfo->window_bounds.top + 1; 366 } 367 368 if (fColorSpace != colorSpace) { 369 fColorSpace = colorSpace; 370 _SetupRenderBuffer(fFrontRenderBuffer, fColorSpace); 371 if (fVisual->doubleBufferMode) 372 _SetupRenderBuffer(fBackRenderBuffer, fColorSpace); 373 } 374 375 _CheckResize(); 376} 377 378 379void 380MesaSoftwareRenderer::UnlockGL() 381{ 382 CALLED(); 383 _mesa_make_current(fContext, NULL, NULL); 384 BGLRenderer::UnlockGL(); 385} 386 387 388void 389MesaSoftwareRenderer::SwapBuffers(bool VSync) 390{ 391 CALLED(); 392 393 if (!fBitmap) 394 return; 395 396 if (fVisual->doubleBufferMode) 397 _mesa_notifySwapBuffers(fContext); 398 399 if (!fDirectModeEnabled || fInfo == NULL) { 400 if (GLView()->LockLooperWithTimeout(1000) == B_OK) { 401 GLView()->DrawBitmap(fBitmap, B_ORIGIN); 402 GLView()->UnlockLooper(); 403 } 404 } else { 405 // TODO: Here the BGLView needs to be drawlocked. 406 _CopyToDirect(); 407 } 408 409 if (VSync) { 410 BScreen screen(GLView()->Window()); 411 screen.WaitForRetrace(); 412 } 413} 414 415 416void 417MesaSoftwareRenderer::Draw(BRect updateRect) 418{ 419 CALLED(); 420 if (fBitmap && (!fDirectModeEnabled || (fInfo == NULL))) 421 GLView()->DrawBitmap(fBitmap, updateRect, updateRect); 422} 423 424 425status_t 426MesaSoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap* bitmap) 427{ 428 CALLED(); 429 color_space scs = fBitmap->ColorSpace(); 430 color_space dcs = bitmap->ColorSpace(); 431 432 if (scs != dcs && (scs != B_RGBA32 || dcs != B_RGB32)) { 433 fprintf(stderr, "CopyPixelsOut(): incompatible color space: %s != %s\n", 434 color_space_name(scs), 435 color_space_name(dcs)); 436 return B_BAD_TYPE; 437 } 438 439 BRect sr = fBitmap->Bounds(); 440 BRect dr = bitmap->Bounds(); 441 442 sr = sr & dr.OffsetBySelf(location); 443 dr = sr.OffsetByCopy(-location.x, -location.y); 444 445 uint8* ps = (uint8*) fBitmap->Bits(); 446 uint8* pd = (uint8*) bitmap->Bits(); 447 uint32* s; 448 uint32* d; 449 uint32 y; 450 for (y = (uint32) sr.top; y <= (uint32)sr.bottom; y++) { 451 s = (uint32*)(ps + y * fBitmap->BytesPerRow()); 452 s += (uint32) sr.left; 453 454 d = (uint32*)(pd + (y + (uint32)(dr.top - sr.top)) 455 * bitmap->BytesPerRow()); 456 d += (uint32) dr.left; 457 458 memcpy(d, s, dr.IntegerWidth() * 4); 459 } 460 return B_OK; 461} 462 463 464status_t 465MesaSoftwareRenderer::CopyPixelsIn(BBitmap* bitmap, BPoint location) 466{ 467 CALLED(); 468 color_space scs = bitmap->ColorSpace(); 469 color_space dcs = fBitmap->ColorSpace(); 470 471 if (scs != dcs && (dcs != B_RGBA32 || scs != B_RGB32)) { 472 fprintf(stderr, "CopyPixelsIn(): incompatible color space: %s != %s\n", 473 color_space_name(scs), 474 color_space_name(dcs)); 475 return B_BAD_TYPE; 476 } 477 478 BRect sr = bitmap->Bounds(); 479 BRect dr = fBitmap->Bounds(); 480 481 sr = sr & dr.OffsetBySelf(location); 482 dr = sr.OffsetByCopy(-location.x, -location.y); 483 484 uint8* ps = (uint8*) bitmap->Bits(); 485 uint8* pd = (uint8*) fBitmap->Bits(); 486 uint32* s; 487 uint32* d; 488 uint32 y; 489 for (y = (uint32) sr.top; y <= (uint32)sr.bottom; y++) { 490 s = (uint32*)(ps + y * bitmap->BytesPerRow()); 491 s += (uint32) sr.left; 492 493 d = (uint32*)(pd + (y + (uint32)(dr.top - sr.top)) 494 * fBitmap->BytesPerRow()); 495 d += (uint32) dr.left; 496 497 memcpy(d, s, dr.IntegerWidth() * 4); 498 } 499 return B_OK; 500} 501 502 503void 504MesaSoftwareRenderer::EnableDirectMode(bool enabled) 505{ 506 fDirectModeEnabled = enabled; 507} 508 509 510void 511MesaSoftwareRenderer::DirectConnected(direct_buffer_info* info) 512{ 513 // TODO: I'm not sure we need to do this: BGLView already 514 // keeps a local copy of the direct_buffer_info passed by 515 // BDirectWindow::DirectConnected(). 516 BAutolock lock(fInfoLocker); 517 if (info) { 518 if (!fInfo) { 519 fInfo = (direct_buffer_info*)malloc(DIRECT_BUFFER_INFO_AREA_SIZE); 520 if (!fInfo) 521 return; 522 } 523 memcpy(fInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE); 524 } else if (fInfo) { 525 free(fInfo); 526 fInfo = NULL; 527 } 528} 529 530 531void 532MesaSoftwareRenderer::FrameResized(float width, float height) 533{ 534 BAutolock lock(fInfoLocker); 535 fNewWidth = (GLuint)width; 536 fNewHeight = (GLuint)height; 537 _CheckResize(); 538} 539 540 541void 542MesaSoftwareRenderer::_CheckResize() 543{ 544 CALLED(); 545 546 if (fBitmap && fNewWidth == fWidth 547 && fNewHeight == fHeight) { 548 return; 549 } 550 551 fHeight = fNewHeight; 552 fWidth = fNewWidth; 553 _mesa_resize_framebuffer(fContext, &fFrameBuffer->base, fWidth, fHeight); 554 555 _AllocateBitmap(); 556} 557 558 559void 560MesaSoftwareRenderer::_AllocateBitmap() 561{ 562 CALLED(); 563 // allocate new size of back buffer bitmap 564 delete fBitmap; 565 fBitmap = NULL; 566 567 if (fWidth < 1 || fHeight < 1) { 568 TRACE("%s: Cannot allocate bitmap < 1x1!\n", __func__); 569 return; 570 } 571 572 BRect rect(0.0, 0.0, fWidth - 1, fHeight - 1); 573 fBitmap = new BBitmap(rect, fColorSpace); 574 for (uint i = 0; i < fHeight; i++) { 575 fRowAddr[fHeight - i - 1] = (GLvoid *)((GLubyte *)fBitmap->Bits() 576 + i * fBitmap->BytesPerRow()); 577 } 578 579 fFrontRenderBuffer->size = fBitmap->BitsLength(); 580 if (fVisual->doubleBufferMode) 581 fBackRenderBuffer->size = fBitmap->BitsLength(); 582 fFrameBuffer->width = fWidth; 583 fFrameBuffer->height = fHeight; 584 TRACE("%s: Bitmap Size: %" B_PRIu32 "\n", __func__, fBitmap->BitsLength()); 585 586 fFrontRenderBuffer->base.Data = fBitmap->Bits(); 587} 588 589 590// #pragma mark - static 591 592 593void 594MesaSoftwareRenderer::_Error(gl_context* ctx) 595{ 596 MesaSoftwareRenderer* mr = (MesaSoftwareRenderer*)ctx->DriverCtx; 597 if (mr && mr->GLView()) 598 mr->GLView()->ErrorCallback((unsigned long)ctx->ErrorValue); 599} 600 601 602const GLubyte* 603MesaSoftwareRenderer::_GetString(gl_context* ctx, GLenum name) 604{ 605 606 switch (name) { 607 case GL_VENDOR: 608 return (const GLubyte*) "Mesa Project"; 609 case GL_RENDERER: { 610 _mesa_get_cpu_features(); 611 static char buffer[256] = { '\0' }; 612 613 if (!buffer[0]) { 614 char* cpuInfo = _mesa_get_cpu_string(); 615 // Let's build an renderer string 616 sprintf(buffer, "Software Rasterizer for %s", cpuInfo); 617 free(cpuInfo); 618 } 619 return (const GLubyte*) buffer; 620 } 621 default: 622 // Let core library handle all other cases 623 return NULL; 624 } 625} 626 627 628void 629MesaSoftwareRenderer::_Viewport(gl_context* ctx, GLint x, GLint y, GLsizei w, 630 GLsizei h) 631{ 632 CALLED(); 633 634 gl_framebuffer* draw = ctx->WinSysDrawBuffer; 635 gl_framebuffer* read = ctx->WinSysReadBuffer; 636 struct msr_framebuffer* msr = msr_framebuffer(draw); 637 638 _mesa_resize_framebuffer(ctx, draw, msr->width, msr->height); 639 _mesa_resize_framebuffer(ctx, read, msr->width, msr->height); 640} 641 642 643void 644MesaSoftwareRenderer::_UpdateState(gl_context* ctx, GLuint new_state) 645{ 646 if (!ctx) 647 return; 648 649 CALLED(); 650 _swrast_InvalidateState(ctx, new_state); 651 _swsetup_InvalidateState(ctx, new_state); 652 _vbo_InvalidateState(ctx, new_state); 653 _tnl_InvalidateState(ctx, new_state); 654} 655 656 657void 658MesaSoftwareRenderer::_ClearFront(gl_context* ctx) 659{ 660 CALLED(); 661 662 MesaSoftwareRenderer* mr = (MesaSoftwareRenderer*)ctx->DriverCtx; 663 BGLView* bglview = mr->GLView(); 664 assert(bglview); 665 BBitmap* bitmap = mr->fBitmap; 666 assert(bitmap); 667 GLuint* start = (GLuint*)bitmap->Bits(); 668 size_t pixelSize = 0; 669 get_pixel_size_for(bitmap->ColorSpace(), &pixelSize, NULL, NULL); 670 const GLuint* clearPixelPtr = (const GLuint*)mr->fClearColor; 671 const GLuint clearPixel = B_LENDIAN_TO_HOST_INT32(*clearPixelPtr); 672 673 int x = ctx->DrawBuffer->_Xmin; 674 int y = ctx->DrawBuffer->_Ymin; 675 uint32 width = ctx->DrawBuffer->_Xmax - x; 676 uint32 height = ctx->DrawBuffer->_Ymax - y; 677 GLboolean all = (width == ctx->DrawBuffer->Width 678 && height == ctx->DrawBuffer->Height); 679 680 if (all) { 681 const int numPixels = mr->fWidth * mr->fHeight; 682 if (clearPixel == 0) { 683 memset(start, 0, numPixels * pixelSize); 684 } else { 685 for (int i = 0; i < numPixels; i++) { 686 start[i] = clearPixel; 687 } 688 } 689 } else { 690 // XXX untested 691 start += y * mr->fWidth + x; 692 for (uint32 i = 0; i < height; i++) { 693 for (uint32 j = 0; j < width; j++) { 694 start[j] = clearPixel; 695 } 696 start += mr->fWidth; 697 } 698 } 699} 700 701 702GLboolean 703MesaSoftwareRenderer::_FrontRenderbufferStorage(gl_context* ctx, 704 struct gl_renderbuffer* render, GLenum internalFormat, 705 GLuint width, GLuint height) 706{ 707 CALLED(); 708 709 render->Data = NULL; 710 render->Width = width; 711 render->Height = height; 712 713 return GL_TRUE; 714} 715 716 717GLboolean 718MesaSoftwareRenderer::_BackRenderbufferStorage(gl_context* ctx, 719 struct gl_renderbuffer* render, GLenum internalFormat, 720 GLuint width, GLuint height) 721{ 722 CALLED(); 723 struct msr_renderbuffer* mrb = msr_renderbuffer(render); 724 725 free(render->Data); 726 _FrontRenderbufferStorage(ctx, render, internalFormat, width, height); 727 728 if (mrb->size) 729 ERROR("%s: suspicious malloc of 0 bytes.\n", __func__); 730 render->Data = malloc(mrb->size); 731 732 return GL_TRUE; 733} 734 735 736void 737MesaSoftwareRenderer::_Flush(gl_context* ctx) 738{ 739 CALLED(); 740 MesaSoftwareRenderer* mr = (MesaSoftwareRenderer*)ctx->DriverCtx; 741 if ((mr->fOptions & BGL_DOUBLE) == 0) { 742 // TODO: SwapBuffers() can call _CopyToDirect(), which should 743 // be always called with with the BGLView drawlocked. 744 // This is not always the case if called from here. 745 mr->SwapBuffers(); 746 } 747} 748 749 750struct msr_renderbuffer* 751MesaSoftwareRenderer::_NewRenderBuffer(bool front) 752{ 753 CALLED(); 754 struct msr_renderbuffer *msr 755 = (struct msr_renderbuffer*)calloc(1, sizeof *msr); 756 757 if (!msr) { 758 ERROR("%s: Failed calloc RenderBuffer\n", __func__); 759 return NULL; 760 } 761 762 _mesa_init_renderbuffer(&msr->base, 0); 763 764 if (_SetupRenderBuffer(msr, fColorSpace) != B_OK) { 765 free(msr); 766 return NULL; 767 } 768 769 if (front) 770 msr->base.AllocStorage = _FrontRenderbufferStorage; 771 else { 772 msr->base.AllocStorage = _BackRenderbufferStorage; 773 msr->base.Delete = _DeleteBackBuffer; 774 } 775 776 return msr; 777} 778 779 780status_t 781MesaSoftwareRenderer::_SetupRenderBuffer( 782 struct msr_renderbuffer* buffer, color_space colorSpace) 783{ 784 CALLED(); 785 786 buffer->base.DataType = GL_UNSIGNED_BYTE; 787 buffer->base.Data = NULL; 788 789 switch (colorSpace) { 790 case B_RGBA32: 791 buffer->base._BaseFormat = GL_RGBA; 792 buffer->base.Format = MESA_FORMAT_ARGB8888; 793 794 buffer->base.GetRow = get_row_RGBA32; 795 buffer->base.GetValues = get_values_RGBA32; 796 buffer->base.PutRow = put_row_RGBA32; 797 buffer->base.PutValues = put_values_RGBA32; 798 buffer->base.PutRowRGB = put_row_rgb_RGBA32; 799 buffer->base.PutMonoRow = put_mono_row_RGBA32; 800 buffer->base.PutMonoValues = put_values_RGBA32; 801 break; 802 case B_RGB32: 803 buffer->base._BaseFormat = GL_RGB; 804 buffer->base.Format = MESA_FORMAT_ARGB8888; 805 806 buffer->base.GetRow = get_row_RGB32; 807 buffer->base.GetValues = get_values_RGB32; 808 buffer->base.PutRow = put_row_RGB32; 809 buffer->base.PutValues = put_values_RGB32; 810 buffer->base.PutRowRGB = put_row_rgb_RGB32; 811 buffer->base.PutMonoRow = put_mono_row_RGB32; 812 buffer->base.PutMonoValues = put_values_RGB32; 813 break; 814 case B_RGB24: 815 buffer->base._BaseFormat = GL_RGB; 816 buffer->base.Format = MESA_FORMAT_RGB888; 817 818 buffer->base.GetRow = get_row_RGB24; 819 buffer->base.GetValues = get_values_RGB24; 820 buffer->base.PutRow = put_row_RGB24; 821 buffer->base.PutValues = put_values_RGB24; 822 buffer->base.PutRowRGB = put_row_rgb_RGB24; 823 buffer->base.PutMonoRow = put_mono_row_RGB24; 824 buffer->base.PutMonoValues = put_values_RGB24; 825 break; 826 case B_RGB16: 827 buffer->base._BaseFormat = GL_RGB; 828 buffer->base.Format = MESA_FORMAT_RGB565; 829 830 buffer->base.GetRow = get_row_RGB16; 831 buffer->base.GetValues = get_values_RGB16; 832 buffer->base.PutRow = put_row_RGB16; 833 buffer->base.PutValues = put_values_RGB16; 834 buffer->base.PutRowRGB = put_row_rgb_RGB16; 835 buffer->base.PutMonoRow = put_mono_row_RGB16; 836 buffer->base.PutMonoValues = put_values_RGB16; 837 break; 838 case B_RGB15: 839 buffer->base._BaseFormat = GL_RGB; 840 buffer->base.Format = MESA_FORMAT_ARGB1555; 841 842 buffer->base.GetRow = get_row_RGB15; 843 buffer->base.GetValues = get_values_RGB15; 844 buffer->base.PutRow = put_row_RGB15; 845 buffer->base.PutValues = put_values_RGB15; 846 buffer->base.PutRowRGB = put_row_rgb_RGB15; 847 buffer->base.PutMonoRow = put_mono_row_RGB15; 848 buffer->base.PutMonoValues = put_values_RGB15; 849 break; 850 default: 851 fprintf(stderr, "Unsupported screen color space %s\n", 852 color_space_name(fColorSpace)); 853 debugger("Unsupported OpenGL color space"); 854 return B_ERROR; 855 } 856 return B_OK; 857} 858 859 860void 861MesaSoftwareRenderer::_DeleteBackBuffer(struct gl_renderbuffer* rb) 862{ 863 CALLED(); 864 free(rb->Data); 865 free(rb); 866} 867 868 869void 870MesaSoftwareRenderer::_CopyToDirect() 871{ 872 BAutolock lock(fInfoLocker); 873 874 // check the bitmap size still matches the size 875 if (fInfo->window_bounds.bottom - fInfo->window_bounds.top 876 != fBitmap->Bounds().IntegerHeight() 877 || fInfo->window_bounds.right - fInfo->window_bounds.left 878 != fBitmap->Bounds().IntegerWidth()) 879 return; 880 881 uint8 bytesPerPixel = fInfo->bits_per_pixel / 8; 882 uint32 bytesPerRow = fBitmap->BytesPerRow(); 883 for (uint32 i = 0; i < fInfo->clip_list_count; i++) { 884 clipping_rect *clip = &fInfo->clip_list[i]; 885 int32 height = clip->bottom - clip->top + 1; 886 int32 bytesWidth 887 = (clip->right - clip->left + 1) * bytesPerPixel; 888 uint8* p = (uint8*)fInfo->bits + clip->top 889 * fInfo->bytes_per_row + clip->left * bytesPerPixel; 890 uint8* b = (uint8*)fBitmap->Bits() 891 + (clip->top - fInfo->window_bounds.top) * bytesPerRow 892 + (clip->left - fInfo->window_bounds.left) 893 * bytesPerPixel; 894 895 for (int y = 0; y < height; y++) { 896 memcpy(p, b, bytesWidth); 897 p += fInfo->bytes_per_row; 898 b += bytesPerRow; 899 } 900 } 901} 902