Bring back the framebuffer driver and accelerant.
This reverts commit 72fc5e6a71
.
They were removed because app_server often picked them instead of
a better graphics driver, and fallbacks merged into VESA instead.
That seems to have created more problems than it solved, in the long run,
and so the intent now is to change app_server to understand the
framebuffer driver as a fallback one instead.
Change-Id: I6edd97fb29ed2b9c13c6c540569695c8426ecfd7
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4614
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
b7a1261eef
commit
f7bd3509e3
@ -4,6 +4,7 @@ SubInclude HAIKU_TOP src add-ons accelerants 3dfx ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants ati ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants common ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants et6x00 ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants framebuffer ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants intel_810 ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants intel_extreme ;
|
||||
SubInclude HAIKU_TOP src add-ons accelerants matrox ;
|
||||
|
13
src/add-ons/accelerants/framebuffer/Jamfile
Normal file
13
src/add-ons/accelerants/framebuffer/Jamfile
Normal file
@ -0,0 +1,13 @@
|
||||
SubDir HAIKU_TOP src add-ons accelerants framebuffer ;
|
||||
|
||||
UsePrivateHeaders graphics ;
|
||||
UsePrivateHeaders [ FDirName graphics vesa ] ;
|
||||
UsePrivateHeaders [ FDirName graphics common ] ;
|
||||
|
||||
Addon framebuffer.accelerant :
|
||||
accelerant.cpp
|
||||
engine.cpp
|
||||
hooks.cpp
|
||||
mode.cpp
|
||||
: libaccelerantscommon.a
|
||||
;
|
249
src/add-ons/accelerants/framebuffer/accelerant.cpp
Normal file
249
src/add-ons/accelerants/framebuffer/accelerant.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
|
||||
//#define TRACE_ACCELERANT
|
||||
#ifdef TRACE_ACCELERANT
|
||||
extern "C" void _sPrintf(const char *format, ...);
|
||||
# define TRACE(x) _sPrintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
struct accelerant_info *gInfo;
|
||||
|
||||
|
||||
class AreaCloner {
|
||||
public:
|
||||
AreaCloner();
|
||||
~AreaCloner();
|
||||
|
||||
area_id Clone(const char *name, void **_address, uint32 spec,
|
||||
uint32 protection, area_id sourceArea);
|
||||
status_t InitCheck() { return fArea < B_OK ? (status_t)fArea : B_OK; }
|
||||
void Keep();
|
||||
|
||||
private:
|
||||
area_id fArea;
|
||||
};
|
||||
|
||||
|
||||
AreaCloner::AreaCloner()
|
||||
:
|
||||
fArea(-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AreaCloner::~AreaCloner()
|
||||
{
|
||||
if (fArea >= B_OK)
|
||||
delete_area(fArea);
|
||||
}
|
||||
|
||||
|
||||
area_id
|
||||
AreaCloner::Clone(const char *name, void **_address, uint32 spec,
|
||||
uint32 protection, area_id sourceArea)
|
||||
{
|
||||
fArea = clone_area(name, _address, spec, protection, sourceArea);
|
||||
return fArea;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AreaCloner::Keep()
|
||||
{
|
||||
fArea = -1;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
/*! This is the common accelerant_info initializer. It is called by
|
||||
both, the first accelerant and all clones.
|
||||
*/
|
||||
static status_t
|
||||
init_common(int device, bool isClone)
|
||||
{
|
||||
// initialize global accelerant info structure
|
||||
|
||||
gInfo = (accelerant_info *)malloc(sizeof(accelerant_info));
|
||||
if (gInfo == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(gInfo, 0, sizeof(accelerant_info));
|
||||
|
||||
gInfo->is_clone = isClone;
|
||||
gInfo->device = device;
|
||||
gInfo->current_mode = UINT16_MAX;
|
||||
|
||||
// get basic info from driver
|
||||
|
||||
area_id sharedArea;
|
||||
if (ioctl(device, VESA_GET_PRIVATE_DATA, &sharedArea, sizeof(area_id))
|
||||
!= 0) {
|
||||
free(gInfo);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
AreaCloner sharedCloner;
|
||||
gInfo->shared_info_area = sharedCloner.Clone("framebuffer shared info",
|
||||
(void **)&gInfo->shared_info, B_ANY_ADDRESS,
|
||||
B_READ_AREA | B_WRITE_AREA, sharedArea);
|
||||
status_t status = sharedCloner.InitCheck();
|
||||
if (status < B_OK) {
|
||||
free(gInfo);
|
||||
return status;
|
||||
}
|
||||
|
||||
sharedCloner.Keep();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*! Cleans up everything done by a successful init_common(). */
|
||||
static void
|
||||
uninit_common(void)
|
||||
{
|
||||
delete_area(gInfo->shared_info_area);
|
||||
gInfo->shared_info_area = -1;
|
||||
gInfo->shared_info = NULL;
|
||||
|
||||
// close the file handle ONLY if we're the clone
|
||||
// (this is what Be tells us ;)
|
||||
if (gInfo->is_clone)
|
||||
close(gInfo->device);
|
||||
|
||||
free(gInfo);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - public accelerant functions
|
||||
|
||||
|
||||
/*! Init primary accelerant */
|
||||
status_t
|
||||
framebuffer_init_accelerant(int device)
|
||||
{
|
||||
TRACE(("framebuffer_init_accelerant()\n"));
|
||||
|
||||
status_t status = init_common(device, false);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
status = create_mode_list();
|
||||
if (status != B_OK) {
|
||||
uninit_common();
|
||||
return status;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
framebuffer_accelerant_clone_info_size(void)
|
||||
{
|
||||
// clone info is device name, so return its maximum size
|
||||
return B_PATH_NAME_LENGTH;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
framebuffer_get_accelerant_clone_info(void *info)
|
||||
{
|
||||
ioctl(gInfo->device, VESA_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_clone_accelerant(void *info)
|
||||
{
|
||||
TRACE(("framebuffer_clone_accelerant()\n"));
|
||||
|
||||
// create full device name
|
||||
char path[MAXPATHLEN];
|
||||
strcpy(path, "/dev/");
|
||||
strcat(path, (const char *)info);
|
||||
|
||||
int fd = open(path, B_READ_WRITE);
|
||||
if (fd < 0)
|
||||
return errno;
|
||||
|
||||
status_t status = init_common(fd, true);
|
||||
if (status != B_OK)
|
||||
goto err1;
|
||||
|
||||
// get read-only clone of supported display modes
|
||||
status = gInfo->mode_list_area = clone_area(
|
||||
"framebuffer cloned modes", (void **)&gInfo->mode_list,
|
||||
B_ANY_ADDRESS, B_READ_AREA, gInfo->shared_info->mode_list_area);
|
||||
if (status < B_OK)
|
||||
goto err2;
|
||||
|
||||
return B_OK;
|
||||
|
||||
err2:
|
||||
uninit_common();
|
||||
err1:
|
||||
close(fd);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*! This function is called for both, the primary accelerant and all of
|
||||
its clones.
|
||||
*/
|
||||
void
|
||||
framebuffer_uninit_accelerant(void)
|
||||
{
|
||||
TRACE(("framebuffer_uninit_accelerant()\n"));
|
||||
|
||||
// delete accelerant instance data
|
||||
delete_area(gInfo->mode_list_area);
|
||||
gInfo->mode_list = NULL;
|
||||
|
||||
uninit_common();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_get_accelerant_device_info(accelerant_device_info *info)
|
||||
{
|
||||
info->version = B_ACCELERANT_VERSION;
|
||||
strcpy(info->name, "Framebuffer Driver");
|
||||
strcpy(info->chipset, "Framebuffer");
|
||||
// ToDo: provide some more insight here...
|
||||
strcpy(info->serial_no, "None");
|
||||
|
||||
#if 0
|
||||
info->memory = ???
|
||||
info->dac_speed = ???
|
||||
#endif
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
sem_id
|
||||
framebuffer_accelerant_retrace_semaphore()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
30
src/add-ons/accelerants/framebuffer/accelerant.h
Normal file
30
src/add-ons/accelerants/framebuffer/accelerant.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VESA_ACCELERANT_H
|
||||
#define VESA_ACCELERANT_H
|
||||
|
||||
|
||||
#include "vesa_info.h"
|
||||
|
||||
|
||||
typedef struct accelerant_info {
|
||||
int device;
|
||||
bool is_clone;
|
||||
|
||||
area_id shared_info_area;
|
||||
vesa_shared_info *shared_info;
|
||||
|
||||
area_id mode_list_area;
|
||||
// cloned list of standard display modes
|
||||
display_mode *mode_list;
|
||||
uint16 current_mode;
|
||||
} accelerant_info;
|
||||
|
||||
extern accelerant_info *gInfo;
|
||||
|
||||
extern status_t create_mode_list(void);
|
||||
|
||||
#endif /* VESA_ACCELERANT_H */
|
49
src/add-ons/accelerants/framebuffer/accelerant_protos.h
Normal file
49
src/add-ons/accelerants/framebuffer/accelerant_protos.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _ACCELERANT_PROTOS_H
|
||||
#define _ACCELERANT_PROTOS_H
|
||||
|
||||
|
||||
#include <Accelerant.h>
|
||||
#include "video_overlay.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// general
|
||||
status_t framebuffer_init_accelerant(int fd);
|
||||
ssize_t framebuffer_accelerant_clone_info_size(void);
|
||||
void framebuffer_get_accelerant_clone_info(void *data);
|
||||
status_t framebuffer_clone_accelerant(void *data);
|
||||
void framebuffer_uninit_accelerant(void);
|
||||
status_t framebuffer_get_accelerant_device_info(accelerant_device_info *adi);
|
||||
sem_id framebuffer_accelerant_retrace_semaphore(void);
|
||||
|
||||
// modes & constraints
|
||||
uint32 framebuffer_accelerant_mode_count(void);
|
||||
status_t framebuffer_get_mode_list(display_mode *dm);
|
||||
status_t framebuffer_set_display_mode(display_mode *modeToSet);
|
||||
status_t framebuffer_get_display_mode(display_mode *currentMode);
|
||||
status_t framebuffer_get_frame_buffer_config(frame_buffer_config *config);
|
||||
status_t framebuffer_get_pixel_clock_limits(display_mode *dm, uint32 *low,
|
||||
uint32 *high);
|
||||
|
||||
// accelerant engine
|
||||
uint32 framebuffer_accelerant_engine_count(void);
|
||||
status_t framebuffer_acquire_engine(uint32 capabilities, uint32 maxWait,
|
||||
sync_token *st, engine_token **et);
|
||||
status_t framebuffer_release_engine(engine_token *et, sync_token *st);
|
||||
void framebuffer_wait_engine_idle(void);
|
||||
status_t framebuffer_get_sync_token(engine_token *et, sync_token *st);
|
||||
status_t framebuffer_sync_to_token(sync_token *st);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ACCELERANT_PROTOS_H */
|
59
src/add-ons/accelerants/framebuffer/engine.cpp
Normal file
59
src/add-ons/accelerants/framebuffer/engine.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "vesa_info.h"
|
||||
|
||||
|
||||
static engine_token sEngineToken = {1, 0 /*B_2D_ACCELERATION*/, NULL};
|
||||
|
||||
|
||||
uint32
|
||||
framebuffer_accelerant_engine_count(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_acquire_engine(uint32 capabilities, uint32 max_wait, sync_token *syncToken,
|
||||
engine_token **_engineToken)
|
||||
{
|
||||
*_engineToken = &sEngineToken;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_release_engine(engine_token *engineToken, sync_token *syncToken)
|
||||
{
|
||||
if (syncToken != NULL)
|
||||
syncToken->engine_id = engineToken->engine_id;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
framebuffer_wait_engine_idle(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_get_sync_token(engine_token *engineToken, sync_token *syncToken)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_sync_to_token(sync_token *syncToken)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
65
src/add-ons/accelerants/framebuffer/hooks.cpp
Normal file
65
src/add-ons/accelerants/framebuffer/hooks.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2005-2012, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
|
||||
extern "C" void*
|
||||
get_accelerant_hook(uint32 feature, void* data)
|
||||
{
|
||||
switch (feature) {
|
||||
/* general */
|
||||
case B_INIT_ACCELERANT:
|
||||
return (void*)framebuffer_init_accelerant;
|
||||
case B_UNINIT_ACCELERANT:
|
||||
return (void*)framebuffer_uninit_accelerant;
|
||||
case B_CLONE_ACCELERANT:
|
||||
return (void*)framebuffer_clone_accelerant;
|
||||
case B_ACCELERANT_CLONE_INFO_SIZE:
|
||||
return (void*)framebuffer_accelerant_clone_info_size;
|
||||
case B_GET_ACCELERANT_CLONE_INFO:
|
||||
return (void*)framebuffer_get_accelerant_clone_info;
|
||||
case B_GET_ACCELERANT_DEVICE_INFO:
|
||||
return (void*)framebuffer_get_accelerant_device_info;
|
||||
case B_ACCELERANT_RETRACE_SEMAPHORE:
|
||||
return (void*)framebuffer_accelerant_retrace_semaphore;
|
||||
|
||||
/* mode configuration */
|
||||
case B_ACCELERANT_MODE_COUNT:
|
||||
return (void*)framebuffer_accelerant_mode_count;
|
||||
case B_GET_MODE_LIST:
|
||||
return (void*)framebuffer_get_mode_list;
|
||||
case B_SET_DISPLAY_MODE:
|
||||
return (void*)framebuffer_set_display_mode;
|
||||
case B_GET_DISPLAY_MODE:
|
||||
return (void*)framebuffer_get_display_mode;
|
||||
case B_GET_FRAME_BUFFER_CONFIG:
|
||||
return (void*)framebuffer_get_frame_buffer_config;
|
||||
case B_GET_PIXEL_CLOCK_LIMITS:
|
||||
return (void*)framebuffer_get_pixel_clock_limits;
|
||||
|
||||
/* engine/synchronization */
|
||||
case B_ACCELERANT_ENGINE_COUNT:
|
||||
return (void*)framebuffer_accelerant_engine_count;
|
||||
case B_ACQUIRE_ENGINE:
|
||||
return (void*)framebuffer_acquire_engine;
|
||||
case B_RELEASE_ENGINE:
|
||||
return (void*)framebuffer_release_engine;
|
||||
case B_WAIT_ENGINE_IDLE:
|
||||
return (void*)framebuffer_wait_engine_idle;
|
||||
case B_GET_SYNC_TOKEN:
|
||||
return (void*)framebuffer_get_sync_token;
|
||||
case B_SYNC_TO_TOKEN:
|
||||
return (void*)framebuffer_sync_to_token;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
147
src/add-ons/accelerants/framebuffer/mode.cpp
Normal file
147
src/add-ons/accelerants/framebuffer/mode.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2005-2015, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <compute_display_timing.h>
|
||||
#include <create_display_modes.h>
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
#include "utility.h"
|
||||
|
||||
|
||||
//#define TRACE_MODE
|
||||
#ifdef TRACE_MODE
|
||||
extern "C" void _sPrintf(const char* format, ...);
|
||||
# define TRACE(x) _sPrintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
bool
|
||||
operator==(const display_mode &lhs, const display_mode &rhs)
|
||||
{
|
||||
return lhs.space == rhs.space
|
||||
&& lhs.virtual_width == rhs.virtual_width
|
||||
&& lhs.virtual_height == rhs.virtual_height
|
||||
&& lhs.h_display_start == rhs.h_display_start
|
||||
&& lhs.v_display_start == rhs.v_display_start;
|
||||
}
|
||||
|
||||
|
||||
/*! Checks if the specified \a mode can be set using VESA. */
|
||||
static bool
|
||||
is_mode_supported(display_mode* mode)
|
||||
{
|
||||
return (mode != NULL) && (*mode == gInfo->shared_info->current_mode);
|
||||
}
|
||||
|
||||
|
||||
/*! Creates the initial mode list of the primary accelerant.
|
||||
It's called from vesa_init_accelerant().
|
||||
*/
|
||||
status_t
|
||||
create_mode_list(void)
|
||||
{
|
||||
const color_space colorspace[] = {
|
||||
(color_space)gInfo->shared_info->current_mode.space
|
||||
};
|
||||
display_mode mode = gInfo->shared_info->current_mode;
|
||||
|
||||
compute_display_timing(mode.virtual_width, mode.virtual_height, 60, false,
|
||||
&mode.timing);
|
||||
fill_display_mode(mode.virtual_width, mode.virtual_height, &mode);
|
||||
|
||||
gInfo->mode_list_area = create_display_modes("framebuffer modes",
|
||||
NULL, &mode, 1, colorspace, 1, is_mode_supported, &gInfo->mode_list,
|
||||
&gInfo->shared_info->mode_count);
|
||||
|
||||
if (gInfo->mode_list_area < 0)
|
||||
return gInfo->mode_list_area;
|
||||
|
||||
gInfo->shared_info->mode_list_area = gInfo->mode_list_area;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
uint32
|
||||
framebuffer_accelerant_mode_count(void)
|
||||
{
|
||||
TRACE(("framebuffer_accelerant_mode_count() = %d\n",
|
||||
gInfo->shared_info->mode_count));
|
||||
return gInfo->shared_info->mode_count;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_get_mode_list(display_mode* modeList)
|
||||
{
|
||||
TRACE(("framebuffer_get_mode_info()\n"));
|
||||
memcpy(modeList, gInfo->mode_list,
|
||||
gInfo->shared_info->mode_count * sizeof(display_mode));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_set_display_mode(display_mode* _mode)
|
||||
{
|
||||
TRACE(("framebuffer_set_display_mode()\n"));
|
||||
if (_mode != NULL && *_mode == gInfo->shared_info->current_mode)
|
||||
return B_OK;
|
||||
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_get_display_mode(display_mode* _currentMode)
|
||||
{
|
||||
TRACE(("framebuffer_get_display_mode()\n"));
|
||||
*_currentMode = gInfo->shared_info->current_mode;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_get_frame_buffer_config(frame_buffer_config* config)
|
||||
{
|
||||
TRACE(("framebuffer_get_frame_buffer_config()\n"));
|
||||
|
||||
config->frame_buffer = gInfo->shared_info->frame_buffer;
|
||||
config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer;
|
||||
config->bytes_per_row = gInfo->shared_info->bytes_per_row;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_get_pixel_clock_limits(display_mode* mode, uint32* _low, uint32* _high)
|
||||
{
|
||||
TRACE(("framebuffer_get_pixel_clock_limits()\n"));
|
||||
|
||||
// TODO: do some real stuff here (taken from radeon driver)
|
||||
uint32 totalPixel = (uint32)mode->timing.h_total
|
||||
* (uint32)mode->timing.v_total;
|
||||
uint32 clockLimit = 2000000;
|
||||
|
||||
// lower limit of about 48Hz vertical refresh
|
||||
*_low = totalPixel * 48L / 1000L;
|
||||
if (*_low > clockLimit)
|
||||
return B_ERROR;
|
||||
|
||||
*_high = clockLimit;
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ SubInclude HAIKU_TOP src add-ons kernel drivers graphics 3dfx ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics ati ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics common ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics et6x00 ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics framebuffer ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics intel_810 ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics intel_extreme ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers graphics matrox ;
|
||||
|
12
src/add-ons/kernel/drivers/graphics/framebuffer/Jamfile
Normal file
12
src/add-ons/kernel/drivers/graphics/framebuffer/Jamfile
Normal file
@ -0,0 +1,12 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel drivers graphics framebuffer ;
|
||||
|
||||
UsePrivateHeaders [ FDirName graphics common ] ;
|
||||
UsePrivateHeaders [ FDirName graphics vesa ] ;
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
KernelAddon framebuffer :
|
||||
device.cpp
|
||||
driver.cpp
|
||||
framebuffer.cpp
|
||||
;
|
||||
|
166
src/add-ons/kernel/drivers/graphics/framebuffer/device.cpp
Normal file
166
src/add-ons/kernel/drivers/graphics/framebuffer/device.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Drivers.h>
|
||||
#include <graphic_driver.h>
|
||||
#include <image.h>
|
||||
#include <KernelExport.h>
|
||||
#include <OS.h>
|
||||
#include <PCI.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <vesa.h>
|
||||
|
||||
#include "driver.h"
|
||||
#include "utility.h"
|
||||
#include "vesa_info.h"
|
||||
#include "framebuffer_private.h"
|
||||
|
||||
|
||||
//#define TRACE_DEVICE
|
||||
#ifdef TRACE_DEVICE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
static status_t
|
||||
device_open(const char* name, uint32 flags, void** _cookie)
|
||||
{
|
||||
int id;
|
||||
|
||||
// find accessed device
|
||||
char* thisName;
|
||||
|
||||
// search for device name
|
||||
for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
|
||||
if (!strcmp(name, thisName))
|
||||
break;
|
||||
}
|
||||
if (thisName == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
framebuffer_info* info = gDeviceInfo[id];
|
||||
|
||||
mutex_lock(&gLock);
|
||||
|
||||
status_t status = B_OK;
|
||||
|
||||
if (info->open_count == 0) {
|
||||
// this device has been opened for the first time, so
|
||||
// we allocate needed resources and initialize the structure
|
||||
if (status == B_OK)
|
||||
status = framebuffer_init(*info);
|
||||
if (status == B_OK)
|
||||
info->id = id;
|
||||
}
|
||||
|
||||
if (status == B_OK) {
|
||||
info->open_count++;
|
||||
*_cookie = info;
|
||||
}
|
||||
|
||||
mutex_unlock(&gLock);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_close(void* cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_free(void* cookie)
|
||||
{
|
||||
struct framebuffer_info* info = (framebuffer_info*)cookie;
|
||||
|
||||
mutex_lock(&gLock);
|
||||
|
||||
if (info->open_count-- == 1) {
|
||||
// release info structure
|
||||
framebuffer_uninit(*info);
|
||||
}
|
||||
|
||||
mutex_unlock(&gLock);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength)
|
||||
{
|
||||
struct framebuffer_info* info = (framebuffer_info*)cookie;
|
||||
|
||||
switch (msg) {
|
||||
case B_GET_ACCELERANT_SIGNATURE:
|
||||
dprintf(DEVICE_NAME ": acc: %s\n", ACCELERANT_NAME);
|
||||
if (user_strlcpy((char*)buffer, ACCELERANT_NAME,
|
||||
B_FILE_NAME_LENGTH) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return B_OK;
|
||||
|
||||
// needed to share data between kernel and accelerant
|
||||
case VESA_GET_PRIVATE_DATA:
|
||||
return user_memcpy(buffer, &info->shared_area, sizeof(area_id));
|
||||
|
||||
// needed for cloning
|
||||
case VESA_GET_DEVICE_NAME:
|
||||
if (user_strlcpy((char*)buffer, gDeviceNames[info->id],
|
||||
B_PATH_NAME_LENGTH) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n",
|
||||
msg, bufferLength));
|
||||
break;
|
||||
}
|
||||
|
||||
return B_DEV_INVALID_IOCTL;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length)
|
||||
{
|
||||
*_length = 0;
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_write(void* /*cookie*/, off_t /*pos*/, const void* /*buffer*/,
|
||||
size_t* _length)
|
||||
{
|
||||
*_length = 0;
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
|
||||
device_hooks gDeviceHooks = {
|
||||
device_open,
|
||||
device_close,
|
||||
device_free,
|
||||
device_ioctl,
|
||||
device_read,
|
||||
device_write,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
13
src/add-ons/kernel/drivers/graphics/framebuffer/device.h
Normal file
13
src/add-ons/kernel/drivers/graphics/framebuffer/device.h
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DEVICE_H
|
||||
#define DEVICE_H
|
||||
|
||||
#include <Drivers.h>
|
||||
|
||||
// The device hooks for the published device
|
||||
extern device_hooks gDeviceHooks;
|
||||
|
||||
#endif /* DEVICE_H */
|
118
src/add-ons/kernel/drivers/graphics/framebuffer/driver.cpp
Normal file
118
src/add-ons/kernel/drivers/graphics/framebuffer/driver.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
#include <KernelExport.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <PCI.h>
|
||||
#include <frame_buffer_console.h>
|
||||
#include <boot_item.h>
|
||||
#include <vesa_info.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "driver.h"
|
||||
#include "device.h"
|
||||
|
||||
|
||||
#define TRACE_DRIVER
|
||||
#ifdef TRACE_DRIVER
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
#define MAX_CARDS 1
|
||||
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
||||
char* gDeviceNames[MAX_CARDS + 1];
|
||||
framebuffer_info* gDeviceInfo[MAX_CARDS];
|
||||
mutex gLock;
|
||||
|
||||
|
||||
extern "C" const char**
|
||||
publish_devices(void)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": publish_devices()\n"));
|
||||
return (const char**)gDeviceNames;
|
||||
}
|
||||
|
||||
|
||||
extern "C" status_t
|
||||
init_hardware(void)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": init_hardware()\n"));
|
||||
|
||||
// If we don't have a VESA mode list, then we are a dumb
|
||||
// framebuffer, e.g. when there are no drivers available
|
||||
// on a UEFI system.
|
||||
return (get_boot_item(VESA_MODES_BOOT_INFO, NULL) == NULL
|
||||
&& get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL) != NULL)
|
||||
? B_OK : B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
extern "C" status_t
|
||||
init_driver(void)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": init_driver()\n"));
|
||||
|
||||
gDeviceInfo[0] = (framebuffer_info*)malloc(sizeof(framebuffer_info));
|
||||
if (gDeviceInfo[0] == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(gDeviceInfo[0], 0, sizeof(framebuffer_info));
|
||||
|
||||
gDeviceNames[0] = strdup("graphics/framebuffer");
|
||||
if (gDeviceNames[0] == NULL) {
|
||||
free(gDeviceNames[0]);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
gDeviceNames[1] = NULL;
|
||||
|
||||
mutex_init(&gLock, "framebuffer lock");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void
|
||||
uninit_driver(void)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": uninit_driver()\n"));
|
||||
|
||||
mutex_destroy(&gLock);
|
||||
|
||||
// free device related structures
|
||||
char* name;
|
||||
for (int32 index = 0; (name = gDeviceNames[index]) != NULL; index++) {
|
||||
free(gDeviceInfo[index]);
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" device_hooks*
|
||||
find_device(const char* name)
|
||||
{
|
||||
int index;
|
||||
|
||||
TRACE((DEVICE_NAME ": find_device()\n"));
|
||||
|
||||
for (index = 0; gDeviceNames[index] != NULL; index++) {
|
||||
if (!strcmp(name, gDeviceNames[index]))
|
||||
return &gDeviceHooks;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
22
src/add-ons/kernel/drivers/graphics/framebuffer/driver.h
Normal file
22
src/add-ons/kernel/drivers/graphics/framebuffer/driver.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DRIVER_H
|
||||
#define DRIVER_H
|
||||
|
||||
|
||||
#include <ISA.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <lock.h>
|
||||
|
||||
#include "framebuffer_private.h"
|
||||
|
||||
|
||||
extern char* gDeviceNames[];
|
||||
extern framebuffer_info* gDeviceInfo[];
|
||||
extern mutex gLock;
|
||||
|
||||
#endif /* DRIVER_H */
|
202
src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer.cpp
Normal file
202
src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "framebuffer_private.h"
|
||||
#include "vesa.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <drivers/bios.h>
|
||||
|
||||
#include <boot_item.h>
|
||||
#include <frame_buffer_console.h>
|
||||
#include <util/kernel_cpp.h>
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include "driver.h"
|
||||
#include "utility.h"
|
||||
#include "vesa_info.h"
|
||||
|
||||
|
||||
static status_t
|
||||
find_graphics_card(addr_t frameBuffer, addr_t& base, size_t& size)
|
||||
{
|
||||
// TODO: when we port this over to the new driver API, this mechanism can be
|
||||
// used to find the right device_node
|
||||
pci_module_info* pci;
|
||||
if (get_module(B_PCI_MODULE_NAME, (module_info**)&pci) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
pci_info info;
|
||||
for (int32 index = 0; pci->get_nth_pci_info(index, &info) == B_OK; index++) {
|
||||
if (info.class_base != PCI_display)
|
||||
continue;
|
||||
|
||||
// check PCI BARs
|
||||
for (uint32 i = 0; i < 6; i++) {
|
||||
if (info.u.h0.base_registers[i] <= frameBuffer
|
||||
&& info.u.h0.base_registers[i] + info.u.h0.base_register_sizes[i]
|
||||
> frameBuffer) {
|
||||
// found it!
|
||||
base = info.u.h0.base_registers[i];
|
||||
size = info.u.h0.base_register_sizes[i];
|
||||
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
get_color_space_for_depth(uint32 depth)
|
||||
{
|
||||
switch (depth) {
|
||||
case 1:
|
||||
return B_GRAY1;
|
||||
case 4:
|
||||
return B_GRAY8;
|
||||
// the app_server is smart enough to translate this to VGA mode
|
||||
case 8:
|
||||
return B_CMAP8;
|
||||
case 15:
|
||||
return B_RGB15;
|
||||
case 16:
|
||||
return B_RGB16;
|
||||
case 24:
|
||||
return B_RGB24;
|
||||
case 32:
|
||||
return B_RGB32;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*! Remaps the frame buffer if necessary; if we've already mapped the complete
|
||||
frame buffer, there is no need to map it again.
|
||||
*/
|
||||
static status_t
|
||||
remap_frame_buffer(framebuffer_info& info, addr_t physicalBase, uint32 width,
|
||||
uint32 height, int8 depth, uint32 bytesPerRow, bool initializing)
|
||||
{
|
||||
vesa_shared_info& sharedInfo = *info.shared_info;
|
||||
addr_t frameBuffer = info.frame_buffer;
|
||||
|
||||
if (!info.complete_frame_buffer_mapped) {
|
||||
addr_t base = physicalBase;
|
||||
size_t size = bytesPerRow * height;
|
||||
bool remap = !initializing;
|
||||
|
||||
if (info.physical_frame_buffer_size != 0) {
|
||||
// we can map the complete frame buffer
|
||||
base = info.physical_frame_buffer;
|
||||
size = info.physical_frame_buffer_size;
|
||||
remap = true;
|
||||
}
|
||||
|
||||
if (remap) {
|
||||
area_id area = map_physical_memory("framebuffer buffer", base,
|
||||
size, B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA,
|
||||
(void**)&frameBuffer);
|
||||
if (area < 0)
|
||||
return area;
|
||||
|
||||
if (initializing) {
|
||||
// We need to manually update the kernel's frame buffer address,
|
||||
// since this frame buffer remapping has not been issued by the
|
||||
// app_server (which would otherwise take care of this)
|
||||
frame_buffer_update(frameBuffer, width, height, depth,
|
||||
bytesPerRow);
|
||||
}
|
||||
|
||||
delete_area(info.shared_info->frame_buffer_area);
|
||||
|
||||
info.frame_buffer = frameBuffer;
|
||||
sharedInfo.frame_buffer_area = area;
|
||||
|
||||
// Turn on write combining for the area
|
||||
vm_set_area_memory_type(area, base, B_MTR_WC);
|
||||
|
||||
if (info.physical_frame_buffer_size != 0)
|
||||
info.complete_frame_buffer_mapped = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (info.complete_frame_buffer_mapped)
|
||||
frameBuffer += physicalBase - info.physical_frame_buffer;
|
||||
|
||||
// Update shared frame buffer information
|
||||
sharedInfo.frame_buffer = (uint8*)frameBuffer;
|
||||
sharedInfo.physical_frame_buffer = (uint8*)physicalBase;
|
||||
sharedInfo.bytes_per_row = bytesPerRow;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
framebuffer_init(framebuffer_info& info)
|
||||
{
|
||||
frame_buffer_boot_info* bufferInfo
|
||||
= (frame_buffer_boot_info*)get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL);
|
||||
if (bufferInfo == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
info.complete_frame_buffer_mapped = false;
|
||||
|
||||
// Find out which PCI device we belong to, so that we know its frame buffer
|
||||
// size
|
||||
find_graphics_card(bufferInfo->physical_frame_buffer,
|
||||
info.physical_frame_buffer, info.physical_frame_buffer_size);
|
||||
|
||||
size_t sharedSize = (sizeof(vesa_shared_info) + 7) & ~7;
|
||||
|
||||
info.shared_area = create_area("framebuffer shared info",
|
||||
(void**)&info.shared_info, B_ANY_KERNEL_ADDRESS,
|
||||
ROUND_TO_PAGE_SIZE(sharedSize), B_FULL_LOCK,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);
|
||||
if (info.shared_area < 0)
|
||||
return info.shared_area;
|
||||
|
||||
vesa_shared_info& sharedInfo = *info.shared_info;
|
||||
|
||||
memset(&sharedInfo, 0, sizeof(vesa_shared_info));
|
||||
|
||||
sharedInfo.frame_buffer_area = bufferInfo->area;
|
||||
|
||||
remap_frame_buffer(info, bufferInfo->physical_frame_buffer,
|
||||
bufferInfo->width, bufferInfo->height, bufferInfo->depth,
|
||||
bufferInfo->bytes_per_row, true);
|
||||
// Does not matter if this fails - the frame buffer was already mapped
|
||||
// before.
|
||||
|
||||
sharedInfo.current_mode.virtual_width = bufferInfo->width;
|
||||
sharedInfo.current_mode.virtual_height = bufferInfo->height;
|
||||
sharedInfo.current_mode.space = get_color_space_for_depth(
|
||||
bufferInfo->depth);
|
||||
|
||||
dprintf(DEVICE_NAME ": framebuffer_init() completed successfully!\n");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
framebuffer_uninit(framebuffer_info& info)
|
||||
{
|
||||
dprintf(DEVICE_NAME": framebuffer_uninit()\n");
|
||||
|
||||
delete_area(info.shared_info->frame_buffer_area);
|
||||
delete_area(info.shared_area);
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VESA_PRIVATE_H
|
||||
#define VESA_PRIVATE_H
|
||||
|
||||
|
||||
#include <Drivers.h>
|
||||
#include <Accelerant.h>
|
||||
#include <PCI.h>
|
||||
|
||||
|
||||
#define DEVICE_NAME "framebuffer"
|
||||
#define ACCELERANT_NAME "framebuffer.accelerant"
|
||||
|
||||
|
||||
struct framebuffer_info {
|
||||
uint32 cookie_magic;
|
||||
int32 open_count;
|
||||
int32 id;
|
||||
struct vesa_shared_info* shared_info;
|
||||
area_id shared_area;
|
||||
|
||||
addr_t frame_buffer;
|
||||
addr_t physical_frame_buffer;
|
||||
size_t physical_frame_buffer_size;
|
||||
bool complete_frame_buffer_mapped;
|
||||
};
|
||||
|
||||
extern status_t framebuffer_init(framebuffer_info& info);
|
||||
extern void framebuffer_uninit(framebuffer_info& info);
|
||||
|
||||
#endif /* VESA_PRIVATE_H */
|
Loading…
Reference in New Issue
Block a user