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 &);
public:
BGLRenderer(BGLView *view, ulong bgl_options,
BGLDispatcher *dispatcher);
BGLRenderer(BGLView *view, ulong bgl_options);
virtual ~BGLRenderer();
void Acquire();
@ -50,7 +49,6 @@ public:
inline int32 ReferenceCount() const { return fRefCount; };
inline ulong Options() const { return fOptions; };
inline BGLView* GLView() { return fView; };
inline BGLDispatcher* GLDispatcher() { return fDispatcher; };
private:
friend class GLRendererRoster;
@ -64,13 +62,12 @@ private:
int32 fRefCount; // How much we're still useful
BGLView* fView; // Never forget who is the boss!
ulong fOptions; // Keep that tune in memory
BGLDispatcher* fDispatcher;// Our personal GL API call dispatcher
GLRendererRoster* fOwningRoster;
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

View File

@ -12,18 +12,19 @@
#include <GL/gl.h>
#define BGL_RGB 0
#define BGL_INDEX 1
#define BGL_SINGLE 0
#define BGL_DOUBLE 2
#define BGL_DIRECT 0
#define BGL_INDIRECT 4
#define BGL_ACCUM 8
#define BGL_ALPHA 16
#define BGL_DEPTH 32
#define BGL_OVERLAY 64
#define BGL_UNDERLAY 128
#define BGL_STENCIL 512
#define BGL_RGB 0
#define BGL_INDEX 1
#define BGL_SINGLE 0
#define BGL_DOUBLE 2
#define BGL_DIRECT 0
#define BGL_INDIRECT 4
#define BGL_ACCUM 8
#define BGL_ALPHA 16
#define BGL_DEPTH 32
#define BGL_OVERLAY 64
#define BGL_UNDERLAY 128
#define BGL_STENCIL 512
#define BGL_SHARE_CONTEXT 1024
#ifdef __cplusplus

View File

@ -57,24 +57,20 @@ hgl_st_framebuffer(struct st_framebuffer_iface *stfbi)
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)
{
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);
//buffer->surface
struct pipe_resource* ptex = buffer->textures[statt];
#if 0
struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
mtx_lock(&stwfb->fb->mutex);
if (!ptex)
return true;
struct pipe_resource* resource = textures[statt];
if (resource)
stw_framebuffer_present_locked(...);
#endif
// TODO: pipe_context here??? Might be needed for hw renderers
buffer->screen->flush_frontbuffer(buffer->screen, NULL, ptex, 0, 0,
buffer->winsysContext, NULL);
return true;
}
@ -93,6 +89,8 @@ hgl_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
buffer = hgl_st_framebuffer(stfbi);
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++)
pipe_resource_reference(&buffer->textures[i], NULL);
}
@ -109,31 +107,34 @@ hgl_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
enum pipe_format format;
unsigned bind;
switch (i) {
case ST_ATTACHMENT_FRONT_LEFT:
case ST_ATTACHMENT_BACK_LEFT:
case ST_ATTACHMENT_FRONT_RIGHT:
case ST_ATTACHMENT_BACK_RIGHT:
format = buffer->visual->color_format;
bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET;
break;
case ST_ATTACHMENT_DEPTH_STENCIL:
format = buffer->visual->depth_stencil_format;
bind = PIPE_BIND_DEPTH_STENCIL;
break;
default:
format = PIPE_FORMAT_NONE;
bind = 0;
break;
}
if (((1 << i) & buffer->visual->buffer_mask) && buffer->textures[i] == NULL) {
switch (i) {
case ST_ATTACHMENT_FRONT_LEFT:
case ST_ATTACHMENT_BACK_LEFT:
case ST_ATTACHMENT_FRONT_RIGHT:
case ST_ATTACHMENT_BACK_RIGHT:
format = buffer->visual->color_format;
bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET;
break;
case ST_ATTACHMENT_DEPTH_STENCIL:
format = buffer->visual->depth_stencil_format;
bind = PIPE_BIND_DEPTH_STENCIL;
break;
default:
format = PIPE_FORMAT_NONE;
bind = 0;
break;
}
if (format != PIPE_FORMAT_NONE) {
templat.format = format;
templat.bind = bind;
buffer->textures[i] = buffer->screen->resource_create(buffer->screen,
&templat);
if (!buffer->textures[i])
return FALSE;
if (format != PIPE_FORMAT_NONE) {
templat.format = format;
templat.bind = bind;
TRACE("resource_create(%d, %d, %d)\n", i, format, bind);
buffer->textures[i] = buffer->screen->resource_create(buffer->screen,
&templat);
if (!buffer->textures[i])
return FALSE;
}
}
}
@ -165,10 +166,6 @@ hgl_st_framebuffer_validate(struct st_context_iface *stctxi,
context = hgl_st_context(stctxi);
buffer = hgl_st_framebuffer(stfbi);
//int32 width = 0;
//int32 height = 0;
//get_bitmap_size(context->bitmap, &width, &height);
// Build mask of current attachments
stAttachmentMask = 0;
for (i = 0; i < count; i++)
@ -186,14 +183,9 @@ hgl_st_framebuffer_validate(struct st_context_iface *stctxi,
ret = hgl_st_framebuffer_validate_textures(stfbi,
context->width, context->height, stAttachmentMask);
if (!ret)
return ret;
// TODO: Simply update attachments
//if (!resized) {
//}
}
for (i = 0; i < count; i++)
@ -223,14 +215,14 @@ static uint32_t hgl_fb_ID = 0;
* Create new framebuffer
*/
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;
CALLED();
// Our requires before creating a framebuffer
assert(context);
assert(context->screen);
assert(context->display);
assert(context->stVisual);
buffer = CALLOC_STRUCT(hgl_buffer);
@ -242,9 +234,10 @@ hgl_create_st_framebuffer(struct hgl_context* context)
// Prepare our buffer
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;
else
buffer->target = PIPE_TEXTURE_RECT;
@ -257,12 +250,26 @@ hgl_create_st_framebuffer(struct hgl_context* context)
p_atomic_set(&buffer->stfbi->stamp, 1);
buffer->stfbi->st_manager_private = (void*)buffer;
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;
}
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*
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*
hgl_create_st_visual(ulong options)
{
@ -335,6 +310,7 @@ hgl_create_st_visual(ulong options)
visual->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
if ((options & BGL_DOUBLE) != 0) {
TRACE("double buffer enabled\n");
visual->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
visual->render_buffer = ST_ATTACHMENT_BACK_LEFT;
}
@ -364,3 +340,33 @@ hgl_destroy_st_visual(struct st_visual* 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
#define HGL_CONTEXT_H
#include "os/os_thread.h"
#include "pipe/p_format.h"
#include "pipe/p_compiler.h"
#include "pipe/p_screen.h"
#include "postprocess/filters.h"
#include "frontend/api.h"
#include "frontend/st_manager.h"
#include "os/os_thread.h"
#include "bitmap_wrapper.h"
@ -41,31 +39,29 @@ struct hgl_buffer
unsigned mask;
struct pipe_screen* screen;
struct pipe_surface* surface;
void* winsysContext;
enum pipe_texture_target target;
struct pipe_resource* textures[ST_ATTACHMENT_COUNT];
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 st_api* api;
// API
struct st_manager* manager;
// Manager
struct hgl_display* display;
struct st_context_iface* st;
// Interface Object
struct st_visual* stVisual;
// Visual
struct pipe_screen* screen;
//struct pipe_resource* textures[ST_ATTACHMENT_COUNT];
// Post processing
struct pp_queue_t* postProcess;
@ -75,13 +71,9 @@ struct hgl_context
unsigned width;
unsigned height;
Bitmap* bitmap;
color_space colorSpace;
mtx_t fbMutex;
struct hgl_buffer* draw;
struct hgl_buffer* read;
struct hgl_buffer* buffer;
};
// 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);
// 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
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);
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
}

View File

@ -11,6 +11,7 @@
#include "GalliumContext.h"
#include <stdio.h>
#include <algorithm>
#include "GLView.h"
@ -41,11 +42,12 @@
#endif
#define ERROR(x...) printf("GalliumContext: " x)
int32 GalliumContext::fDisplayRefCount = 0;
hgl_display* GalliumContext::fDisplay = NULL;
GalliumContext::GalliumContext(ulong options)
:
fOptions(options),
fScreen(NULL),
fCurrentContext(0)
{
CALLED();
@ -54,7 +56,7 @@ GalliumContext::GalliumContext(ulong options)
for (context_id i = 0; i < CONTEXT_MAX; i++)
fContext[i] = NULL;
CreateScreen();
CreateDisplay();
(void) mtx_init(&fMutex, mtx_plain);
}
@ -70,17 +72,20 @@ GalliumContext::~GalliumContext()
DestroyContext(i);
Unlock();
mtx_destroy(&fMutex);
DestroyDisplay();
// TODO: Destroy fScreen
mtx_destroy(&fMutex);
}
status_t
GalliumContext::CreateScreen()
GalliumContext::CreateDisplay()
{
CALLED();
if (atomic_add(&fDisplayRefCount, 1) > 0)
return B_OK;
// Allocate winsys and attach callback hooks
struct sw_winsys* winsys = hgl_create_sw_winsys();
@ -89,25 +94,47 @@ GalliumContext::CreateScreen()
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__);
FREE(winsys);
winsys->destroy(winsys);
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);
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;
}
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
GalliumContext::CreateContext(Bitmap *bitmap)
GalliumContext::CreateContext(HGLWinsysContext *wsContext)
{
CALLED();
@ -119,31 +146,15 @@ GalliumContext::CreateContext(Bitmap *bitmap)
}
// Set up the initial things our context needs
context->bitmap = bitmap;
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);
context->display = fDisplay;
// Create state tracker visual
context->stVisual = hgl_create_st_visual(fOptions);
// Create state tracker framebuffers
context->draw = hgl_create_st_framebuffer(context);
context->read = hgl_create_st_framebuffer(context);
context->buffer = hgl_create_st_framebuffer(context, wsContext);
if (!context->draw || !context->read) {
if (!context->buffer) {
ERROR("%s: Problem allocating framebuffer!\n", __func__);
FREE(context->stVisual);
return -1;
@ -159,10 +170,17 @@ GalliumContext::CreateContext(Bitmap *bitmap)
attribs.minor = 0;
//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
enum st_context_error result;
context->st = context->api->create_context(context->api, context->manager,
&attribs, &result, context->st);
context->st = fDisplay->api->create_context(fDisplay->api, fDisplay->manager,
&attribs, &result, shared);
if (!context->st) {
ERROR("%s: Couldn't create mesa state tracker context!\n",
@ -200,7 +218,7 @@ GalliumContext::CreateContext(Bitmap *bitmap)
context->st->st_manager_private = (void*)context;
struct st_context *stContext = (struct st_context*)context->st;
// Init Gallium3D Post Processing
// TODO: no pp filters are enabled yet through postProcessEnable
context->postProcess = pp_init(stContext->pipe, context->postProcessEnable,
@ -243,7 +261,7 @@ GalliumContext::DestroyContext(context_id contextID)
return;
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);
}
@ -251,23 +269,18 @@ GalliumContext::DestroyContext(context_id contextID)
pp_free(fContext[contextID]->postProcess);
// Delete state tracker framebuffer objects
if (fContext[contextID]->read)
delete fContext[contextID]->read;
if (fContext[contextID]->draw)
delete fContext[contextID]->draw;
if (fContext[contextID]->buffer)
hgl_destroy_st_framebuffer(fContext[contextID]->buffer);
if (fContext[contextID]->stVisual)
hgl_destroy_st_visual(fContext[contextID]->stVisual);
if (fContext[contextID]->manager)
hgl_destroy_st_manager(fContext[contextID]->manager);
FREE(fContext[contextID]);
}
status_t
GalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID)
GalliumContext::SetCurrentContext(bool set, context_id contextID)
{
CALLED();
@ -279,16 +292,17 @@ GalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID)
Lock();
context_id oldContextID = fCurrentContext;
struct hgl_context* context = fContext[contextID];
Unlock();
if (!context) {
ERROR("%s: Invalid context provided (#%" B_PRIu64 ")!\n",
__func__, contextID);
Unlock();
return B_ERROR;
}
if (!bitmap) {
context->api->make_current(context->api, NULL, NULL, NULL);
if (!set) {
fDisplay->api->make_current(fDisplay->api, NULL, NULL, NULL);
Unlock();
return B_OK;
}
@ -297,24 +311,13 @@ GalliumContext::SetCurrentContext(Bitmap *bitmap, context_id contextID)
if (oldContextID > 0 && oldContextID != contextID) {
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
context->api->make_current(context->api, context->st, context->draw->stfbi,
context->read->stfbi);
//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;
fDisplay->api->make_current(fDisplay->api, context->st, context->buffer->stfbi,
context->buffer->stfbi);
Unlock();
return B_OK;
}
@ -326,40 +329,62 @@ GalliumContext::SwapBuffers(context_id contextID)
CALLED();
Lock();
struct hgl_context *context = fContext[contextID];
Unlock();
struct hgl_context* context = fContext[contextID];
if (!context) {
ERROR("%s: context not found\n", __func__);
return B_ERROR;
}
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__);
Unlock();
return B_ERROR;
}
fScreen->flush_frontbuffer(fScreen, context->st->pipe, surface->texture, 0, 0,
context->bitmap, NULL);
// will flush front buffer if no double buffering is used
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;
}
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
GalliumContext::Validate(uint32 width, uint32 height)
{
CALLED();
if (!fContext[fCurrentContext]) {
if (!fContext[fCurrentContext])
return false;
}
if (fContext[fCurrentContext]->width != width
|| fContext[fCurrentContext]->height != height) {
if (fContext[fCurrentContext]->width != width + 1
|| fContext[fCurrentContext]->height != height + 1) {
Invalidate(width, height);
return false;
}
@ -375,12 +400,11 @@ GalliumContext::Invalidate(uint32 width, uint32 height)
assert(fContext[fCurrentContext]);
// Update st_context dimensions
fContext[fCurrentContext]->width = width;
fContext[fCurrentContext]->height = height;
fContext[fCurrentContext]->width = width + 1;
fContext[fCurrentContext]->height = height + 1;
// Is this the best way to invalidate?
p_atomic_inc(&fContext[fCurrentContext]->read->stfbi->stamp);
p_atomic_inc(&fContext[fCurrentContext]->draw->stfbi->stamp);
p_atomic_inc(&fContext[fCurrentContext]->buffer->stfbi->stamp);
}

View File

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

View File

@ -35,16 +35,99 @@ extern const char* color_space_name(color_space space);
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,
BGLDispatcher* dispatcher)
struct RasBuf32
{
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),
fBitmap(NULL),
BGLRenderer(view, options),
fDirectModeEnabled(false),
fInfo(NULL),
fInfoLocker("info locker"),
@ -53,9 +136,6 @@ SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options,
{
CALLED();
// Disable double buffer for the moment.
//options &= ~BGL_DOUBLE;
// Initialize the "Haiku Software GL Pipe"
time_t beg;
time_t end;
@ -65,7 +145,6 @@ SoftwareRenderer::SoftwareRenderer(BGLView *view, ulong options,
TRACE("Haiku Software GL Pipe initialization time: %f.\n",
difftime(end, beg));
// Allocate a bitmap
BRect b = view->Bounds();
fColorSpace = BScreen(view->Window()).ColorSpace();
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();
fHeight = (GLint)b.IntegerHeight();
_AllocateBitmap();
// Initialize the first "Haiku Software GL Pipe" context
beg = time(NULL);
fContextID = fContextObj->CreateContext(fBitmap);
fContextID = fContextObj->CreateContext(this);
end = time(NULL);
if (fContextID < 0)
@ -98,8 +175,6 @@ SoftwareRenderer::~SoftwareRenderer()
if (fContextObj)
delete fContextObj;
if (fBitmap)
delete fBitmap;
}
@ -111,21 +186,19 @@ SoftwareRenderer::LockGL()
color_space cs = BScreen(GLView()->Window()).ColorSpace();
BAutolock lock(fInfoLocker);
if (fDirectModeEnabled && fInfo != NULL) {
fWidth = fInfo->window_bounds.right - fInfo->window_bounds.left;
fHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top;
{
BAutolock lock(fInfoLocker);
if (fDirectModeEnabled && fInfo != NULL) {
fWidth = fInfo->window_bounds.right - fInfo->window_bounds.left;
fHeight = fInfo->window_bounds.bottom - fInfo->window_bounds.top;
}
fContextObj->Validate(fWidth, fHeight);
fColorSpace = cs;
}
if (fBitmap && cs == fColorSpace && fContextObj->Validate(fWidth, fHeight)) {
fContextObj->SetCurrentContext(fBitmap, fContextID);
return;
}
fColorSpace = cs;
_AllocateBitmap();
fContextObj->SetCurrentContext(fBitmap, fContextID);
// do not hold fInfoLocker here to avoid deadlock
fContextObj->SetCurrentContext(true, fContextID);
}
@ -136,76 +209,54 @@ SoftwareRenderer::UnlockGL()
if ((fOptions & BGL_DOUBLE) == 0) {
SwapBuffers();
}
fContextObj->SetCurrentContext(NULL, fContextID);
fContextObj->SetCurrentContext(false, fContextID);
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
SoftwareRenderer::SwapBuffers(bool vsync)
{
// CALLED();
if (!fBitmap)
return;
BScreen screen(GLView()->Window());
fContextObj->SwapBuffers(fContextID);
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;
}
}
fContextObj->Validate(fWidth, fHeight);
if (vsync)
screen.WaitForRetrace();
}
void
SoftwareRenderer::Draw(BRect updateRect)
{
// CALLED();
if ((!fDirectModeEnabled || fInfo == NULL) && fBitmap)
GLView()->DrawBitmap(fBitmap, updateRect, updateRect);
fContextObj->Draw(fContextID, updateRect);
}
@ -213,41 +264,9 @@ status_t
SoftwareRenderer::CopyPixelsOut(BPoint location, BBitmap *bitmap)
{
CALLED();
color_space scs = fBitmap->ColorSpace();
color_space dcs = bitmap->ColorSpace();
if (scs != dcs && (scs != B_RGBA32 || dcs != B_RGB32)) {
ERROR("%s::CopyPixelsOut(): incompatible color space: %s != %s\n",
__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;
// TODO: implement
return B_ERROR;
}
@ -256,40 +275,8 @@ SoftwareRenderer::CopyPixelsIn(BBitmap *bitmap, BPoint location)
{
CALLED();
color_space sourceCS = bitmap->ColorSpace();
color_space destinationCS = fBitmap->ColorSpace();
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;
// TODO: implement
return B_ERROR;
}
@ -327,36 +314,3 @@ SoftwareRenderer::FrameResized(float width, float height)
fWidth = (GLuint)width;
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,37 +18,34 @@
#include "GalliumContext.h"
class SoftwareRenderer : public BGLRenderer {
class SoftwareRenderer : public BGLRenderer, public HGLWinsysContext {
public:
SoftwareRenderer(BGLView *view,
ulong bgl_options,
BGLDispatcher *dispatcher);
ulong bgl_options);
virtual ~SoftwareRenderer();
virtual void LockGL();
virtual void UnlockGL();
void LockGL();
void UnlockGL();
virtual void SwapBuffers(bool vsync = false);
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);
void Display(BBitmap* bitmap, BRect* updateRect);
virtual void EnableDirectMode(bool enabled);
virtual void DirectConnected(direct_buffer_info *info);
void SwapBuffers(bool vsync = false);
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:
void _AllocateBitmap();
GalliumContext* fContextObj;
BBitmap* fBitmap;
context_id fContextID;
bool fDirectModeEnabled;
direct_buffer_info* fInfo;
BLocker fInfoLocker;
ulong fOptions;
ulong fOptions;
GLuint fWidth;
GLuint fHeight;
color_space fColorSpace;

View File

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

View File

@ -27,6 +27,16 @@
#ifndef _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
extern "C" {
#endif

View File

@ -20,7 +20,7 @@
libswhgl = static_library(
'swhgl',
files('hgl_sw_winsys.c'),
files('hgl_sw_winsys.cpp'),
gnu_symbol_visibility : 'hidden',
include_directories : [inc_gallium, inc_include, inc_src, inc_gallium_aux,
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 "GLDispatcher.h"
BGLRenderer::BGLRenderer(BGLView* view, ulong glOptions,
BGLDispatcher* dispatcher)
BGLRenderer::BGLRenderer(BGLView* view, ulong glOptions)
:
fRefCount(1),
fView(view),
fOptions(glOptions),
fDispatcher(dispatcher)
fOptions(glOptions)
{
}
BGLRenderer::~BGLRenderer()
{
delete fDispatcher;
}
@ -38,7 +33,7 @@ BGLRenderer::Acquire()
void
BGLRenderer::Release()
{
if (atomic_add(&fRefCount, -1) < 1)
if (atomic_add(&fRefCount, -1) <= 1)
delete this;
}

View File

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

View File

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

View File

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

View File

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