diff --git a/include/exstubs.h b/include/exstubs.h index add9950e..003dd3d9 100644 --- a/include/exstubs.h +++ b/include/exstubs.h @@ -96,11 +96,20 @@ typedef struct _DriDriver DriDriver; typedef struct _DriDriverOps { DriDriver* (*create_driver) (int device_fd); + void (*destroy_driver) (DriDriver *driver); + /** + * This operator creates a buffer with the specified pixel format, + * width, and height. If succeed, a valid (not zero) buffer id + * and the picth (row stride in bytes) will be returned. + * If failed, it returns 0. + * + * \note The driver must implement this operator. + */ uint32_t (* create_buffer) (DriDriver *driver, int depth, int bpp, - unsigned int width, unsigned int height, + unsigned int width, unsigned int height, unsigned int *pitch); BOOL (* fetch_buffer) (DriDriver *driver, @@ -108,19 +117,104 @@ typedef struct _DriDriverOps { unsigned int *width, unsigned int *height, unsigned int *pitch); + /** + * This operator maps the buffer into the current process virtual memory + * space, and returns the virtual address. If failed, it returns NULL. + * + * \note The driver must implement this operator. + */ uint8_t* (* map_buffer) (DriDriver *driver, uint32_t buffer_id); + + /** + * This operator un-maps a buffer. + * + * \note The driver must implement this operator. + */ void (* unmap_buffer) (DriDriver *driver, uint32_t buffer_id); +#if 0 uint8_t * (* begin_flush) (DriDriver *driver, uint32_t buffer_id); void (* end_flush) (DriDriver *driver, uint32_t buffer_id); +#endif + /** + * This operator destroies a buffer. + * + * \note The driver must implement this operator. + */ void (* destroy_buffer) (DriDriver *driver, uint32_t buffer_id); + + /** + * This operator clears the specific rectangle area of a buffer + * with the specific pixel value. If succeed, it returns 0. + * + * \note If this operator is set as NULL, the driver does not support + * hardware accelerated clear operation. + */ + int (* clear_buffer) (DriDriver *driver, + uint32_t buffer_id, const GAL_Rect* rc, uint32_t pixel_value); + + /** + * This operator checks whether a hardware accelerated blit + * can be done between the source buffer and the destination buffer. + * If succeed, it returns 0. + * + * \note If this operator is set as NULL, it will be supposed that + * the driver does not support any hardware accelerated blit operation. + */ + int (* check_blit) (DriDriver *driver, + uint32_t src_id, uint32_t dst_id); + + /** + * This operator copies bits from a source buffer to a destination buffer. + * + * \note If this operator is set as NULL, the driver does not support + * hardware accelerated copy blit. + */ + int (* copy_blit) (DriDriver *driver, + uint32_t src_id, const GAL_Rect* src_rc, + uint32_t dst_id, const GAL_Rect* dst_rc); + + /** + * This operator blits pixles from a source buffer with the source alpha value + * specified to a destination buffer. + * + * \note If this operator is set as NULL, the driver does not support + * hardware accelerated blit with alpha. + */ + int (* alpha_blit) (DriDriver *driver, + uint32_t src_id, const GAL_Rect* src_rc, + uint32_t dst_id, const GAL_Rect* dst_rc, uint8_t alpha); + + /** + * This operator blits pixles from a source buffer to a destination buffer, + * but skipping the pixel value specified by \a color_key. + * + * \note If this operator is set as NULL, the driver does not support + * hardware accelerated blit with color key. + */ + int (* key_blit) (DriDriver *driver, + uint32_t src_id, const GAL_Rect* src_rc, + uint32_t dst_id, const GAL_Rect* dst_rc, uint32_t color_key); + + /** + * This operator blits pixles from a source buffer with the source alpha value + * specified to a destination buffer, but skipping the pixel value specified. + * + * \note If this operator is set as NULL, the driver does not support + * hardware accelerated blit with alpha and color key. + */ + int (* alpha_key_blit) (DriDriver *driver, + uint32_t src_id, const GAL_Rect* src_rc, + uint32_t dst_id, const GAL_Rect* dst_rc, + uint8_t alpha, uint32_t color_key); + } DriDriverOps; /* implement this stub to return the DRI driver operators */ diff --git a/src/newgal/dri/drivideo.c b/src/newgal/dri/drivideo.c index dbac64a3..89cb1797 100644 --- a/src/newgal/dri/drivideo.c +++ b/src/newgal/dri/drivideo.c @@ -333,11 +333,32 @@ static GAL_VideoDevice *DRI_CreateDevice(int devindex) device->RequestHWSurface = NULL; #endif device->AllocHWSurface = DRI_AllocHWSurface_Accl; - device->CheckHWBlit = DRI_CheckHWBlit_Accl; - device->FillHWRect = DRI_FillHWRect_Accl; - device->SetHWColorKey = DRI_SetHWColorKey_Accl; - device->SetHWAlpha = DRI_SetHWAlpha_Accl; device->FreeHWSurface = DRI_FreeHWSurface_Accl; + + if (device->hidden->driver_ops->clear_buffer) { + device->info.blit_fill = 1; + device->FillHWRect = DRI_FillHWRect_Accl; + } + else + device->FillHWRect = NULL; + + if (device->hidden->driver_ops->check_blit) { + device->CheckHWBlit = DRI_CheckHWBlit_Accl; + device->SetHWColorKey = DRI_SetHWColorKey_Accl; + device->SetHWAlpha = DRI_SetHWAlpha_Accl; + + device->info.blit_hw = 1; + if (device->hidden->driver_ops->alpha_blit) + device->info.blit_hw_A = 1; + if (device->hidden->driver_ops->key_blit) + device->info.blit_hw_CC = 1; + } + else { + device->CheckHWBlit = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + } + device->Suspend = DRI_Suspend; device->Resume = DRI_Resume; } @@ -910,7 +931,7 @@ static GAL_Surface *DRI_SetVideoMode_Accl(_THIS, GAL_Surface *current, _DBG_PRINTF("NEWGAL>DRM>ACCL: real screen mode: %dx%d-%dbpp\n", width, height, bpp); - current->flags = flags & GAL_FULLSCREEN; + current->flags = (GAL_FULLSCREEN | GAL_HWSURFACE); current->w = width; current->h = height; current->pitch = this->hidden->pitch; @@ -941,22 +962,128 @@ error: static int DRI_AllocHWSurface_Accl(_THIS, GAL_Surface *surface) { + DriVideoData* vdata = this->hidden; + unsigned int pitch; + uint32_t buff_id = 0; + + // TODO: handle pixel format + buff_id = vdata->driver_ops->create_buffer(vdata->driver, 24, 32, + surface->w, surface->h, &pitch); + if (buff_id == 0) { + return -1; + } + + surface->pixels = vdata->driver_ops->map_buffer(vdata->driver, buff_id); + if (surface->pixels == NULL) { + _ERR_PRINTF ("NEWGAL>DRM>ACCL: cannot map hardware buffer: %m\n"); + goto error; + } + + surface->flags |= GAL_HWSURFACE; + surface->pitch = pitch; + surface->hwdata = (struct private_hwdata *)(uintptr_t)buff_id; return 0; + +error: + if (buff_id) + vdata->driver_ops->destroy_buffer(vdata->driver, buff_id); + + return -1; } static void DRI_FreeHWSurface_Accl(_THIS, GAL_Surface *surface) { + DriVideoData* vdata = this->hidden; + uint32_t buff_id = (uint32_t)(uintptr_t)surface->hwdata; + + if (buff_id) { + vdata->driver_ops->unmap_buffer(vdata->driver, buff_id); + vdata->driver_ops->destroy_buffer(vdata->driver, buff_id); + } + + surface->pixels = NULL; + surface->hwdata = NULL; +} + +static int DRI_HWBlit(GAL_Surface *src, GAL_Rect *src_rc, + GAL_Surface *dst, GAL_Rect *dst_rc) +{ + GAL_VideoDevice *this = current_video; + DriVideoData* vdata = this->hidden; + uint32_t src_id = (uint32_t)(uintptr_t)src->hwdata; + uint32_t dst_id = (uint32_t)(uintptr_t)dst->hwdata; + + if ((src->flags & GAL_SRCALPHA) == GAL_SRCALPHA && + (src->flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY) { + return vdata->driver_ops->alpha_key_blit(vdata->driver, + src_id, src_rc, dst_id, dst_rc, + src->format->alpha, src->format->colorkey); + } + else if ((src->flags & GAL_SRCALPHA) == GAL_SRCALPHA) { + return vdata->driver_ops->alpha_blit(vdata->driver, + src_id, src_rc, dst_id, dst_rc, + src->format->alpha); + } + else if ((src->flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY) { + return vdata->driver_ops->key_blit(vdata->driver, + src_id, src_rc, dst_id, dst_rc, + src->format->colorkey); + } + else { + return vdata->driver_ops->copy_blit(vdata->driver, + src_id, src_rc, dst_id, dst_rc); + } + + return 0; } static int DRI_CheckHWBlit_Accl(_THIS, GAL_Surface *src, GAL_Surface *dst) { - return 0; + DriVideoData* vdata = this->hidden; + uint32_t src_id = (uint32_t)(uintptr_t)src->hwdata; + uint32_t dst_id = (uint32_t)(uintptr_t)dst->hwdata; + int accelerated; + + /* Set initial acceleration on */ + src->flags |= GAL_HWACCEL; + + /* Set the surface attributes */ + if ((src->flags & GAL_SRCALPHA) == GAL_SRCALPHA && + (src->flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY && + (vdata->driver_ops->alpha_key_blit == NULL)) { + src->flags &= ~GAL_HWACCEL; + } + else if ((src->flags & GAL_SRCALPHA) == GAL_SRCALPHA && + (vdata->driver_ops->alpha_blit == NULL)) { + src->flags &= ~GAL_HWACCEL; + } + else if ((src->flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY && + (vdata->driver_ops->key_blit == NULL)) { + src->flags &= ~GAL_HWACCEL; + } + else if (vdata->driver_ops->copy_blit == NULL) { + src->flags &= ~GAL_HWACCEL; + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & GAL_HWACCEL); + if (accelerated && + vdata->driver_ops->check_blit(vdata->driver, src_id, dst_id) == 0) { + src->map->hw_blit = DRI_HWBlit; + } + else + accelerated = 0; + + return accelerated; } static int DRI_FillHWRect_Accl(_THIS, GAL_Surface *dst, GAL_Rect *rect, Uint32 color) { - return 0; + DriVideoData* vdata = this->hidden; + uint32_t dst_id = (uint32_t)(uintptr_t)dst->hwdata; + + return vdata->driver_ops->clear_buffer(vdata->driver, dst_id, rect, color); } static int DRI_SetHWColorKey_Accl(_THIS, GAL_Surface *surface, Uint32 key)