hgl: Major refactor and cleanup

* Drop old-timey GLDisplatcher
* Refactor haiku-softpipe fixing some hacks
* Bubble BBitmap up to winsys

Reviewed-by: Alexander von Gluck IV <kallisti5@unixzen.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8323>
This commit is contained in:
X512 2021-01-05 00:12:38 -06:00 committed by Alexander von Gluck IV
parent bd6ea80d96
commit 065cf4f914
18 changed files with 506 additions and 683 deletions

View File

@ -27,8 +27,7 @@ class _EXPORT BGLRenderer
BGLRenderer & operator=(const BGLRenderer &); BGLRenderer & operator=(const BGLRenderer &);
public: public:
BGLRenderer(BGLView *view, ulong bgl_options, BGLRenderer(BGLView *view, ulong bgl_options);
BGLDispatcher *dispatcher);
virtual ~BGLRenderer(); virtual ~BGLRenderer();
void Acquire(); void Acquire();
@ -50,7 +49,6 @@ public:
inline int32 ReferenceCount() const { return fRefCount; }; inline int32 ReferenceCount() const { return fRefCount; };
inline ulong Options() const { return fOptions; }; inline ulong Options() const { return fOptions; };
inline BGLView* GLView() { return fView; }; inline BGLView* GLView() { return fView; };
inline BGLDispatcher* GLDispatcher() { return fDispatcher; };
private: private:
friend class GLRendererRoster; friend class GLRendererRoster;
@ -64,13 +62,12 @@ private:
int32 fRefCount; // How much we're still useful int32 fRefCount; // How much we're still useful
BGLView* fView; // Never forget who is the boss! BGLView* fView; // Never forget who is the boss!
ulong fOptions; // Keep that tune in memory ulong fOptions; // Keep that tune in memory
BGLDispatcher* fDispatcher;// Our personal GL API call dispatcher
GLRendererRoster* fOwningRoster; GLRendererRoster* fOwningRoster;
renderer_id fID; renderer_id fID;
}; };
extern "C" _EXPORT BGLRenderer* instantiate_gl_renderer(BGLView *view, ulong options, BGLDispatcher *dispatcher); extern "C" _EXPORT BGLRenderer* instantiate_gl_renderer(BGLView *view, ulong options);
#endif // GLRENDERER_H #endif // GLRENDERER_H

View File

@ -24,6 +24,7 @@
#define BGL_OVERLAY 64 #define BGL_OVERLAY 64
#define BGL_UNDERLAY 128 #define BGL_UNDERLAY 128
#define BGL_STENCIL 512 #define BGL_STENCIL 512
#define BGL_SHARE_CONTEXT 1024
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -57,24 +57,20 @@ hgl_st_framebuffer(struct st_framebuffer_iface *stfbi)
static bool static bool
hgl_st_framebuffer_flush_front(struct st_context_iface *stctxi, hgl_st_framebuffer_flush_front(struct st_context_iface* stctxi,
struct st_framebuffer_iface* stfbi, enum st_attachment_type statt) struct st_framebuffer_iface* stfbi, enum st_attachment_type statt)
{ {
CALLED(); CALLED();
//struct hgl_context* context = hgl_st_context(stctxi);
// struct hgl_buffer* buffer = hgl_st_context(stfbi);
struct hgl_buffer* buffer = hgl_st_framebuffer(stfbi); struct hgl_buffer* buffer = hgl_st_framebuffer(stfbi);
//buffer->surface struct pipe_resource* ptex = buffer->textures[statt];
#if 0 if (!ptex)
struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); return true;
mtx_lock(&stwfb->fb->mutex);
struct pipe_resource* resource = textures[statt]; // TODO: pipe_context here??? Might be needed for hw renderers
if (resource) buffer->screen->flush_frontbuffer(buffer->screen, NULL, ptex, 0, 0,
stw_framebuffer_present_locked(...); buffer->winsysContext, NULL);
#endif
return true; return true;
} }
@ -93,6 +89,8 @@ hgl_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
buffer = hgl_st_framebuffer(stfbi); buffer = hgl_st_framebuffer(stfbi);
if (buffer->width != width || buffer->height != height) { if (buffer->width != width || buffer->height != height) {
TRACE("validate_textures: size changed: %d, %d -> %d, %d\n",
buffer->width, buffer->height, width, height);
for (i = 0; i < ST_ATTACHMENT_COUNT; i++) for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
pipe_resource_reference(&buffer->textures[i], NULL); pipe_resource_reference(&buffer->textures[i], NULL);
} }
@ -109,6 +107,7 @@ hgl_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
enum pipe_format format; enum pipe_format format;
unsigned bind; unsigned bind;
if (((1 << i) & buffer->visual->buffer_mask) && buffer->textures[i] == NULL) {
switch (i) { switch (i) {
case ST_ATTACHMENT_FRONT_LEFT: case ST_ATTACHMENT_FRONT_LEFT:
case ST_ATTACHMENT_BACK_LEFT: case ST_ATTACHMENT_BACK_LEFT:
@ -130,12 +129,14 @@ hgl_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
if (format != PIPE_FORMAT_NONE) { if (format != PIPE_FORMAT_NONE) {
templat.format = format; templat.format = format;
templat.bind = bind; templat.bind = bind;
TRACE("resource_create(%d, %d, %d)\n", i, format, bind);
buffer->textures[i] = buffer->screen->resource_create(buffer->screen, buffer->textures[i] = buffer->screen->resource_create(buffer->screen,
&templat); &templat);
if (!buffer->textures[i]) if (!buffer->textures[i])
return FALSE; return FALSE;
} }
} }
}
buffer->width = width; buffer->width = width;
buffer->height = height; buffer->height = height;
@ -165,10 +166,6 @@ hgl_st_framebuffer_validate(struct st_context_iface *stctxi,
context = hgl_st_context(stctxi); context = hgl_st_context(stctxi);
buffer = hgl_st_framebuffer(stfbi); buffer = hgl_st_framebuffer(stfbi);
//int32 width = 0;
//int32 height = 0;
//get_bitmap_size(context->bitmap, &width, &height);
// Build mask of current attachments // Build mask of current attachments
stAttachmentMask = 0; stAttachmentMask = 0;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
@ -189,11 +186,6 @@ hgl_st_framebuffer_validate(struct st_context_iface *stctxi,
if (!ret) if (!ret)
return ret; return ret;
// TODO: Simply update attachments
//if (!resized) {
//}
} }
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
@ -223,14 +215,14 @@ static uint32_t hgl_fb_ID = 0;
* Create new framebuffer * Create new framebuffer
*/ */
struct hgl_buffer * struct hgl_buffer *
hgl_create_st_framebuffer(struct hgl_context* context) hgl_create_st_framebuffer(struct hgl_context* context, void *winsysContext)
{ {
struct hgl_buffer *buffer; struct hgl_buffer *buffer;
CALLED(); CALLED();
// Our requires before creating a framebuffer // Our requires before creating a framebuffer
assert(context); assert(context);
assert(context->screen); assert(context->display);
assert(context->stVisual); assert(context->stVisual);
buffer = CALLOC_STRUCT(hgl_buffer); buffer = CALLOC_STRUCT(hgl_buffer);
@ -242,9 +234,10 @@ hgl_create_st_framebuffer(struct hgl_context* context)
// Prepare our buffer // Prepare our buffer
buffer->visual = context->stVisual; buffer->visual = context->stVisual;
buffer->screen = context->screen; buffer->screen = context->display->manager->screen;
buffer->winsysContext = winsysContext;
if (context->screen->get_param(buffer->screen, PIPE_CAP_NPOT_TEXTURES)) if (buffer->screen->get_param(buffer->screen, PIPE_CAP_NPOT_TEXTURES))
buffer->target = PIPE_TEXTURE_2D; buffer->target = PIPE_TEXTURE_2D;
else else
buffer->target = PIPE_TEXTURE_RECT; buffer->target = PIPE_TEXTURE_RECT;
@ -257,12 +250,26 @@ hgl_create_st_framebuffer(struct hgl_context* context)
p_atomic_set(&buffer->stfbi->stamp, 1); p_atomic_set(&buffer->stfbi->stamp, 1);
buffer->stfbi->st_manager_private = (void*)buffer; buffer->stfbi->st_manager_private = (void*)buffer;
buffer->stfbi->ID = p_atomic_inc_return(&hgl_fb_ID); buffer->stfbi->ID = p_atomic_inc_return(&hgl_fb_ID);
buffer->stfbi->state_manager = context->manager; buffer->stfbi->state_manager = context->display->manager;
return buffer; return buffer;
} }
void
hgl_destroy_st_framebuffer(struct hgl_buffer *buffer)
{
CALLED();
int i;
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
pipe_resource_reference(&buffer->textures[i], NULL);
FREE(buffer->stfbi);
FREE(buffer);
}
struct st_api* struct st_api*
hgl_create_st_api() hgl_create_st_api()
{ {
@ -271,38 +278,6 @@ hgl_create_st_api()
} }
struct st_manager *
hgl_create_st_manager(struct hgl_context* context)
{
struct st_manager* manager;
CALLED();
// Required things
assert(context);
assert(context->screen);
manager = CALLOC_STRUCT(st_manager);
assert(manager);
//manager->display = dpy;
manager->screen = context->screen;
manager->get_param = hgl_st_manager_get_param;
manager->st_manager_private = (void *)context;
return manager;
}
void
hgl_destroy_st_manager(struct st_manager *manager)
{
CALLED();
FREE(manager);
}
struct st_visual* struct st_visual*
hgl_create_st_visual(ulong options) hgl_create_st_visual(ulong options)
{ {
@ -335,6 +310,7 @@ hgl_create_st_visual(ulong options)
visual->render_buffer = ST_ATTACHMENT_FRONT_LEFT; visual->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
if ((options & BGL_DOUBLE) != 0) { if ((options & BGL_DOUBLE) != 0) {
TRACE("double buffer enabled\n");
visual->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; visual->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
visual->render_buffer = ST_ATTACHMENT_BACK_LEFT; visual->render_buffer = ST_ATTACHMENT_BACK_LEFT;
} }
@ -364,3 +340,33 @@ hgl_destroy_st_visual(struct st_visual* visual)
FREE(visual); FREE(visual);
} }
struct hgl_display*
hgl_create_display(struct pipe_screen* screen)
{
struct hgl_display* display;
display = CALLOC_STRUCT(hgl_display);
assert(display);
display->api = st_gl_api_create();
display->manager = CALLOC_STRUCT(st_manager);
assert(display->manager);
display->manager->screen = screen;
display->manager->get_param = hgl_st_manager_get_param;
// display->manager->st_manager_private is used by llvmpipe
return display;
}
void
hgl_destroy_display(struct hgl_display *display)
{
if (display->manager->destroy)
display->manager->destroy(display->manager);
FREE(display->manager);
if (display->api->destroy)
display->api->destroy(display->api);
FREE(display);
}

View File

@ -8,15 +8,13 @@
#ifndef HGL_CONTEXT_H #ifndef HGL_CONTEXT_H
#define HGL_CONTEXT_H #define HGL_CONTEXT_H
#include "os/os_thread.h"
#include "pipe/p_format.h" #include "pipe/p_format.h"
#include "pipe/p_compiler.h" #include "pipe/p_compiler.h"
#include "pipe/p_screen.h" #include "pipe/p_screen.h"
#include "postprocess/filters.h" #include "postprocess/filters.h"
#include "frontend/api.h" #include "frontend/api.h"
#include "frontend/st_manager.h"
#include "os/os_thread.h"
#include "bitmap_wrapper.h" #include "bitmap_wrapper.h"
@ -41,31 +39,29 @@ struct hgl_buffer
unsigned mask; unsigned mask;
struct pipe_screen* screen; struct pipe_screen* screen;
struct pipe_surface* surface; void* winsysContext;
enum pipe_texture_target target; enum pipe_texture_target target;
struct pipe_resource* textures[ST_ATTACHMENT_COUNT]; struct pipe_resource* textures[ST_ATTACHMENT_COUNT];
void *map; void *map;
};
//struct hgl_buffer *next; /**< next in linked list */
struct hgl_display
{
mtx_t mutex;
struct st_api* api;
struct st_manager* manager;
}; };
struct hgl_context struct hgl_context
{ {
struct st_api* api; struct hgl_display* display;
// API
struct st_manager* manager;
// Manager
struct st_context_iface* st; struct st_context_iface* st;
// Interface Object
struct st_visual* stVisual; struct st_visual* stVisual;
// Visual
struct pipe_screen* screen;
//struct pipe_resource* textures[ST_ATTACHMENT_COUNT];
// Post processing // Post processing
struct pp_queue_t* postProcess; struct pp_queue_t* postProcess;
@ -75,13 +71,9 @@ struct hgl_context
unsigned width; unsigned width;
unsigned height; unsigned height;
Bitmap* bitmap;
color_space colorSpace;
mtx_t fbMutex; mtx_t fbMutex;
struct hgl_buffer* draw; struct hgl_buffer* buffer;
struct hgl_buffer* read;
}; };
// hgl_buffer from statetracker interface // hgl_buffer from statetracker interface
@ -91,7 +83,8 @@ struct hgl_buffer* hgl_st_framebuffer(struct st_framebuffer_iface *stfbi);
struct st_api* hgl_create_st_api(void); struct st_api* hgl_create_st_api(void);
// hgl framebuffer // hgl framebuffer
struct hgl_buffer* hgl_create_st_framebuffer(struct hgl_context* context); struct hgl_buffer* hgl_create_st_framebuffer(struct hgl_context* context, void *winsysContext);
void hgl_destroy_st_framebuffer(struct hgl_buffer *buffer);
// hgl manager // hgl manager
struct st_manager* hgl_create_st_manager(struct hgl_context* screen); struct st_manager* hgl_create_st_manager(struct hgl_context* screen);
@ -101,6 +94,10 @@ void hgl_destroy_st_manager(struct st_manager *manager);
struct st_visual* hgl_create_st_visual(ulong options); struct st_visual* hgl_create_st_visual(ulong options);
void hgl_destroy_st_visual(struct st_visual* visual); void hgl_destroy_st_visual(struct st_visual* visual);
// hgl display
struct hgl_display* hgl_create_display(struct pipe_screen* screen);
void hgl_destroy_display(struct hgl_display *display);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -11,6 +11,7 @@
#include "GalliumContext.h" #include "GalliumContext.h"
#include <stdio.h> #include <stdio.h>
#include <algorithm>
#include "GLView.h" #include "GLView.h"
@ -41,11 +42,12 @@
#endif #endif
#define ERROR(x...) printf("GalliumContext: " x) #define ERROR(x...) printf("GalliumContext: " x)
int32 GalliumContext::fDisplayRefCount = 0;
hgl_display* GalliumContext::fDisplay = NULL;
GalliumContext::GalliumContext(ulong options) GalliumContext::GalliumContext(ulong options)
: :
fOptions(options), fOptions(options),
fScreen(NULL),
fCurrentContext(0) fCurrentContext(0)
{ {
CALLED(); CALLED();
@ -54,7 +56,7 @@ GalliumContext::GalliumContext(ulong options)
for (context_id i = 0; i < CONTEXT_MAX; i++) for (context_id i = 0; i < CONTEXT_MAX; i++)
fContext[i] = NULL; fContext[i] = NULL;
CreateScreen(); CreateDisplay();
(void) mtx_init(&fMutex, mtx_plain); (void) mtx_init(&fMutex, mtx_plain);
} }
@ -70,17 +72,20 @@ GalliumContext::~GalliumContext()
DestroyContext(i); DestroyContext(i);
Unlock(); Unlock();
mtx_destroy(&fMutex); DestroyDisplay();
// TODO: Destroy fScreen mtx_destroy(&fMutex);
} }
status_t status_t
GalliumContext::CreateScreen() GalliumContext::CreateDisplay()
{ {
CALLED(); CALLED();
if (atomic_add(&fDisplayRefCount, 1) > 0)
return B_OK;
// Allocate winsys and attach callback hooks // Allocate winsys and attach callback hooks
struct sw_winsys* winsys = hgl_create_sw_winsys(); struct sw_winsys* winsys = hgl_create_sw_winsys();
@ -89,25 +94,47 @@ GalliumContext::CreateScreen()
return B_ERROR; return B_ERROR;
} }
fScreen = sw_screen_create(winsys); struct pipe_screen* screen = sw_screen_create(winsys);
if (fScreen == NULL) { if (screen == NULL) {
ERROR("%s: Couldn't create screen!\n", __FUNCTION__); ERROR("%s: Couldn't create screen!\n", __FUNCTION__);
FREE(winsys); winsys->destroy(winsys);
return B_ERROR; return B_ERROR;
} }
debug_screen_wrap(fScreen); debug_screen_wrap(screen);
const char* driverName = fScreen->get_name(fScreen); const char* driverName = screen->get_name(screen);
ERROR("%s: Using %s driver.\n", __func__, driverName); ERROR("%s: Using %s driver.\n", __func__, driverName);
fDisplay = hgl_create_display(screen);
if (fDisplay == NULL) {
ERROR("%s: Couldn't create display!\n", __FUNCTION__);
screen->destroy(screen); // will also destroy winsys
return B_ERROR;
}
return B_OK; return B_OK;
} }
void
GalliumContext::DestroyDisplay()
{
if (atomic_add(&fDisplayRefCount, -1) > 1)
return;
if (fDisplay != NULL) {
struct pipe_screen* screen = fDisplay->manager->screen;
hgl_destroy_display(fDisplay); fDisplay = NULL;
screen->destroy(screen); // destroy will deallocate object
}
}
context_id context_id
GalliumContext::CreateContext(Bitmap *bitmap) GalliumContext::CreateContext(HGLWinsysContext *wsContext)
{ {
CALLED(); CALLED();
@ -119,31 +146,15 @@ GalliumContext::CreateContext(Bitmap *bitmap)
} }
// Set up the initial things our context needs // Set up the initial things our context needs
context->bitmap = bitmap; context->display = fDisplay;
context->colorSpace = get_bitmap_color_space(bitmap);
context->screen = fScreen;
context->draw = NULL;
context->read = NULL;
context->st = NULL;
// Create st_gl_api
context->api = hgl_create_st_api();
if (!context->api) {
ERROR("%s: Couldn't obtain Mesa state tracker API!\n", __func__);
return -1;
}
// Create state_tracker manager
context->manager = hgl_create_st_manager(context);
// Create state tracker visual // Create state tracker visual
context->stVisual = hgl_create_st_visual(fOptions); context->stVisual = hgl_create_st_visual(fOptions);
// Create state tracker framebuffers // Create state tracker framebuffers
context->draw = hgl_create_st_framebuffer(context); context->buffer = hgl_create_st_framebuffer(context, wsContext);
context->read = hgl_create_st_framebuffer(context);
if (!context->draw || !context->read) { if (!context->buffer) {
ERROR("%s: Problem allocating framebuffer!\n", __func__); ERROR("%s: Problem allocating framebuffer!\n", __func__);
FREE(context->stVisual); FREE(context->stVisual);
return -1; return -1;
@ -159,10 +170,17 @@ GalliumContext::CreateContext(Bitmap *bitmap)
attribs.minor = 0; attribs.minor = 0;
//attribs.flags |= ST_CONTEXT_FLAG_DEBUG; //attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
struct st_context_iface* shared = NULL;
if (fOptions & BGL_SHARE_CONTEXT) {
shared = fDisplay->api->get_current(fDisplay->api);
TRACE("shared context: %p\n", shared);
}
// Create context using state tracker api call // Create context using state tracker api call
enum st_context_error result; enum st_context_error result;
context->st = context->api->create_context(context->api, context->manager, context->st = fDisplay->api->create_context(fDisplay->api, fDisplay->manager,
&attribs, &result, context->st); &attribs, &result, shared);
if (!context->st) { if (!context->st) {
ERROR("%s: Couldn't create mesa state tracker context!\n", ERROR("%s: Couldn't create mesa state tracker context!\n",
@ -243,7 +261,7 @@ GalliumContext::DestroyContext(context_id contextID)
return; return;
if (fContext[contextID]->st) { if (fContext[contextID]->st) {
fContext[contextID]->st->flush(fContext[contextID]->st, 0, NULL); fContext[contextID]->st->flush(fContext[contextID]->st, 0, NULL, NULL, NULL);
fContext[contextID]->st->destroy(fContext[contextID]->st); fContext[contextID]->st->destroy(fContext[contextID]->st);
} }
@ -251,23 +269,18 @@ GalliumContext::DestroyContext(context_id contextID)
pp_free(fContext[contextID]->postProcess); pp_free(fContext[contextID]->postProcess);
// Delete state tracker framebuffer objects // Delete state tracker framebuffer objects
if (fContext[contextID]->read) if (fContext[contextID]->buffer)
delete fContext[contextID]->read; hgl_destroy_st_framebuffer(fContext[contextID]->buffer);
if (fContext[contextID]->draw)
delete fContext[contextID]->draw;
if (fContext[contextID]->stVisual) if (fContext[contextID]->stVisual)
hgl_destroy_st_visual(fContext[contextID]->stVisual); hgl_destroy_st_visual(fContext[contextID]->stVisual);
if (fContext[contextID]->manager)
hgl_destroy_st_manager(fContext[contextID]->manager);
FREE(fContext[contextID]); FREE(fContext[contextID]);
} }
status_t status_t
GalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID) GalliumContext::SetCurrentContext(bool set, context_id contextID)
{ {
CALLED(); CALLED();
@ -279,16 +292,17 @@ GalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID)
Lock(); Lock();
context_id oldContextID = fCurrentContext; context_id oldContextID = fCurrentContext;
struct hgl_context* context = fContext[contextID]; struct hgl_context* context = fContext[contextID];
Unlock();
if (!context) { if (!context) {
ERROR("%s: Invalid context provided (#%" B_PRIu64 ")!\n", ERROR("%s: Invalid context provided (#%" B_PRIu64 ")!\n",
__func__, contextID); __func__, contextID);
Unlock();
return B_ERROR; return B_ERROR;
} }
if (!bitmap) { if (!set) {
context->api->make_current(context->api, NULL, NULL, NULL); fDisplay->api->make_current(fDisplay->api, NULL, NULL, NULL);
Unlock();
return B_OK; return B_OK;
} }
@ -297,24 +311,13 @@ GalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID)
if (oldContextID > 0 && oldContextID != contextID) { if (oldContextID > 0 && oldContextID != contextID) {
fContext[oldContextID]->st->flush(fContext[oldContextID]->st, fContext[oldContextID]->st->flush(fContext[oldContextID]->st,
ST_FLUSH_FRONT, NULL); ST_FLUSH_FRONT, NULL, NULL, NULL);
} }
// We need to lock and unlock framebuffers before accessing them // We need to lock and unlock framebuffers before accessing them
context->api->make_current(context->api, context->st, context->draw->stfbi, fDisplay->api->make_current(fDisplay->api, context->st, context->buffer->stfbi,
context->read->stfbi); context->buffer->stfbi);
Unlock();
//if (context->textures[ST_ATTACHMENT_BACK_LEFT]
// && context->textures[ST_ATTACHMENT_DEPTH_STENCIL]
// && context->postProcess) {
// TRACE("Postprocessing textures...\n");
// pp_init_fbos(context->postProcess,
// context->textures[ST_ATTACHMENT_BACK_LEFT]->width0,
// context->textures[ST_ATTACHMENT_BACK_LEFT]->height0);
//}
context->bitmap = bitmap;
//context->st->pipe->priv = context;
return B_OK; return B_OK;
} }
@ -326,40 +329,62 @@ GalliumContext::SwapBuffers(context_id contextID)
CALLED(); CALLED();
Lock(); Lock();
struct hgl_context *context = fContext[contextID]; struct hgl_context* context = fContext[contextID];
Unlock();
if (!context) { if (!context) {
ERROR("%s: context not found\n", __func__); ERROR("%s: context not found\n", __func__);
return B_ERROR; Unlock();
}
context->st->flush(context->st, ST_FLUSH_FRONT, NULL);
struct hgl_buffer* buffer = hgl_st_framebuffer(context->draw->stfbi);
pipe_surface* surface = buffer->surface;
if (!surface) {
ERROR("%s: Invalid drawable surface!\n", __func__);
return B_ERROR; return B_ERROR;
} }
fScreen->flush_frontbuffer(fScreen, context->st->pipe, surface->texture, 0, 0, // will flush front buffer if no double buffering is used
context->bitmap, NULL); context->st->flush(context->st, ST_FLUSH_FRONT, NULL, NULL, NULL);
struct hgl_buffer* buffer = context->buffer;
// flush back buffer and swap buffers if double buffering is used
if (buffer->textures[ST_ATTACHMENT_BACK_LEFT] != NULL) {
buffer->screen->flush_frontbuffer(buffer->screen, NULL, buffer->textures[ST_ATTACHMENT_BACK_LEFT],
0, 0, buffer->winsysContext, NULL);
std::swap(buffer->textures[ST_ATTACHMENT_FRONT_LEFT], buffer->textures[ST_ATTACHMENT_BACK_LEFT]);
p_atomic_inc(&buffer->stfbi->stamp);
}
Unlock();
return B_OK; return B_OK;
} }
void
GalliumContext::Draw(context_id contextID, BRect updateRect)
{
struct hgl_context *context = fContext[contextID];
if (!context) {
ERROR("%s: context not found\n", __func__);
return;
}
struct hgl_buffer* buffer = context->buffer;
if (buffer->textures[ST_ATTACHMENT_FRONT_LEFT] == NULL)
return;
buffer->screen->flush_frontbuffer(buffer->screen, NULL, buffer->textures[ST_ATTACHMENT_FRONT_LEFT],
0, 0, buffer->winsysContext, NULL);
}
bool bool
GalliumContext::Validate(uint32 width, uint32 height) GalliumContext::Validate(uint32 width, uint32 height)
{ {
CALLED(); CALLED();
if (!fContext[fCurrentContext]) { if (!fContext[fCurrentContext])
return false; return false;
}
if (fContext[fCurrentContext]->width != width if (fContext[fCurrentContext]->width != width + 1
|| fContext[fCurrentContext]->height != height) { || fContext[fCurrentContext]->height != height + 1) {
Invalidate(width, height); Invalidate(width, height);
return false; return false;
} }
@ -375,12 +400,11 @@ GalliumContext::Invalidate(uint32 width, uint32 height)
assert(fContext[fCurrentContext]); assert(fContext[fCurrentContext]);
// Update st_context dimensions // Update st_context dimensions
fContext[fCurrentContext]->width = width; fContext[fCurrentContext]->width = width + 1;
fContext[fCurrentContext]->height = height; fContext[fCurrentContext]->height = height + 1;
// Is this the best way to invalidate? // Is this the best way to invalidate?
p_atomic_inc(&fContext[fCurrentContext]->read->stfbi->stamp); p_atomic_inc(&fContext[fCurrentContext]->buffer->stfbi->stamp);
p_atomic_inc(&fContext[fCurrentContext]->draw->stfbi->stamp);
} }

View File

@ -16,10 +16,10 @@
#include "pipe/p_screen.h" #include "pipe/p_screen.h"
#include "postprocess/filters.h" #include "postprocess/filters.h"
#include "hgl_context.h" #include "hgl_context.h"
#include "sw/hgl/hgl_sw_winsys.h"
#include "bitmap_wrapper.h"
class BBitmap;
class GalliumContext { class GalliumContext {
public: public:
@ -29,23 +29,25 @@ public:
void Lock(); void Lock();
void Unlock(); void Unlock();
context_id CreateContext(Bitmap* bitmap); context_id CreateContext(HGLWinsysContext *wsContext);
void DestroyContext(context_id contextID); void DestroyContext(context_id contextID);
context_id GetCurrentContext() { return fCurrentContext; }; context_id GetCurrentContext() { return fCurrentContext; };
status_t SetCurrentContext(Bitmap *bitmap, status_t SetCurrentContext(bool set, context_id contextID);
context_id contextID);
status_t SwapBuffers(context_id contextID); status_t SwapBuffers(context_id contextID);
void Draw(context_id contextID, BRect updateRect);
bool Validate(uint32 width, uint32 height); bool Validate(uint32 width, uint32 height);
void Invalidate(uint32 width, uint32 height); void Invalidate(uint32 width, uint32 height);
private: private:
status_t CreateScreen(); status_t CreateDisplay();
void DestroyDisplay();
void Flush(); void Flush();
ulong fOptions; ulong fOptions;
struct pipe_screen* fScreen; static int32 fDisplayRefCount;
static hgl_display* fDisplay;
// Context Management // Context Management
struct hgl_context* fContext[CONTEXT_MAX]; struct hgl_context* fContext[CONTEXT_MAX];

View File

@ -35,16 +35,99 @@ extern const char* color_space_name(color_space space);
extern "C" _EXPORT BGLRenderer* extern "C" _EXPORT BGLRenderer*
instantiate_gl_renderer(BGLView *view, ulong opts, BGLDispatcher *dispatcher) instantiate_gl_renderer(BGLView *view, ulong opts)
{ {
return new SoftwareRenderer(view, opts, dispatcher); return new SoftwareRenderer(view, opts);
} }
SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options, struct RasBuf32
BGLDispatcher* dispatcher) {
int32 width, height, stride;
int32 orgX, orgY;
int32 *colors;
RasBuf32(int32 width, int32 height, int32 stride, int32 orgX, int32 orgY, int32 *colors):
width(width), height(height), stride(stride), orgX(orgX), orgY(orgY), colors(colors)
{}
RasBuf32(BBitmap *bmp)
{
width = bmp->Bounds().IntegerWidth() + 1;
height = bmp->Bounds().IntegerHeight() + 1;
stride = bmp->BytesPerRow()/4;
orgX = 0;
orgY = 0;
colors = (int32*)bmp->Bits();
}
RasBuf32(direct_buffer_info *info)
{
width = 0x7fffffff;
height = 0x7fffffff;
stride = info->bytes_per_row/4;
orgX = 0;
orgY = 0;
colors = (int32*)info->bits;
}
void ClipSize(int32 x, int32 y, int32 w, int32 h)
{
if (x < 0) {w += x; x = 0;}
if (y < 0) {h += y; y = 0;}
if (x + w > width) {w = width - x;}
if (y + h > height) {h = height - y;}
if ((w > 0) && (h > 0)) {
colors += y*stride + x;
width = w;
height = h;
} else {
width = 0; height = 0; colors = NULL;
}
if (x + orgX > 0) {orgX += x;} else {orgX = 0;}
if (y + orgY > 0) {orgY += y;} else {orgY = 0;}
}
void ClipRect(int32 l, int32 t, int32 r, int32 b)
{
ClipSize(l, t, r - l, b - t);
}
void Shift(int32 dx, int32 dy)
{
orgX += dx;
orgY += dy;
}
void Clear(int32 color)
{
RasBuf32 dst = *this;
dst.stride -= dst.width;
for (; dst.height > 0; dst.height--) {
for (int32 i = dst.width; i > 0; i--)
*dst.colors++ = color;
dst.colors += dst.stride;
}
}
void Blit(RasBuf32 src)
{
RasBuf32 dst = *this;
int32 x, y;
x = src.orgX - orgX;
y = src.orgY - orgY;
dst.ClipSize(x, y, src.width, src.height);
src.ClipSize(-x, -y, width, height);
for (; dst.height > 0; dst.height--) {
memcpy(dst.colors, src.colors, 4*dst.width);
dst.colors += dst.stride;
src.colors += src.stride;
}
}
};
SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options)
: :
BGLRenderer(view, options, dispatcher), BGLRenderer(view, options),
fBitmap(NULL),
fDirectModeEnabled(false), fDirectModeEnabled(false),
fInfo(NULL), fInfo(NULL),
fInfoLocker("info locker"), fInfoLocker("info locker"),
@ -53,9 +136,6 @@ SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options,
{ {
CALLED(); CALLED();
// Disable double buffer for the moment.
//options &= ~BGL_DOUBLE;
// Initialize the "Haiku Software GL Pipe" // Initialize the "Haiku Software GL Pipe"
time_t beg; time_t beg;
time_t end; time_t end;
@ -65,7 +145,6 @@ SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options,
TRACE("Haiku Software GL Pipe initialization time: %f.\n", TRACE("Haiku Software GL Pipe initialization time: %f.\n",
difftime(end, beg)); difftime(end, beg));
// Allocate a bitmap
BRect b = view->Bounds(); BRect b = view->Bounds();
fColorSpace = BScreen(view->Window()).ColorSpace(); fColorSpace = BScreen(view->Window()).ColorSpace();
TRACE("%s: Colorspace:\t%s\n", __func__, color_space_name(fColorSpace)); TRACE("%s: Colorspace:\t%s\n", __func__, color_space_name(fColorSpace));
@ -73,11 +152,9 @@ SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options,
fWidth = (GLint)b.IntegerWidth(); fWidth = (GLint)b.IntegerWidth();
fHeight = (GLint)b.IntegerHeight(); fHeight = (GLint)b.IntegerHeight();
_AllocateBitmap();
// Initialize the first "Haiku Software GL Pipe" context // Initialize the first "Haiku Software GL Pipe" context
beg = time(NULL); beg = time(NULL);
fContextID = fContextObj->CreateContext(fBitmap); fContextID = fContextObj->CreateContext(this);
end = time(NULL); end = time(NULL);
if (fContextID < 0) if (fContextID < 0)
@ -98,8 +175,6 @@ SoftwareRenderer::~SoftwareRenderer()
if (fContextObj) if (fContextObj)
delete fContextObj; delete fContextObj;
if (fBitmap)
delete fBitmap;
} }
@ -111,21 +186,19 @@ SoftwareRenderer::LockGL()
color_space cs = BScreen(GLView()->Window()).ColorSpace(); color_space cs = BScreen(GLView()->Window()).ColorSpace();
{
BAutolock lock(fInfoLocker); BAutolock lock(fInfoLocker);
if (fDirectModeEnabled && fInfo != NULL) { if (fDirectModeEnabled && fInfo != NULL) {
fWidth = fInfo->window_bounds.right - fInfo->window_bounds.left; fWidth = fInfo->window_bounds.right - fInfo->window_bounds.left;
fHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top; fHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top;
} }
if (fBitmap && cs == fColorSpace && fContextObj->Validate(fWidth, fHeight)) { fContextObj->Validate(fWidth, fHeight);
fContextObj->SetCurrentContext(fBitmap, fContextID); fColorSpace = cs;
return;
} }
fColorSpace = cs; // do not hold fInfoLocker here to avoid deadlock
fContextObj->SetCurrentContext(true, fContextID);
_AllocateBitmap();
fContextObj->SetCurrentContext(fBitmap, fContextID);
} }
@ -136,76 +209,54 @@ SoftwareRenderer::UnlockGL()
if ((fOptions & BGL_DOUBLE) == 0) { if ((fOptions & BGL_DOUBLE) == 0) {
SwapBuffers(); SwapBuffers();
} }
fContextObj->SetCurrentContext(NULL, fContextID); fContextObj->SetCurrentContext(false, fContextID);
BGLRenderer::UnlockGL(); BGLRenderer::UnlockGL();
} }
void
SoftwareRenderer::Display(BBitmap *bitmap, BRect *updateRect)
{
// CALLED();
if (!fDirectModeEnabled) {
// TODO: avoid timeout
if (GLView()->LockLooperWithTimeout(1000) == B_OK) {
GLView()->DrawBitmap(bitmap, B_ORIGIN);
GLView()->UnlockLooper();
}
} else {
BAutolock lock(fInfoLocker);
if (fInfo != NULL) {
RasBuf32 srcBuf(bitmap);
RasBuf32 dstBuf(fInfo);
for (uint32 i = 0; i < fInfo->clip_list_count; i++) {
clipping_rect *clip = &fInfo->clip_list[i];
RasBuf32 dstClip = dstBuf;
dstClip.ClipRect(clip->left, clip->top, clip->right + 1, clip->bottom + 1);
dstClip.Shift(-fInfo->window_bounds.left, -fInfo->window_bounds.top);
dstClip.Blit(srcBuf);
}
}
}
}
void void
SoftwareRenderer::SwapBuffers(bool vsync) SoftwareRenderer::SwapBuffers(bool vsync)
{ {
// CALLED();
if (!fBitmap)
return;
BScreen screen(GLView()->Window()); BScreen screen(GLView()->Window());
fContextObj->SwapBuffers(fContextID); fContextObj->SwapBuffers(fContextID);
fContextObj->Validate(fWidth, fHeight);
BAutolock lock(fInfoLocker);
if (!fDirectModeEnabled || fInfo == NULL) {
if (GLView()->LockLooperWithTimeout(1000) == B_OK) {
GLView()->DrawBitmap(fBitmap, B_ORIGIN);
GLView()->UnlockLooper();
if (vsync)
screen.WaitForRetrace();
}
return;
}
// check the bitmap size still matches the size
if (fInfo->window_bounds.bottom - fInfo->window_bounds.top
!= fBitmap->Bounds().IntegerHeight()
|| fInfo->window_bounds.right - fInfo->window_bounds.left
!= fBitmap->Bounds().IntegerWidth()) {
ERROR("%s: Bitmap size doesn't match size!\n", __func__);
return;
}
uint32 bytesPerRow = fBitmap->BytesPerRow();
uint8 bytesPerPixel = bytesPerRow / fBitmap->Bounds().IntegerWidth();
for (uint32 i = 0; i < fInfo->clip_list_count; i++) {
clipping_rect *clip = &fInfo->clip_list[i];
int32 height = clip->bottom - clip->top + 1;
int32 bytesWidth
= (clip->right - clip->left + 1) * bytesPerPixel;
bytesWidth -= bytesPerPixel;
uint8 *p = (uint8 *)fInfo->bits + clip->top
* fInfo->bytes_per_row + clip->left * bytesPerPixel;
uint8 *b = (uint8 *)fBitmap->Bits()
+ (clip->top - fInfo->window_bounds.top) * bytesPerRow
+ (clip->left - fInfo->window_bounds.left) * bytesPerPixel;
for (int y = 0; y < height - 1; y++) {
memcpy(p, b, bytesWidth);
p += fInfo->bytes_per_row;
b += bytesPerRow;
}
}
if (vsync) if (vsync)
screen.WaitForRetrace(); screen.WaitForRetrace();
} }
void void
SoftwareRenderer::Draw(BRect updateRect) SoftwareRenderer::Draw(BRect updateRect)
{ {
// CALLED(); // CALLED();
if ((!fDirectModeEnabled || fInfo == NULL) && fBitmap) fContextObj->Draw(fContextID, updateRect);
GLView()->DrawBitmap(fBitmap, updateRect, updateRect);
} }
@ -213,41 +264,9 @@ status_t
SoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap *bitmap) SoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap *bitmap)
{ {
CALLED(); CALLED();
color_space scs = fBitmap->ColorSpace();
color_space dcs = bitmap->ColorSpace();
if (scs != dcs && (scs != B_RGBA32 || dcs != B_RGB32)) { // TODO: implement
ERROR("%s::CopyPixelsOut(): incompatible color space: %s != %s\n", return B_ERROR;
__PRETTY_FUNCTION__, color_space_name(scs), color_space_name(dcs));
return B_BAD_TYPE;
}
BRect sr = fBitmap->Bounds();
BRect dr = bitmap->Bounds();
// int32 w1 = sr.IntegerWidth();
// int32 h1 = sr.IntegerHeight();
// int32 w2 = dr.IntegerWidth();
// int32 h2 = dr.IntegerHeight();
sr = sr & dr.OffsetBySelf(location);
dr = sr.OffsetByCopy(-location.x, -location.y);
uint8 *ps = (uint8 *) fBitmap->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 * fBitmap->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;
} }
@ -256,40 +275,8 @@ SoftwareRenderer::CopyPixelsIn(BBitmap *bitmap, BPoint location)
{ {
CALLED(); CALLED();
color_space sourceCS = bitmap->ColorSpace(); // TODO: implement
color_space destinationCS = fBitmap->ColorSpace(); return B_ERROR;
if (sourceCS != destinationCS
&& (sourceCS != B_RGB32 || destinationCS != B_RGBA32)) {
ERROR("%s::CopyPixelsIn(): incompatible color space: %s != %s\n",
__PRETTY_FUNCTION__, color_space_name(sourceCS),
color_space_name(destinationCS));
return B_BAD_TYPE;
}
BRect sr = bitmap->Bounds();
BRect dr = fBitmap->Bounds();
sr = sr & dr.OffsetBySelf(location);
dr = sr.OffsetByCopy(-location.x, -location.y);
uint8 *ps = (uint8 *) bitmap->Bits();
uint8 *pd = (uint8 *) fBitmap->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))
* fBitmap->BytesPerRow());
d += (uint32) dr.left;
memcpy(d, s, dr.IntegerWidth() * 4);
}
return B_OK;
} }
@ -327,36 +314,3 @@ SoftwareRenderer::FrameResized(float width, float height)
fWidth = (GLuint)width; fWidth = (GLuint)width;
fHeight = (GLuint)height; fHeight = (GLuint)height;
} }
void
SoftwareRenderer::_AllocateBitmap()
{
// CALLED();
// allocate new size of back buffer bitmap
BAutolock lock(fInfoLocker);
if (fBitmap)
delete fBitmap;
if (fWidth < 1 || fHeight < 1) {
TRACE("%s: Can't allocate bitmap of %dx%d\n", __func__,
fWidth, fHeight);
return;
}
BRect rect(0.0, 0.0, fWidth, fHeight);
fBitmap = new (std::nothrow) BBitmap(rect, fColorSpace);
if (fBitmap == NULL) {
TRACE("%s: Can't create bitmap!\n", __func__);
return;
}
TRACE("%s: New bitmap size: %" B_PRId32 " x %" B_PRId32 "\n", __func__,
fBitmap->Bounds().IntegerWidth(), fBitmap->Bounds().IntegerHeight());
#if 0
// debug..
void *data = fBitmap->Bits();
memset(data, 0xcc, fBitmap->BitsLength());
#endif
}

View File

@ -18,31 +18,28 @@
#include "GalliumContext.h" #include "GalliumContext.h"
class SoftwareRenderer : public BGLRenderer { class SoftwareRenderer : public BGLRenderer, public HGLWinsysContext {
public: public:
SoftwareRenderer(BGLView *view, SoftwareRenderer(BGLView *view,
ulong bgl_options, ulong bgl_options);
BGLDispatcher *dispatcher);
virtual ~SoftwareRenderer(); virtual ~SoftwareRenderer();
virtual void LockGL(); void LockGL();
virtual void UnlockGL(); void UnlockGL();
virtual void SwapBuffers(bool vsync = false); void Display(BBitmap* bitmap, BRect* updateRect);
virtual void Draw(BRect updateRect);
virtual status_t CopyPixelsOut(BPoint source, BBitmap *dest);
virtual status_t CopyPixelsIn(BBitmap *source, BPoint dest);
virtual void FrameResized(float width, float height);
virtual void EnableDirectMode(bool enabled); void SwapBuffers(bool vsync = false);
virtual void DirectConnected(direct_buffer_info *info); void Draw(BRect updateRect);
status_t CopyPixelsOut(BPoint source, BBitmap *dest);
status_t CopyPixelsIn(BBitmap *source, BPoint dest);
void FrameResized(float width, float height);
void EnableDirectMode(bool enabled);
void DirectConnected(direct_buffer_info *info);
private: private:
void _AllocateBitmap();
GalliumContext* fContextObj; GalliumContext* fContextObj;
BBitmap* fBitmap;
context_id fContextID; context_id fContextID;
bool fDirectModeEnabled; bool fDirectModeEnabled;

View File

@ -37,9 +37,10 @@
#include "frontend/api.h" #include "frontend/api.h"
#include "frontend/sw_winsys.h" #include "frontend/sw_winsys.h"
#include "bitmap_wrapper.h"
#include "hgl_sw_winsys.h" #include "hgl_sw_winsys.h"
#include <Bitmap.h>
#include <OS.h>
#ifdef DEBUG #ifdef DEBUG
# define TRACE(x...) printf("hgl:winsys: " x) # define TRACE(x...) printf("hgl:winsys: " x)
@ -63,6 +64,7 @@ struct haiku_displaytarget
unsigned size; unsigned size;
void* data; void* data;
BBitmap* bitmap;
}; };
@ -126,10 +128,18 @@ hgl_winsys_displaytarget_create(struct sw_winsys* winsys,
haikuDisplayTarget->stride = align(formatStride, alignment); haikuDisplayTarget->stride = align(formatStride, alignment);
haikuDisplayTarget->size = haikuDisplayTarget->stride * blockSize; haikuDisplayTarget->size = haikuDisplayTarget->stride * blockSize;
if (textureUsage & PIPE_BIND_DISPLAY_TARGET) {
haikuDisplayTarget->data = NULL;
haikuDisplayTarget->bitmap = new BBitmap(
BRect(0, 0, width - 1, height - 1),
haikuDisplayTarget->colorSpace,
haikuDisplayTarget->stride);
} else {
haikuDisplayTarget->data haikuDisplayTarget->data
= align_malloc(haikuDisplayTarget->size, alignment); = align_malloc(haikuDisplayTarget->size, alignment);
assert(haikuDisplayTarget->data); haikuDisplayTarget->bitmap = NULL;
}
*stride = haikuDisplayTarget->stride; *stride = haikuDisplayTarget->stride;
@ -151,6 +161,9 @@ hgl_winsys_displaytarget_destroy(struct sw_winsys* winsys,
if (haikuDisplayTarget->data != NULL) if (haikuDisplayTarget->data != NULL)
align_free(haikuDisplayTarget->data); align_free(haikuDisplayTarget->data);
if (haikuDisplayTarget->bitmap != NULL)
delete haikuDisplayTarget->bitmap;
FREE(haikuDisplayTarget); FREE(haikuDisplayTarget);
} }
@ -179,13 +192,16 @@ hgl_winsys_displaytarget_map(struct sw_winsys* winsys,
struct haiku_displaytarget* haikuDisplayTarget struct haiku_displaytarget* haikuDisplayTarget
= hgl_sw_displaytarget(displayTarget); = hgl_sw_displaytarget(displayTarget);
if (haikuDisplayTarget->bitmap != NULL)
return haikuDisplayTarget->bitmap->Bits();
return haikuDisplayTarget->data; return haikuDisplayTarget->data;
} }
static void static void
hgl_winsys_displaytarget_unmap(struct sw_winsys* winsys, hgl_winsys_displaytarget_unmap(struct sw_winsys* winsys,
struct sw_displaytarget* disptarget) struct sw_displaytarget* displayTarget)
{ {
return; return;
} }
@ -198,19 +214,11 @@ hgl_winsys_displaytarget_display(struct sw_winsys* winsys,
{ {
assert(contextPrivate); assert(contextPrivate);
Bitmap* bitmap = (Bitmap*)contextPrivate;
struct haiku_displaytarget* haikuDisplayTarget struct haiku_displaytarget* haikuDisplayTarget
= hgl_sw_displaytarget(displayTarget); = hgl_sw_displaytarget(displayTarget);
import_bitmap_bits(bitmap, haikuDisplayTarget->data, HGLWinsysContext *context = (HGLWinsysContext*)contextPrivate;
haikuDisplayTarget->size, haikuDisplayTarget->stride, context->Display(haikuDisplayTarget->bitmap, NULL);
haikuDisplayTarget->colorSpace);
// Dump the rendered bitmap to disk for debugging
//dump_bitmap(bitmap);
return;
} }

View File

@ -27,6 +27,16 @@
#ifndef _HGL_SOFTWAREWINSYS_H #ifndef _HGL_SOFTWAREWINSYS_H
#define _HGL_SOFTWAREWINSYS_H #define _HGL_SOFTWAREWINSYS_H
#ifdef __cplusplus
class BBitmap;
class BRect;
class HGLWinsysContext {
public:
virtual void Display(BBitmap *bitmap, BRect *updateRect) = 0;
};
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@ -20,7 +20,7 @@
libswhgl = static_library( libswhgl = static_library(
'swhgl', 'swhgl',
files('hgl_sw_winsys.c'), files('hgl_sw_winsys.cpp'),
gnu_symbol_visibility : 'hidden', gnu_symbol_visibility : 'hidden',
include_directories : [inc_gallium, inc_include, inc_src, inc_gallium_aux, include_directories : [inc_gallium, inc_include, inc_src, inc_gallium_aux,
include_directories('../../../frontends/hgl') include_directories('../../../frontends/hgl')

View File

@ -1,65 +0,0 @@
/*
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000-2015 Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Brian Paul <brian.e.paul@gmail.com>
* Philippe Houdoin <philippe.houdoin@free.fr>
* Alexander von Gluck IV <kallisti5@unixzen.com>
*/
#include "glapi/glapi.h"
#include "glapi/glapi_priv.h"
extern "C" {
/*
* NOTE: this file portion implements C-based dispatch of the OpenGL entrypoints
* (glAccum, glBegin, etc).
* This code IS NOT USED if we're compiling on an x86 system and using
* the glapi_x86.S assembly code.
*/
#if !(defined(USE_X86_ASM) || defined(USE_SPARC_ASM))
#define KEYWORD1 PUBLIC
#define KEYWORD2
#define NAME(func) gl##func
#define DISPATCH(func, args, msg) \
const struct _glapi_table* dispatch; \
dispatch = _glapi_Dispatch ? _glapi_Dispatch : _glapi_get_dispatch();\
(dispatch->func) args
#define RETURN_DISPATCH(func, args, msg) \
const struct _glapi_table* dispatch; \
dispatch = _glapi_Dispatch ? _glapi_Dispatch : _glapi_get_dispatch();\
return (dispatch->func) args
#endif
}
/* NOTE: this file portion implement a thin OpenGL entrypoints dispatching
C++ wrapper class
*/
#include "GLDispatcher.h"
BGLDispatcher::BGLDispatcher()
{
}
BGLDispatcher::~BGLDispatcher()
{
}
status_t
BGLDispatcher::SetTable(struct _glapi_table* table)
{
_glapi_set_dispatch(table);
return B_OK;
}

View File

@ -1,105 +0,0 @@
/*
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000-2015 Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Brian Paul <brian.e.paul@gmail.com>
* Philippe Houdoin <philippe.houdoin@free.fr>
*/
#ifndef GLDISPATCHER_H
#define GLDISPATCHER_H
#include <BeBuild.h>
#include <GL/gl.h>
#include <SupportDefs.h>
#include "main/glheader.h"
#include "glapi/glapi.h"
class BGLDispatcher
{
// Private unimplemented copy constructors
BGLDispatcher(const BGLDispatcher &);
BGLDispatcher & operator=(const BGLDispatcher &);
public:
BGLDispatcher();
~BGLDispatcher();
void SetCurrentContext(void* context);
void* CurrentContext();
struct _glapi_table* Table();
status_t SetTable(struct _glapi_table* dispatch);
uint32 TableSize();
const _glapi_proc operator[](const char* functionName);
const char* operator[](uint32 offset);
const _glapi_proc AddressOf(const char* functionName);
uint32 OffsetOf(const char* functionName);
};
// Inlines methods
inline void
BGLDispatcher::SetCurrentContext(void* context)
{
_glapi_set_context(context);
}
inline void*
BGLDispatcher::CurrentContext()
{
return _glapi_get_context();
}
inline struct _glapi_table*
BGLDispatcher::Table()
{
return _glapi_get_dispatch();
}
inline uint32
BGLDispatcher::TableSize()
{
return _glapi_get_dispatch_table_size();
}
inline const _glapi_proc
BGLDispatcher::operator[](const char* functionName)
{
return _glapi_get_proc_address(functionName);
}
inline const char*
BGLDispatcher::operator[](uint32 offset)
{
return _glapi_get_proc_name((GLuint) offset);
}
inline const _glapi_proc
BGLDispatcher::AddressOf(const char* functionName)
{
return _glapi_get_proc_address(functionName);
}
inline uint32
BGLDispatcher::OffsetOf(const char* functionName)
{
return (uint32) _glapi_get_proc_offset(functionName);
}
#endif // GLDISPATCHER_H

View File

@ -8,23 +8,18 @@
#include "GLRenderer.h" #include "GLRenderer.h"
#include "GLDispatcher.h"
BGLRenderer::BGLRenderer(BGLView* view, ulong glOptions)
BGLRenderer::BGLRenderer(BGLView* view, ulong glOptions,
BGLDispatcher* dispatcher)
: :
fRefCount(1), fRefCount(1),
fView(view), fView(view),
fOptions(glOptions), fOptions(glOptions)
fDispatcher(dispatcher)
{ {
} }
BGLRenderer::~BGLRenderer() BGLRenderer::~BGLRenderer()
{ {
delete fDispatcher;
} }
@ -38,7 +33,7 @@ BGLRenderer::Acquire()
void void
BGLRenderer::Release() BGLRenderer::Release()
{ {
if (atomic_add(&fRefCount, -1) < 1) if (atomic_add(&fRefCount, -1) <= 1)
delete this; delete this;
} }

View File

@ -12,28 +12,34 @@
#include <image.h> #include <image.h>
#include <kernel/image.h> #include <kernel/image.h>
#include <system/safemode_defs.h> #include <private/system/safemode_defs.h>
#include <Directory.h> #include <Directory.h>
#include <FindDirectory.h> #include <FindDirectory.h>
#include <Path.h> #include <Path.h>
#include <strings.h> #include <strings.h>
#include "GLDispatcher.h"
#include "GLRendererRoster.h" #include "GLRendererRoster.h"
#include <new> #include <new>
#include <string.h> #include <string.h>
#include <stdio.h>
extern "C" status_t _kern_get_safemode_option(const char* parameter, extern "C" status_t _kern_get_safemode_option(const char* parameter,
char* buffer, size_t* _bufferSize); char* buffer, size_t* _bufferSize);
GLRendererRoster *GLRendererRoster::fInstance = NULL;
GLRendererRoster::GLRendererRoster(BGLView* view, ulong options) GLRendererRoster *GLRendererRoster::Roster()
{
if (fInstance == NULL) {
fInstance = new GLRendererRoster();
}
return fInstance;
}
GLRendererRoster::GLRendererRoster()
: :
fNextID(0),
fView(view),
fOptions(options),
fSafeMode(false), fSafeMode(false),
fABISubDirectory(NULL) fABISubDirectory(NULL)
{ {
@ -84,14 +90,19 @@ GLRendererRoster::~GLRendererRoster()
BGLRenderer* BGLRenderer*
GLRendererRoster::GetRenderer(int32 id) GLRendererRoster::GetRenderer(BGLView *view, ulong options)
{ {
RendererMap::const_iterator iterator = fRenderers.find(id); for (
if (iterator == fRenderers.end()) RendererMap::const_iterator iterator = fRenderers.begin();
iterator != fRenderers.end();
iterator++
) {
renderer_item item = *iterator;
BGLRenderer* renderer;
renderer = item.entry(view, options);
return renderer;
}
return NULL; return NULL;
struct renderer_item item = iterator->second;
return item.renderer;
} }
@ -102,6 +113,7 @@ GLRendererRoster::AddDefaultPaths()
const directory_which paths[] = { const directory_which paths[] = {
B_USER_NONPACKAGED_ADDONS_DIRECTORY, B_USER_NONPACKAGED_ADDONS_DIRECTORY,
B_USER_ADDONS_DIRECTORY, B_USER_ADDONS_DIRECTORY,
B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
B_SYSTEM_ADDONS_DIRECTORY, B_SYSTEM_ADDONS_DIRECTORY,
}; };
@ -162,24 +174,22 @@ GLRendererRoster::AddPath(const char* path)
status_t status_t
GLRendererRoster::AddRenderer(BGLRenderer* renderer, GLRendererRoster::AddRenderer(InstantiateRenderer entry,
image_id image, const entry_ref* ref, ino_t node) image_id image, const entry_ref* ref, ino_t node)
{ {
renderer_item item; renderer_item item;
item.renderer = renderer; item.entry = entry;
item.image = image; item.image = image;
item.node = node; item.node = node;
if (ref != NULL) if (ref != NULL)
item.ref = *ref; item.ref = *ref;
try { try {
fRenderers[fNextID] = item; fRenderers.push_back(item);
} catch (...) { } catch (...) {
return B_NO_MEMORY; return B_NO_MEMORY;
} }
renderer->fOwningRoster = this;
renderer->fID = fNextID++;
return B_OK; return B_OK;
} }
@ -194,30 +204,29 @@ GLRendererRoster::CreateRenderer(const entry_ref& ref)
return status; return status;
BPath path(&ref); BPath path(&ref);
printf("OpenGL load add-on: %s\n", path.Path());
image_id image = load_add_on(path.Path()); image_id image = load_add_on(path.Path());
if (image < B_OK) if (image < B_OK)
return image; return image;
BGLRenderer* (*instantiate_renderer) InstantiateRenderer instantiate_renderer;
(BGLView* view, ulong options, BGLDispatcher* dispatcher);
status = get_image_symbol(
image, "instantiate_gl_renderer",
B_SYMBOL_TYPE_TEXT, (void**)&instantiate_renderer
);
status = get_image_symbol(image, "instantiate_gl_renderer",
B_SYMBOL_TYPE_TEXT, (void**)&instantiate_renderer);
if (status == B_OK) { if (status == B_OK) {
BGLRenderer* renderer if ((status = AddRenderer(instantiate_renderer, image, &ref, nodeRef.node)) != B_OK) {
= instantiate_renderer(fView, fOptions, new BGLDispatcher());
if (!renderer) {
unload_add_on(image);
return B_UNSUPPORTED;
}
if (AddRenderer(renderer, image, &ref, nodeRef.node) != B_OK) {
renderer->Release();
// this will delete the renderer
unload_add_on(image); unload_add_on(image);
return status;
} }
printf("OpenGL add-on registered: %s\n", path.Path());
return B_OK; return B_OK;
} }
printf("OpenGL add-on failed to instantiate: %s\n", path.Path());
unload_add_on(image); unload_add_on(image);
return status; return status;

View File

@ -9,42 +9,43 @@
#define _GLRENDERER_ROSTER_H #define _GLRENDERER_ROSTER_H
#include "GLRenderer.h" #include <GLRenderer.h>
#include <map> #include <vector>
typedef BGLRenderer* (*InstantiateRenderer) (BGLView* view, ulong options);
struct renderer_item { struct renderer_item {
BGLRenderer* renderer; InstantiateRenderer entry;
entry_ref ref; entry_ref ref;
ino_t node; ino_t node;
image_id image; image_id image;
}; };
typedef std::map<renderer_id, renderer_item> RendererMap; typedef std::vector<renderer_item> RendererMap;
class GLRendererRoster { class GLRendererRoster {
public: public:
GLRendererRoster(BGLView* view, ulong options); static GLRendererRoster *Roster();
virtual ~GLRendererRoster(); BGLRenderer* GetRenderer(BGLView *view, ulong options);
BGLRenderer* GetRenderer(int32 id = 0);
private: private:
GLRendererRoster();
virtual ~GLRendererRoster();
void AddDefaultPaths(); void AddDefaultPaths();
status_t AddPath(const char* path); status_t AddPath(const char* path);
status_t AddRenderer(BGLRenderer* renderer, status_t AddRenderer(InstantiateRenderer entry, image_id image,
image_id image, const entry_ref* ref, ino_t node); const entry_ref* ref, ino_t node);
status_t CreateRenderer(const entry_ref& ref); status_t CreateRenderer(const entry_ref& ref);
RendererMap fRenderers; static GLRendererRoster* fInstance;
int32 fNextID;
BGLView* fView;
ulong fOptions;
bool fSafeMode; bool fSafeMode;
const char* fABISubDirectory; const char* fABISubDirectory;
RendererMap fRenderers;
}; };

View File

@ -20,10 +20,10 @@
#include <DirectWindow.h> #include <DirectWindow.h>
#include "GLRenderer.h" #include "GLRenderer.h"
#include "interface/DirectWindowPrivate.h" #include <private/interface/DirectWindowPrivate.h>
#include "GLDispatcher.h"
#include "GLRendererRoster.h" #include "GLRendererRoster.h"
#include "glapi/glapi.h"
struct glview_direct_info { struct glview_direct_info {
direct_buffer_info* direct_info; direct_buffer_info* direct_info;
@ -39,7 +39,6 @@ BGLView::BGLView(BRect rect, const char* name, ulong resizingMode, ulong mode,
ulong options) ulong options)
: :
BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS), BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS),
// | B_FULL_UPDATE_ON_RESIZE)
fGc(NULL), fGc(NULL),
fOptions(options), fOptions(options),
fDitherCount(0), fDitherCount(0),
@ -47,11 +46,9 @@ BGLView::BGLView(BRect rect, const char* name, ulong resizingMode, ulong mode,
fDisplayLock("BGLView display lock"), fDisplayLock("BGLView display lock"),
fClipInfo(NULL), fClipInfo(NULL),
fRenderer(NULL), fRenderer(NULL),
fRoster(NULL),
fDitherMap(NULL) fDitherMap(NULL)
{ {
fRoster = new GLRendererRoster(this, options); fRenderer = GLRendererRoster::Roster()->GetRenderer(this, options);
fRenderer = fRoster->GetRenderer();
} }
@ -77,6 +74,15 @@ BGLView::LockGL()
void void
BGLView::UnlockGL() BGLView::UnlockGL()
{ {
thread_id lockerThread = fDisplayLock.LockingThread();
thread_id callerThread = find_thread(NULL);
if (lockerThread != B_ERROR && lockerThread != callerThread) {
printf("UnlockGL is called from wrong thread, lockerThread: %d, callerThread: %d\n",
(int)lockerThread, (int)callerThread);
debugger("[!]");
}
if (fRenderer != NULL && fDisplayLock.CountLocks() == 1) if (fRenderer != NULL && fDisplayLock.CountLocks() == 1)
fRenderer->UnlockGL(); fRenderer->UnlockGL();
fDisplayLock.Unlock(); fDisplayLock.Unlock();
@ -113,15 +119,7 @@ BGLView::EmbeddedView()
void* void*
BGLView::GetGLProcAddress(const char* procName) BGLView::GetGLProcAddress(const char* procName)
{ {
BGLDispatcher* glDispatcher = NULL; return (void*)_glapi_get_proc_address(procName);
if (fRenderer)
glDispatcher = fRenderer->GLDispatcher();
if (glDispatcher)
return (void*)glDispatcher->AddressOf(procName);
return NULL;
} }
@ -170,9 +168,8 @@ void
BGLView::Draw(BRect updateRect) BGLView::Draw(BRect updateRect)
{ {
if (fRenderer) { if (fRenderer) {
_LockDraw(); if (!fClipInfo || !fClipInfo->enable_direct_mode)
fRenderer->Draw(updateRect); fRenderer->Draw(updateRect);
_UnlockDraw();
return; return;
} }
// TODO: auto-size and center the string // TODO: auto-size and center the string
@ -237,10 +234,6 @@ BGLView::AllAttached()
void void
BGLView::DetachedFromWindow() BGLView::DetachedFromWindow()
{ {
if (fRenderer)
fRenderer->Release();
fRenderer = NULL;
BView::DetachedFromWindow(); BView::DetachedFromWindow();
} }
@ -260,12 +253,9 @@ BGLView::FrameResized(float width, float height)
v->ConvertToParent(&fBounds); v->ConvertToParent(&fBounds);
if (fRenderer) { if (fRenderer) {
LockGL(); //_LockDraw();
_LockDraw();
_CallDirectConnected();
fRenderer->FrameResized(width, height); fRenderer->FrameResized(width, height);
_UnlockDraw(); //_UnlockDraw();
UnlockGL();
} }
BView::FrameResized(width, height); BView::FrameResized(width, height);
@ -342,6 +332,7 @@ BGLView::GetSupportedSuites(BMessage* data)
void void
BGLView::DirectConnected(direct_buffer_info* info) BGLView::DirectConnected(direct_buffer_info* info)
{ {
printf("BGLView::DirectConnected\n");
if (fClipInfo == NULL) { if (fClipInfo == NULL) {
fClipInfo = new (std::nothrow) glview_direct_info(); fClipInfo = new (std::nothrow) glview_direct_info();
if (fClipInfo == NULL) if (fClipInfo == NULL)
@ -350,33 +341,33 @@ BGLView::DirectConnected(direct_buffer_info* info)
direct_buffer_info* localInfo = fClipInfo->direct_info; direct_buffer_info* localInfo = fClipInfo->direct_info;
_LockDraw();
switch (info->buffer_state & B_DIRECT_MODE_MASK) { switch (info->buffer_state & B_DIRECT_MODE_MASK) {
case B_DIRECT_START: case B_DIRECT_START:
fClipInfo->direct_connected = true; fClipInfo->direct_connected = true;
memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE); memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
_UnlockDraw();
break; break;
case B_DIRECT_MODIFY: case B_DIRECT_MODIFY:
_LockDraw();
memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE); memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
_UnlockDraw();
break; break;
case B_DIRECT_STOP: case B_DIRECT_STOP:
fClipInfo->direct_connected = false; fClipInfo->direct_connected = false;
_LockDraw();
break; break;
} }
if (fRenderer) if (fRenderer)
_CallDirectConnected(); _CallDirectConnected();
_UnlockDraw();
} }
void void
BGLView::EnableDirectMode(bool enabled) BGLView::EnableDirectMode(bool enabled)
{ {
printf("BGLView::EnableDirectMode: %d\n", (int)enabled);
if (fRenderer) if (fRenderer)
fRenderer->EnableDirectMode(enabled); fRenderer->EnableDirectMode(enabled);
if (fClipInfo == NULL) { if (fClipInfo == NULL) {
@ -412,8 +403,10 @@ BGLView::_UnlockDraw()
void void
BGLView::_CallDirectConnected() BGLView::_CallDirectConnected()
{ {
if (!fClipInfo) if (!fClipInfo || !fClipInfo->direct_connected) {
fRenderer->DirectConnected(NULL);
return; return;
}
direct_buffer_info* localInfo = fClipInfo->direct_info; direct_buffer_info* localInfo = fClipInfo->direct_info;
direct_buffer_info* info = (direct_buffer_info*)malloc( direct_buffer_info* info = (direct_buffer_info*)malloc(
@ -472,10 +465,9 @@ BGLView::BGLView(BRect rect, char* name, ulong resizingMode, ulong mode,
fDisplayLock("BGLView display lock"), fDisplayLock("BGLView display lock"),
fClipInfo(NULL), fClipInfo(NULL),
fRenderer(NULL), fRenderer(NULL),
fRoster(NULL),
fDitherMap(NULL) fDitherMap(NULL)
{ {
fRoster = new GLRendererRoster(this, options); fRenderer = GLRendererRoster::Roster()->GetRenderer(this, options);
} }

View File

@ -21,7 +21,7 @@
libgl = shared_library( libgl = shared_library(
'GL', 'GL',
files( files(
'GLView.cpp', 'GLRenderer.cpp', 'GLRendererRoster.cpp', 'GLDispatcher.cpp', 'GLView.cpp', 'GLRenderer.cpp', 'GLRendererRoster.cpp',
), ),
link_args : [ld_args_bsymbolic, ld_args_gc_sections], link_args : [ld_args_bsymbolic, ld_args_gc_sections],
include_directories : [ include_directories : [