/* * Mesa 3-D graphics library * Version: 6.1 * * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include extern "C" { #include "glheader.h" #include "version.h" #include "buffers.h" #include "bufferobj.h" #include "context.h" #include "colormac.h" #include "depth.h" #include "extensions.h" #include "macros.h" #include "matrix.h" #include "mtypes.h" #include "texformat.h" #include "texobj.h" #include "teximage.h" #include "texstore.h" #include "vbo/vbo.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "swrast/s_context.h" #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" #include "drivers/common/driverfuncs.h" } // extern "C" #include #include // BeOS component ordering for B_RGBA32 bitmap format #if B_HOST_IS_LENDIAN #define BE_RCOMP 2 #define BE_GCOMP 1 #define BE_BCOMP 0 #define BE_ACOMP 3 #define PACK_B_RGBA32(color) (color[BCOMP] | (color[GCOMP] << 8) | \ (color[RCOMP] << 16) | (color[ACOMP] << 24)) #define PACK_B_RGB32(color) (color[BCOMP] | (color[GCOMP] << 8) | \ (color[RCOMP] << 16) | 0xFF000000) #else // Big Endian B_RGBA32 bitmap format #define BE_RCOMP 1 #define BE_GCOMP 2 #define BE_BCOMP 3 #define BE_ACOMP 0 #define PACK_B_RGBA32(color) (color[ACOMP] | (color[RCOMP] << 8) | \ (color[GCOMP] << 16) | (color[BCOMP] << 24)) #define PACK_B_RGB32(color) ((color[RCOMP] << 8) | (color[GCOMP] << 16) | \ (color[BCOMP] << 24) | 0xFF000000) #endif #define FLIP(coord) (LIBGGI_MODE(ggi_ctx->ggi_visual)->visible.y-(coord) - 1) const char * color_space_name(color_space space); // // This object hangs off of the BGLView object. We have to use // Be's BGLView class as-is to maintain binary compatibility (we // can't add new members to it). Instead we just put all our data // in this class and use BGLVIew::m_gc to point to it. // class MesaDriver { friend class BGLView; public: MesaDriver(); ~MesaDriver(); void Init(BGLView * bglview, struct gl_context * c, struct gl_config * v, struct gl_framebuffer * b); void LockGL(); void UnlockGL(); void SwapBuffers() const; status_t CopyPixelsOut(BPoint source, BBitmap *dest); status_t CopyPixelsIn(BBitmap *source, BPoint dest); void CopySubBuffer(GLint x, GLint y, GLuint width, GLuint height) const; void Draw(BRect updateRect) const; private: MesaDriver(const MesaDriver &rhs); // copy constructor illegal MesaDriver &operator=(const MesaDriver &rhs); // assignment oper. illegal struct gl_context * m_glcontext; struct gl_config * m_glvisual; struct gl_framebuffer * m_glframebuffer; BGLView * m_bglview; BBitmap * m_bitmap; GLchan m_clear_color[4]; // buffer clear color GLuint m_clear_index; // buffer clear color index GLint m_bottom; // used for flipping Y coords GLuint m_width; GLuint m_height; // Mesa Device Driver callback functions static void UpdateState(struct gl_context *ctx, GLuint new_state); static void ClearIndex(struct gl_context *ctx, GLuint index); static void ClearColor(struct gl_context *ctx, const GLfloat color[4]); static void Clear(struct gl_context *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height); static void ClearFront(struct gl_context *ctx, GLboolean all, GLint x, GLint y, GLint width, GLint height); static void ClearBack(struct gl_context *ctx, GLboolean all, GLint x, GLint y, GLint width, GLint height); static void Index(struct gl_context *ctx, GLuint index); static void Color(struct gl_context *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a); static void SetBuffer(struct gl_context *ctx, struct gl_framebuffer *colorBuffer, GLenum mode); static void GetBufferSize(struct gl_framebuffer * framebuffer, GLuint *width, GLuint *height); static void Error(struct gl_context *ctx); static const GLubyte * GetString(struct gl_context *ctx, GLenum name); static void Viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h); // Front-buffer functions static void WriteRGBASpanFront(const struct gl_context *ctx, GLuint n, GLint x, GLint y, CONST GLubyte rgba[][4], const GLubyte mask[]); static void WriteRGBSpanFront(const struct gl_context *ctx, GLuint n, GLint x, GLint y, CONST GLubyte rgba[][3], const GLubyte mask[]); static void WriteMonoRGBASpanFront(const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLchan color[4], const GLubyte mask[]); static void WriteRGBAPixelsFront(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], CONST GLubyte rgba[][4], const GLubyte mask[]); static void WriteMonoRGBAPixelsFront(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], const GLchan color[4], const GLubyte mask[]); static void WriteCI32SpanFront(const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLuint index[], const GLubyte mask[]); static void WriteCI8SpanFront(const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLubyte index[], const GLubyte mask[]); static void WriteMonoCISpanFront(const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLuint colorIndex, const GLubyte mask[]); static void WriteCI32PixelsFront(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], const GLuint index[], const GLubyte mask[]); static void WriteMonoCIPixelsFront(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLuint colorIndex, const GLubyte mask[]); static void ReadCI32SpanFront(const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLuint index[]); static void ReadRGBASpanFront(const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4]); static void ReadCI32PixelsFront(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLuint indx[], const GLubyte mask[]); static void ReadRGBAPixelsFront(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[]); // Back buffer functions static void WriteRGBASpanBack(const struct gl_context *ctx, GLuint n, GLint x, GLint y, CONST GLubyte rgba[][4], const GLubyte mask[]); static void WriteRGBSpanBack(const struct gl_context *ctx, GLuint n, GLint x, GLint y, CONST GLubyte rgba[][3], const GLubyte mask[]); static void WriteMonoRGBASpanBack(const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLchan color[4], const GLubyte mask[]); static void WriteRGBAPixelsBack(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], CONST GLubyte rgba[][4], const GLubyte mask[]); static void WriteMonoRGBAPixelsBack(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], const GLchan color[4], const GLubyte mask[]); static void WriteCI32SpanBack(const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLuint index[], const GLubyte mask[]); static void WriteCI8SpanBack(const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLubyte index[], const GLubyte mask[]); static void WriteMonoCISpanBack(const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLuint colorIndex, const GLubyte mask[]); static void WriteCI32PixelsBack(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], const GLuint index[], const GLubyte mask[]); static void WriteMonoCIPixelsBack(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLuint colorIndex, const GLubyte mask[]); static void ReadCI32SpanBack(const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLuint index[]); static void ReadRGBASpanBack(const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4]); static void ReadCI32PixelsBack(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLuint indx[], const GLubyte mask[]); static void ReadRGBAPixelsBack(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[]); }; //------------------------------------------------------------------ // Public interface methods //------------------------------------------------------------------ // // Input: rect - initial rectangle // name - window name // resizingMode - example: B_FOLLOW_NONE // mode - usually 0 ? // options - Bitwise-OR of BGL_* tokens // BGLView::BGLView(BRect rect, char *name, ulong resizingMode, ulong mode, ulong options) : BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS) // | B_FULL_UPDATE_ON_RESIZE) { // We don't support single buffering (yet): double buffering forced. options |= BGL_DOUBLE; const GLboolean rgbFlag = ((options & BGL_INDEX) == 0); const GLboolean alphaFlag = ((options & BGL_ALPHA) == BGL_ALPHA); const GLboolean dblFlag = ((options & BGL_DOUBLE) == BGL_DOUBLE); const GLboolean stereoFlag = false; const GLint depth = (options & BGL_DEPTH) ? 16 : 0; const GLint stencil = (options & BGL_STENCIL) ? 8 : 0; const GLint accum = (options & BGL_ACCUM) ? 16 : 0; const GLint index = (options & BGL_INDEX) ? 32 : 0; const GLint red = rgbFlag ? 8 : 0; const GLint green = rgbFlag ? 8 : 0; const GLint blue = rgbFlag ? 8 : 0; const GLint alpha = alphaFlag ? 8 : 0; m_options = options | BGL_INDIRECT; struct dd_function_table functions; if (!rgbFlag) { fprintf(stderr, "Mesa Warning: color index mode not supported\n"); } // Allocate auxiliary data object MesaDriver * md = new MesaDriver(); // examine option flags and create gl_context struct struct gl_config * visual = _mesa_create_visual( dblFlag, stereoFlag, red, green, blue, alpha, depth, stencil, accum, accum, accum, accum, 1 ); // Initialize device driver function table _mesa_init_driver_functions(&functions); functions.GetString = md->GetString; functions.UpdateState = md->UpdateState; functions.GetBufferSize = md->GetBufferSize; functions.Clear = md->Clear; functions.ClearIndex = md->ClearIndex; functions.ClearColor = md->ClearColor; functions.Error = md->Error; functions.Viewport = md->Viewport; // create core context struct gl_context *ctx = _mesa_create_context(API_OPENGL, visual, NULL, &functions, md); if (! ctx) { _mesa_destroy_visual(visual); delete md; return; } _mesa_enable_sw_extensions(ctx); _mesa_enable_1_3_extensions(ctx); _mesa_enable_1_4_extensions(ctx); _mesa_enable_1_5_extensions(ctx); // create core framebuffer struct gl_framebuffer * buffer = _mesa_create_framebuffer(visual, depth > 0 ? GL_TRUE : GL_FALSE, stencil > 0 ? GL_TRUE: GL_FALSE, accum > 0 ? GL_TRUE : GL_FALSE, alphaFlag ); /* Initialize the software rasterizer and helper modules. */ _swrast_CreateContext(ctx); _vbo_CreateContext(ctx); _tnl_CreateContext(ctx); _swsetup_CreateContext(ctx); _swsetup_Wakeup(ctx); md->Init(this, ctx, visual, buffer ); // Hook aux data into BGLView object m_gc = md; // some stupid applications (Quake2) don't even think about calling LockGL() // before using glGetString and friends... so make sure there is at least a // valid context. if (!_mesa_get_current_context()) { LockGL(); // not needed, we don't have a looper yet: UnlockLooper(); } } BGLView::~BGLView() { // printf("BGLView destructor\n"); MesaDriver * md = (MesaDriver *) m_gc; assert(md); delete md; } void BGLView::LockGL() { MesaDriver * md = (MesaDriver *) m_gc; assert(md); md->LockGL(); } void BGLView::UnlockGL() { MesaDriver * md = (MesaDriver *) m_gc; assert(md); md->UnlockGL(); } void BGLView::SwapBuffers() { SwapBuffers(false); } void BGLView::SwapBuffers(bool vSync) { MesaDriver * md = (MesaDriver *) m_gc; assert(md); md->SwapBuffers(); if (vSync) { BScreen screen(Window()); screen.WaitForRetrace(); } } #if 0 void BGLView::CopySubBufferMESA(GLint x, GLint y, GLuint width, GLuint height) { MesaDriver * md = (MesaDriver *) m_gc; assert(md); md->CopySubBuffer(x, y, width, height); } #endif BView * BGLView::EmbeddedView() { return NULL; } status_t BGLView::CopyPixelsOut(BPoint source, BBitmap *dest) { if (! dest || ! dest->Bounds().IsValid()) return B_BAD_VALUE; MesaDriver * md = (MesaDriver *) m_gc; assert(md); return md->CopyPixelsOut(source, dest); } status_t BGLView::CopyPixelsIn(BBitmap *source, BPoint dest) { if (! source || ! source->Bounds().IsValid()) return B_BAD_VALUE; MesaDriver * md = (MesaDriver *) m_gc; assert(md); return md->CopyPixelsIn(source, dest); } void BGLView::ErrorCallback(unsigned long errorCode) // Mesa's GLenum is not ulong but uint! { char msg[32]; sprintf(msg, "GL: Error code $%04lx.", errorCode); // debugger(msg); fprintf(stderr, "%s\n", msg); return; } void BGLView::Draw(BRect updateRect) { // printf("BGLView::Draw()\n"); MesaDriver * md = (MesaDriver *) m_gc; assert(md); md->Draw(updateRect); } void BGLView::AttachedToWindow() { BView::AttachedToWindow(); // don't paint window background white when resized SetViewColor(B_TRANSPARENT_32_BIT); } void BGLView::AllAttached() { BView::AllAttached(); // printf("BGLView AllAttached\n"); } void BGLView::DetachedFromWindow() { BView::DetachedFromWindow(); } void BGLView::AllDetached() { BView::AllDetached(); // printf("BGLView AllDetached"); } void BGLView::FrameResized(float width, float height) { return BView::FrameResized(width, height); } status_t BGLView::Perform(perform_code d, void *arg) { return BView::Perform(d, arg); } status_t BGLView::Archive(BMessage *data, bool deep) const { return BView::Archive(data, deep); } void BGLView::MessageReceived(BMessage *msg) { BView::MessageReceived(msg); } void BGLView::SetResizingMode(uint32 mode) { BView::SetResizingMode(mode); } void BGLView::Show() { BView::Show(); } void BGLView::Hide() { BView::Hide(); } BHandler *BGLView::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier, int32 form, const char *property) { return BView::ResolveSpecifier(msg, index, specifier, form, property); } status_t BGLView::GetSupportedSuites(BMessage *data) { return BView::GetSupportedSuites(data); } void BGLView::DirectConnected( direct_buffer_info *info ) { #if 0 if (! m_direct_connected && m_direct_connection_disabled) return; direct_info_locker->Lock(); switch(info->buffer_state & B_DIRECT_MODE_MASK) { case B_DIRECT_START: m_direct_connected = true; case B_DIRECT_MODIFY: // Get clipping information if (m_clip_list) free(m_clip_list); m_clip_list_count = info->clip_list_count; m_clip_list = (clipping_rect *) malloc(m_clip_list_count*sizeof(clipping_rect)); if (m_clip_list) { memcpy(m_clip_list, info->clip_list, m_clip_list_count*sizeof(clipping_rect)); fBits = (uint8 *) info->bits; fRowBytes = info->bytes_per_row; fFormat = info->pixel_format; fBounds = info->window_bounds; fDirty = true; } break; case B_DIRECT_STOP: fConnected = false; break; } direct_info_locker->Unlock(); #endif } void BGLView::EnableDirectMode( bool enabled ) { // TODO } //---- virtual reserved methods ---------- void BGLView::_ReservedGLView1() {} void BGLView::_ReservedGLView2() {} void BGLView::_ReservedGLView3() {} void BGLView::_ReservedGLView4() {} void BGLView::_ReservedGLView5() {} void BGLView::_ReservedGLView6() {} void BGLView::_ReservedGLView7() {} void BGLView::_ReservedGLView8() {} #if 0 // Not implemented!!! BGLView::BGLView(const BGLView &v) : BView(v) { // XXX not sure how this should work printf("Warning BGLView::copy constructor not implemented\n"); } BGLView &BGLView::operator=(const BGLView &v) { printf("Warning BGLView::operator= not implemented\n"); return *this; } #endif void BGLView::dither_front() { // no-op } bool BGLView::confirm_dither() { // no-op return false; } void BGLView::draw(BRect r) { // XXX no-op ??? } /* Direct Window stuff */ void BGLView::drawScanline( int x1, int x2, int y, void *data ) { // no-op } void BGLView::scanlineHandler(struct rasStateRec *state, GLint x1, GLint x2) { // no-op } void BGLView::lock_draw() { // no-op } void BGLView::unlock_draw() { // no-op } bool BGLView::validateView() { // no-op return true; } // #pragma mark - MesaDriver::MesaDriver() { m_glcontext = NULL; m_glvisual = NULL; m_glframebuffer = NULL; m_bglview = NULL; m_bitmap = NULL; m_clear_color[BE_RCOMP] = 0; m_clear_color[BE_GCOMP] = 0; m_clear_color[BE_BCOMP] = 0; m_clear_color[BE_ACOMP] = 0; m_clear_index = 0; } MesaDriver::~MesaDriver() { _mesa_destroy_visual(m_glvisual); _mesa_destroy_framebuffer(m_glframebuffer); _mesa_destroy_context(m_glcontext); delete m_bitmap; } void MesaDriver::Init(BGLView * bglview, struct gl_context * ctx, struct gl_config * visual, struct gl_framebuffer * framebuffer) { m_bglview = bglview; m_glcontext = ctx; m_glvisual = visual; m_glframebuffer = framebuffer; MesaDriver * md = (MesaDriver *) ctx->DriverCtx; struct swrast_device_driver * swdd = _swrast_GetDeviceDriverReference( ctx ); TNLcontext * tnl = TNL_CONTEXT(ctx); assert(md->m_glcontext == ctx ); assert(tnl); assert(swdd); // Use default TCL pipeline tnl->Driver.RunPipeline = _tnl_run_pipeline; swdd->SetBuffer = this->SetBuffer; } void MesaDriver::LockGL() { m_bglview->LockLooper(); UpdateState(m_glcontext, 0); _mesa_make_current(m_glcontext, m_glframebuffer); } void MesaDriver::UnlockGL() { if (m_bglview->Looper()->IsLocked()) m_bglview->UnlockLooper(); // Could call _mesa_make_current(NULL, NULL) but it would just // hinder performance } void MesaDriver::SwapBuffers() const { _mesa_notifySwapBuffers(m_glcontext); if (m_bitmap) { m_bglview->LockLooper(); m_bglview->DrawBitmap(m_bitmap); m_bglview->UnlockLooper(); }; } void MesaDriver::CopySubBuffer(GLint x, GLint y, GLuint width, GLuint height) const { if (m_bitmap) { // Source bitmap and view's bitmap are same size. // Source and dest rectangle are the same. // Note (x,y) = (0,0) is the lower-left corner, have to flip Y BRect srcAndDest; srcAndDest.left = x; srcAndDest.right = x + width - 1; srcAndDest.bottom = m_bottom - y; srcAndDest.top = srcAndDest.bottom - height + 1; m_bglview->DrawBitmap(m_bitmap, srcAndDest, srcAndDest); } } status_t MesaDriver::CopyPixelsOut(BPoint location, BBitmap *bitmap) { color_space scs = m_bitmap->ColorSpace(); color_space dcs = bitmap->ColorSpace(); if (scs != dcs && (scs != B_RGBA32 || dcs != B_RGB32)) { printf("CopyPixelsOut(): incompatible color space: %s != %s\n", color_space_name(scs), color_space_name(dcs)); return B_BAD_TYPE; } // debugger("CopyPixelsOut()"); BRect sr = m_bitmap->Bounds(); BRect dr = bitmap->Bounds(); sr = sr & dr.OffsetBySelf(location); dr = sr.OffsetByCopy(-location.x, -location.y); uint8 *ps = (uint8 *) m_bitmap->Bits(); uint8 *pd = (uint8 *) bitmap->Bits(); uint32 *s, *d; uint32 y; for (y = (uint32) sr.top; y <= (uint32) sr.bottom; y++) { s = (uint32 *) (ps + y * m_bitmap->BytesPerRow()); s += (uint32) sr.left; d = (uint32 *) (pd + (y + (uint32) (dr.top - sr.top)) * bitmap->BytesPerRow()); d += (uint32) dr.left; memcpy(d, s, dr.IntegerWidth() * 4); } return B_OK; } status_t MesaDriver::CopyPixelsIn(BBitmap *bitmap, BPoint location) { color_space scs = bitmap->ColorSpace(); color_space dcs = m_bitmap->ColorSpace(); if (scs != dcs && (dcs != B_RGBA32 || scs != B_RGB32)) { printf("CopyPixelsIn(): incompatible color space: %s != %s\n", color_space_name(scs), color_space_name(dcs)); return B_BAD_TYPE; } // debugger("CopyPixelsIn()"); BRect sr = bitmap->Bounds(); BRect dr = m_bitmap->Bounds(); sr = sr & dr.OffsetBySelf(location); dr = sr.OffsetByCopy(-location.x, -location.y); uint8 *ps = (uint8 *) bitmap->Bits(); uint8 *pd = (uint8 *) m_bitmap->Bits(); uint32 *s, *d; uint32 y; for (y = (uint32) sr.top; y <= (uint32) sr.bottom; y++) { s = (uint32 *) (ps + y * bitmap->BytesPerRow()); s += (uint32) sr.left; d = (uint32 *) (pd + (y + (uint32) (dr.top - sr.top)) * m_bitmap->BytesPerRow()); d += (uint32) dr.left; memcpy(d, s, dr.IntegerWidth() * 4); } return B_OK; } void MesaDriver::Draw(BRect updateRect) const { if (m_bitmap) m_bglview->DrawBitmap(m_bitmap, updateRect, updateRect); } void MesaDriver::Error(struct gl_context *ctx) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; if (md && md->m_bglview) md->m_bglview->ErrorCallback((unsigned long) ctx->ErrorValue); } void MesaDriver::UpdateState( struct gl_context *ctx, GLuint new_state ) { struct swrast_device_driver * swdd = _swrast_GetDeviceDriverReference( ctx ); _swrast_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); _vbo_InvalidateState( ctx, new_state ); _tnl_InvalidateState( ctx, new_state ); if (ctx->Color.DrawBuffer[0] == GL_FRONT) { /* read/write front buffer */ swdd->WriteRGBASpan = MesaDriver::WriteRGBASpanFront; swdd->WriteRGBSpan = MesaDriver::WriteRGBSpanFront; swdd->WriteRGBAPixels = MesaDriver::WriteRGBAPixelsFront; swdd->WriteMonoRGBASpan = MesaDriver::WriteMonoRGBASpanFront; swdd->WriteMonoRGBAPixels = MesaDriver::WriteMonoRGBAPixelsFront; swdd->WriteCI32Span = MesaDriver::WriteCI32SpanFront; swdd->WriteCI8Span = MesaDriver::WriteCI8SpanFront; swdd->WriteMonoCISpan = MesaDriver::WriteMonoCISpanFront; swdd->WriteCI32Pixels = MesaDriver::WriteCI32PixelsFront; swdd->WriteMonoCIPixels = MesaDriver::WriteMonoCIPixelsFront; swdd->ReadRGBASpan = MesaDriver::ReadRGBASpanFront; swdd->ReadRGBAPixels = MesaDriver::ReadRGBAPixelsFront; swdd->ReadCI32Span = MesaDriver::ReadCI32SpanFront; swdd->ReadCI32Pixels = MesaDriver::ReadCI32PixelsFront; } else { /* read/write back buffer */ swdd->WriteRGBASpan = MesaDriver::WriteRGBASpanBack; swdd->WriteRGBSpan = MesaDriver::WriteRGBSpanBack; swdd->WriteRGBAPixels = MesaDriver::WriteRGBAPixelsBack; swdd->WriteMonoRGBASpan = MesaDriver::WriteMonoRGBASpanBack; swdd->WriteMonoRGBAPixels = MesaDriver::WriteMonoRGBAPixelsBack; swdd->WriteCI32Span = MesaDriver::WriteCI32SpanBack; swdd->WriteCI8Span = MesaDriver::WriteCI8SpanBack; swdd->WriteMonoCISpan = MesaDriver::WriteMonoCISpanBack; swdd->WriteCI32Pixels = MesaDriver::WriteCI32PixelsBack; swdd->WriteMonoCIPixels = MesaDriver::WriteMonoCIPixelsBack; swdd->ReadRGBASpan = MesaDriver::ReadRGBASpanBack; swdd->ReadRGBAPixels = MesaDriver::ReadRGBAPixelsBack; swdd->ReadCI32Span = MesaDriver::ReadCI32SpanBack; swdd->ReadCI32Pixels = MesaDriver::ReadCI32PixelsBack; } } void MesaDriver::ClearIndex(struct gl_context *ctx, GLuint index) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; md->m_clear_index = index; } void MesaDriver::ClearColor(struct gl_context *ctx, const GLfloat color[4]) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; CLAMPED_FLOAT_TO_CHAN(md->m_clear_color[BE_RCOMP], color[0]); CLAMPED_FLOAT_TO_CHAN(md->m_clear_color[BE_GCOMP], color[1]); CLAMPED_FLOAT_TO_CHAN(md->m_clear_color[BE_BCOMP], color[2]); CLAMPED_FLOAT_TO_CHAN(md->m_clear_color[BE_ACOMP], color[3]); assert(md->m_bglview); } void MesaDriver::Clear(struct gl_context *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height) { if (mask & DD_FRONT_LEFT_BIT) ClearFront(ctx, all, x, y, width, height); if (mask & DD_BACK_LEFT_BIT) ClearBack(ctx, all, x, y, width, height); mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT); if (mask) _swrast_Clear( ctx, mask, all, x, y, width, height ); return; } void MesaDriver::ClearFront(struct gl_context *ctx, GLboolean all, GLint x, GLint y, GLint width, GLint height) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BGLView *bglview = md->m_bglview; assert(bglview); bglview->SetHighColor(md->m_clear_color[BE_RCOMP], md->m_clear_color[BE_GCOMP], md->m_clear_color[BE_BCOMP], md->m_clear_color[BE_ACOMP]); bglview->SetLowColor(md->m_clear_color[BE_RCOMP], md->m_clear_color[BE_GCOMP], md->m_clear_color[BE_BCOMP], md->m_clear_color[BE_ACOMP]); if (all) { BRect b = bglview->Bounds(); bglview->FillRect(b); } else { // XXX untested BRect b; b.left = x; b.right = x + width; b.bottom = md->m_height - y - 1; b.top = b.bottom - height; bglview->FillRect(b); } // restore drawing color #if 0 bglview->SetHighColor(md->mColor[BE_RCOMP], md->mColor[BE_GCOMP], md->mColor[BE_BCOMP], md->mColor[BE_ACOMP]); bglview->SetLowColor(md->mColor[BE_RCOMP], md->mColor[BE_GCOMP], md->mColor[BE_BCOMP], md->mColor[BE_ACOMP]); #endif } void MesaDriver::ClearBack(struct gl_context *ctx, GLboolean all, GLint x, GLint y, GLint width, GLint height) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BGLView *bglview = md->m_bglview; assert(bglview); BBitmap *bitmap = md->m_bitmap; assert(bitmap); GLuint *start = (GLuint *) bitmap->Bits(); const GLuint *clearPixelPtr = (const GLuint *) md->m_clear_color; const GLuint clearPixel = B_LENDIAN_TO_HOST_INT32(*clearPixelPtr); if (all) { const int numPixels = md->m_width * md->m_height; if (clearPixel == 0) { memset(start, 0, numPixels * 4); } else { for (int i = 0; i < numPixels; i++) { start[i] = clearPixel; } } } else { // XXX untested start += y * md->m_width + x; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { start[j] = clearPixel; } start += md->m_width; } } } void MesaDriver::SetBuffer(struct gl_context *ctx, struct gl_framebuffer *buffer, GLenum mode) { /* TODO */ (void) ctx; (void) buffer; (void) mode; } void MesaDriver::GetBufferSize(struct gl_framebuffer * framebuffer, GLuint *width, GLuint *height) { GET_CURRENT_CONTEXT(ctx); if (!ctx) return; MesaDriver * md = (MesaDriver *) ctx->DriverCtx; BGLView *bglview = md->m_bglview; assert(bglview); BRect b = bglview->Bounds(); *width = (GLuint) b.IntegerWidth() + 1; // (b.right - b.left + 1); *height = (GLuint) b.IntegerHeight() + 1; // (b.bottom - b.top + 1); md->m_bottom = (GLint) b.bottom; if (ctx->Visual.doubleBufferMode) { if (*width != md->m_width || *height != md->m_height) { // allocate new size of back buffer bitmap if (md->m_bitmap) delete md->m_bitmap; BRect rect(0.0, 0.0, *width - 1, *height - 1); md->m_bitmap = new BBitmap(rect, B_RGBA32); } } else { md->m_bitmap = NULL; } md->m_width = *width; md->m_height = *height; } void MesaDriver::Viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) { /* poll for window size change and realloc software Z/stencil/etc if needed */ _mesa_ResizeBuffersMESA(); } const GLubyte *MesaDriver::GetString(struct gl_context *ctx, GLenum name) { switch (name) { case GL_RENDERER: return (const GLubyte *) "Mesa " MESA_VERSION_STRING " powered BGLView (software)"; default: // Let core library handle all other cases return NULL; } } // Plot a pixel. (0,0) is upper-left corner // This is only used when drawing to the front buffer. inline void Plot(BGLView *bglview, int x, int y) { // XXX There's got to be a better way! BPoint p(x, y), q(x+1, y); bglview->StrokeLine(p, q); } void MesaDriver::WriteRGBASpanFront(const struct gl_context *ctx, GLuint n, GLint x, GLint y, CONST GLubyte rgba[][4], const GLubyte mask[]) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BGLView *bglview = md->m_bglview; assert(bglview); int flippedY = md->m_bottom - y; if (mask) { for (GLuint i = 0; i < n; i++) { if (mask[i]) { bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2], rgba[i][3]); Plot(bglview, x++, flippedY); } } } else { for (GLuint i = 0; i < n; i++) { bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2], rgba[i][3]); Plot(bglview, x++, flippedY); } } } void MesaDriver::WriteRGBSpanFront(const struct gl_context *ctx, GLuint n, GLint x, GLint y, CONST GLubyte rgba[][3], const GLubyte mask[]) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BGLView *bglview = md->m_bglview; assert(bglview); int flippedY = md->m_bottom - y; if (mask) { for (GLuint i = 0; i < n; i++) { if (mask[i]) { bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]); Plot(bglview, x++, flippedY); } } } else { for (GLuint i = 0; i < n; i++) { bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]); Plot(bglview, x++, flippedY); } } } void MesaDriver::WriteMonoRGBASpanFront(const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLchan color[4], const GLubyte mask[]) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BGLView *bglview = md->m_bglview; assert(bglview); int flippedY = md->m_bottom - y; bglview->SetHighColor(color[RCOMP], color[GCOMP], color[BCOMP]); if (mask) { for (GLuint i = 0; i < n; i++) { if (mask[i]) { Plot(bglview, x++, flippedY); } } } else { for (GLuint i = 0; i < n; i++) { Plot(bglview, x++, flippedY); } } } void MesaDriver::WriteRGBAPixelsFront(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], CONST GLubyte rgba[][4], const GLubyte mask[] ) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BGLView *bglview = md->m_bglview; assert(bglview); if (mask) { for (GLuint i = 0; i < n; i++) { if (mask[i]) { bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]); Plot(bglview, x[i], md->m_bottom - y[i]); } } } else { for (GLuint i = 0; i < n; i++) { bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]); Plot(bglview, x[i], md->m_bottom - y[i]); } } } void MesaDriver::WriteMonoRGBAPixelsFront(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], const GLchan color[4], const GLubyte mask[]) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BGLView *bglview = md->m_bglview; assert(bglview); // plot points using current color bglview->SetHighColor(color[RCOMP], color[GCOMP], color[BCOMP]); if (mask) { for (GLuint i = 0; i < n; i++) { if (mask[i]) { Plot(bglview, x[i], md->m_bottom - y[i]); } } } else { for (GLuint i = 0; i < n; i++) { Plot(bglview, x[i], md->m_bottom - y[i]); } } } void MesaDriver::WriteCI32SpanFront( const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLuint index[], const GLubyte mask[] ) { printf("WriteCI32SpanFront() not implemented yet!\n"); // TODO } void MesaDriver::WriteCI8SpanFront( const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLubyte index[], const GLubyte mask[] ) { printf("WriteCI8SpanFront() not implemented yet!\n"); // TODO } void MesaDriver::WriteMonoCISpanFront( const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLuint colorIndex, const GLubyte mask[] ) { printf("WriteMonoCISpanFront() not implemented yet!\n"); // TODO } void MesaDriver::WriteCI32PixelsFront( const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], const GLuint index[], const GLubyte mask[] ) { printf("WriteCI32PixelsFront() not implemented yet!\n"); // TODO } void MesaDriver::WriteMonoCIPixelsFront( const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLuint colorIndex, const GLubyte mask[] ) { printf("WriteMonoCIPixelsFront() not implemented yet!\n"); // TODO } void MesaDriver::ReadCI32SpanFront( const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLuint index[] ) { printf("ReadCI32SpanFront() not implemented yet!\n"); // TODO } void MesaDriver::ReadRGBASpanFront( const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] ) { printf("ReadRGBASpanFront() not implemented yet!\n"); // TODO } void MesaDriver::ReadCI32PixelsFront( const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLuint indx[], const GLubyte mask[] ) { printf("ReadCI32PixelsFront() not implemented yet!\n"); // TODO } void MesaDriver::ReadRGBAPixelsFront( const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] ) { printf("ReadRGBAPixelsFront() not implemented yet!\n"); // TODO } void MesaDriver::WriteRGBASpanBack(const struct gl_context *ctx, GLuint n, GLint x, GLint y, CONST GLubyte rgba[][4], const GLubyte mask[]) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BBitmap *bitmap = md->m_bitmap; assert(bitmap); int row = md->m_bottom - y; uint8 * ptr = (uint8 *) bitmap->Bits() + (row * bitmap->BytesPerRow()) + x * 4; uint32 * pixel = (uint32 *) ptr; if (mask) { while(n--) { if (*mask++) *pixel = PACK_B_RGBA32(rgba[0]); pixel++; rgba++; }; } else { while(n--) { *pixel++ = PACK_B_RGBA32(rgba[0]); rgba++; }; }; } void MesaDriver::WriteRGBSpanBack(const struct gl_context *ctx, GLuint n, GLint x, GLint y, CONST GLubyte rgb[][3], const GLubyte mask[]) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BBitmap *bitmap = md->m_bitmap; assert(bitmap); int row = md->m_bottom - y; uint8 * ptr = (uint8 *) bitmap->Bits() + (row * bitmap->BytesPerRow()) + x * 4; uint32 * pixel = (uint32 *) ptr; if (mask) { while(n--) { if (*mask++) *pixel = PACK_B_RGB32(rgb[0]); pixel++; rgb++; }; } else { while(n--) { *pixel++ = PACK_B_RGB32(rgb[0]); rgb++; }; }; } void MesaDriver::WriteMonoRGBASpanBack(const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLchan color[4], const GLubyte mask[]) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BBitmap *bitmap = md->m_bitmap; assert(bitmap); int row = md->m_bottom - y; uint8 * ptr = (uint8 *) bitmap->Bits() + (row * bitmap->BytesPerRow()) + x * 4; uint32 * pixel = (uint32 *) ptr; uint32 pixel_color = PACK_B_RGBA32(color); if (mask) { while(n--) { if (*mask++) *pixel = pixel_color; pixel++; }; } else { while(n--) { *pixel++ = pixel_color; }; }; } void MesaDriver::WriteRGBAPixelsBack(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], CONST GLubyte rgba[][4], const GLubyte mask[] ) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BBitmap *bitmap = md->m_bitmap; assert(bitmap); #if 0 while(n--) { if (*mask++) { int row = md->m_bottom - *y; uint8 * pixel = (uint8 *) bitmap->Bits() + (row * bitmap->BytesPerRow()) + *x * 4; *((uint32 *) pixel) = PACK_B_RGBA32(rgba[0]); }; x++; y++; rgba++; }; #else if (mask) { for (GLuint i = 0; i < n; i++) { if (mask[i]) { GLubyte *pixel = (GLubyte *) bitmap->Bits() + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4; pixel[BE_RCOMP] = rgba[i][RCOMP]; pixel[BE_GCOMP] = rgba[i][GCOMP]; pixel[BE_BCOMP] = rgba[i][BCOMP]; pixel[BE_ACOMP] = rgba[i][ACOMP]; } } } else { for (GLuint i = 0; i < n; i++) { GLubyte *pixel = (GLubyte *) bitmap->Bits() + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4; pixel[BE_RCOMP] = rgba[i][RCOMP]; pixel[BE_GCOMP] = rgba[i][GCOMP]; pixel[BE_BCOMP] = rgba[i][BCOMP]; pixel[BE_ACOMP] = rgba[i][ACOMP]; } } #endif } void MesaDriver::WriteMonoRGBAPixelsBack(const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], const GLchan color[4], const GLubyte mask[]) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; BBitmap *bitmap = md->m_bitmap; assert(bitmap); uint32 pixel_color = PACK_B_RGBA32(color); #if 0 while(n--) { if (*mask++) { int row = md->m_bottom - *y; uint8 * pixel = (uint8 *) bitmap->Bits() + (row * bitmap->BytesPerRow()) + *x * 4; *((uint32 *) pixel) = pixel_color; }; x++; y++; }; #else if (mask) { for (GLuint i = 0; i < n; i++) { if (mask[i]) { GLubyte * ptr = (GLubyte *) bitmap->Bits() + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4; *((uint32 *) ptr) = pixel_color; } } } else { for (GLuint i = 0; i < n; i++) { GLubyte * ptr = (GLubyte *) bitmap->Bits() + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4; *((uint32 *) ptr) = pixel_color; } } #endif } void MesaDriver::WriteCI32SpanBack( const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLuint index[], const GLubyte mask[] ) { printf("WriteCI32SpanBack() not implemented yet!\n"); // TODO } void MesaDriver::WriteCI8SpanBack( const struct gl_context *ctx, GLuint n, GLint x, GLint y, const GLubyte index[], const GLubyte mask[] ) { printf("WriteCI8SpanBack() not implemented yet!\n"); // TODO } void MesaDriver::WriteMonoCISpanBack( const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLuint colorIndex, const GLubyte mask[] ) { printf("WriteMonoCISpanBack() not implemented yet!\n"); // TODO } void MesaDriver::WriteCI32PixelsBack( const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], const GLuint index[], const GLubyte mask[] ) { printf("WriteCI32PixelsBack() not implemented yet!\n"); // TODO } void MesaDriver::WriteMonoCIPixelsBack( const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLuint colorIndex, const GLubyte mask[] ) { printf("WriteMonoCIPixelsBack() not implemented yet!\n"); // TODO } void MesaDriver::ReadCI32SpanBack( const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLuint index[] ) { printf("ReadCI32SpanBack() not implemented yet!\n"); // TODO } void MesaDriver::ReadRGBASpanBack( const struct gl_context *ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] ) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; const BBitmap *bitmap = md->m_bitmap; assert(bitmap); int row = md->m_bottom - y; const GLubyte *pixel = (GLubyte *) bitmap->Bits() + (row * bitmap->BytesPerRow()) + x * 4; for (GLuint i = 0; i < n; i++) { rgba[i][RCOMP] = pixel[BE_RCOMP]; rgba[i][GCOMP] = pixel[BE_GCOMP]; rgba[i][BCOMP] = pixel[BE_BCOMP]; rgba[i][ACOMP] = pixel[BE_ACOMP]; pixel += 4; } } void MesaDriver::ReadCI32PixelsBack( const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLuint indx[], const GLubyte mask[] ) { printf("ReadCI32PixelsBack() not implemented yet!\n"); // TODO } void MesaDriver::ReadRGBAPixelsBack( const struct gl_context *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] ) { MesaDriver *md = (MesaDriver *) ctx->DriverCtx; const BBitmap *bitmap = md->m_bitmap; assert(bitmap); if (mask) { for (GLuint i = 0; i < n; i++) { if (mask[i]) { GLubyte *pixel = (GLubyte *) bitmap->Bits() + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4; rgba[i][RCOMP] = pixel[BE_RCOMP]; rgba[i][GCOMP] = pixel[BE_GCOMP]; rgba[i][BCOMP] = pixel[BE_BCOMP]; rgba[i][ACOMP] = pixel[BE_ACOMP]; }; }; } else { for (GLuint i = 0; i < n; i++) { GLubyte *pixel = (GLubyte *) bitmap->Bits() + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4; rgba[i][RCOMP] = pixel[BE_RCOMP]; rgba[i][GCOMP] = pixel[BE_GCOMP]; rgba[i][BCOMP] = pixel[BE_BCOMP]; rgba[i][ACOMP] = pixel[BE_ACOMP]; }; }; } const char * color_space_name(color_space space) { #define C2N(a) case a: return #a switch (space) { C2N(B_RGB24); C2N(B_RGB32); C2N(B_RGBA32); C2N(B_RGB32_BIG); C2N(B_RGBA32_BIG); C2N(B_GRAY8); C2N(B_GRAY1); C2N(B_RGB16); C2N(B_RGB15); C2N(B_RGBA15); C2N(B_CMAP8); default: return "Unknown!"; }; #undef C2N };