|
@@ -78,18 +78,20 @@ static __always_inline u16 efi_blt_col_to_vid16(struct efi_gop_pixel *blt)
|
|
|
}
|
|
|
|
|
|
static __always_inline efi_status_t gop_blt_int(struct efi_gop *this,
|
|
|
- struct efi_gop_pixel *buffer,
|
|
|
+ struct efi_gop_pixel *bufferp,
|
|
|
u32 operation, efi_uintn_t sx,
|
|
|
efi_uintn_t sy, efi_uintn_t dx,
|
|
|
efi_uintn_t dy,
|
|
|
efi_uintn_t width,
|
|
|
efi_uintn_t height,
|
|
|
- efi_uintn_t delta)
|
|
|
+ efi_uintn_t delta,
|
|
|
+ efi_uintn_t vid_bpp)
|
|
|
{
|
|
|
struct efi_gop_obj *gopobj = container_of(this, struct efi_gop_obj, ops);
|
|
|
- efi_uintn_t i, j, linelen;
|
|
|
+ efi_uintn_t i, j, linelen, slineoff = 0, dlineoff, swidth, dwidth;
|
|
|
u32 *fb32 = gopobj->fb;
|
|
|
u16 *fb16 = gopobj->fb;
|
|
|
+ struct efi_gop_pixel *buffer = __builtin_assume_aligned(bufferp, 4);
|
|
|
|
|
|
if (delta) {
|
|
|
/* Check for 4 byte alignment */
|
|
@@ -133,6 +135,37 @@ static __always_inline efi_status_t gop_blt_int(struct efi_gop *this,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
+ /* Calculate line width */
|
|
|
+ switch (operation) {
|
|
|
+ case EFI_BLT_BUFFER_TO_VIDEO:
|
|
|
+ swidth = linelen;
|
|
|
+ break;
|
|
|
+ case EFI_BLT_VIDEO_TO_BLT_BUFFER:
|
|
|
+ case EFI_BLT_VIDEO_TO_VIDEO:
|
|
|
+ swidth = gopobj->info.width;
|
|
|
+ if (!vid_bpp)
|
|
|
+ return EFI_UNSUPPORTED;
|
|
|
+ break;
|
|
|
+ case EFI_BLT_VIDEO_FILL:
|
|
|
+ swidth = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (operation) {
|
|
|
+ case EFI_BLT_BUFFER_TO_VIDEO:
|
|
|
+ case EFI_BLT_VIDEO_FILL:
|
|
|
+ case EFI_BLT_VIDEO_TO_VIDEO:
|
|
|
+ dwidth = gopobj->info.width;
|
|
|
+ if (!vid_bpp)
|
|
|
+ return EFI_UNSUPPORTED;
|
|
|
+ break;
|
|
|
+ case EFI_BLT_VIDEO_TO_BLT_BUFFER:
|
|
|
+ dwidth = linelen;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ slineoff = swidth * sy;
|
|
|
+ dlineoff = dwidth * dy;
|
|
|
for (i = 0; i < height; i++) {
|
|
|
for (j = 0; j < width; j++) {
|
|
|
struct efi_gop_pixel pix;
|
|
@@ -143,70 +176,65 @@ static __always_inline efi_status_t gop_blt_int(struct efi_gop *this,
|
|
|
pix = *buffer;
|
|
|
break;
|
|
|
case EFI_BLT_BUFFER_TO_VIDEO:
|
|
|
- pix = buffer[linelen * (i + sy) + j + sx];
|
|
|
+ pix = buffer[slineoff + j + sx];
|
|
|
break;
|
|
|
case EFI_BLT_VIDEO_TO_BLT_BUFFER:
|
|
|
case EFI_BLT_VIDEO_TO_VIDEO:
|
|
|
- switch (gopobj->bpix) {
|
|
|
-#ifdef CONFIG_DM_VIDEO
|
|
|
- case VIDEO_BPP32:
|
|
|
-#else
|
|
|
- case LCD_COLOR32:
|
|
|
-#endif
|
|
|
+ if (vid_bpp == 32)
|
|
|
pix = *(struct efi_gop_pixel *)&fb32[
|
|
|
- gopobj->info.width *
|
|
|
- (i + sy) + j + sx];
|
|
|
- break;
|
|
|
-#ifdef CONFIG_DM_VIDEO
|
|
|
- case VIDEO_BPP16:
|
|
|
-#else
|
|
|
- case LCD_COLOR16:
|
|
|
-#endif
|
|
|
+ slineoff + j + sx];
|
|
|
+ else
|
|
|
pix = efi_vid16_to_blt_col(fb16[
|
|
|
- gopobj->info.width *
|
|
|
- (i + sy) + j + sx]);
|
|
|
- break;
|
|
|
- default:
|
|
|
- return EFI_UNSUPPORTED;
|
|
|
- }
|
|
|
+ slineoff + j + sx]);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
/* Write destination pixel */
|
|
|
switch (operation) {
|
|
|
case EFI_BLT_VIDEO_TO_BLT_BUFFER:
|
|
|
- buffer[linelen * (i + dy) + j + dx] = pix;
|
|
|
+ buffer[dlineoff + j + dx] = pix;
|
|
|
break;
|
|
|
case EFI_BLT_BUFFER_TO_VIDEO:
|
|
|
case EFI_BLT_VIDEO_FILL:
|
|
|
case EFI_BLT_VIDEO_TO_VIDEO:
|
|
|
- switch (gopobj->bpix) {
|
|
|
+ if (vid_bpp == 32)
|
|
|
+ fb32[dlineoff + j + dx] = *(u32 *)&pix;
|
|
|
+ else
|
|
|
+ fb16[dlineoff + j + dx] =
|
|
|
+ efi_blt_col_to_vid16(&pix);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ slineoff += swidth;
|
|
|
+ dlineoff += dwidth;
|
|
|
+ }
|
|
|
+
|
|
|
+ return EFI_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+static efi_uintn_t gop_get_bpp(struct efi_gop *this)
|
|
|
+{
|
|
|
+ struct efi_gop_obj *gopobj = container_of(this, struct efi_gop_obj, ops);
|
|
|
+ efi_uintn_t vid_bpp = 0;
|
|
|
+
|
|
|
+ switch (gopobj->bpix) {
|
|
|
#ifdef CONFIG_DM_VIDEO
|
|
|
- case VIDEO_BPP32:
|
|
|
+ case VIDEO_BPP32:
|
|
|
#else
|
|
|
- case LCD_COLOR32:
|
|
|
+ case LCD_COLOR32:
|
|
|
#endif
|
|
|
- fb32[gopobj->info.width *
|
|
|
- (i + dy) + j + dx] = *(u32 *)&pix;
|
|
|
- break;
|
|
|
+ vid_bpp = 32;
|
|
|
+ break;
|
|
|
#ifdef CONFIG_DM_VIDEO
|
|
|
- case VIDEO_BPP16:
|
|
|
+ case VIDEO_BPP16:
|
|
|
#else
|
|
|
- case LCD_COLOR16:
|
|
|
+ case LCD_COLOR16:
|
|
|
#endif
|
|
|
- fb16[gopobj->info.width *
|
|
|
- (i + dy) + j + dx] =
|
|
|
- efi_blt_col_to_vid16(&pix);
|
|
|
- break;
|
|
|
- default:
|
|
|
- return EFI_UNSUPPORTED;
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
+ vid_bpp = 16;
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
- return EFI_SUCCESS;
|
|
|
+ return vid_bpp;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -223,21 +251,33 @@ static efi_status_t gop_blt_video_fill(struct efi_gop *this,
|
|
|
u32 foo, efi_uintn_t sx,
|
|
|
efi_uintn_t sy, efi_uintn_t dx,
|
|
|
efi_uintn_t dy, efi_uintn_t width,
|
|
|
- efi_uintn_t height, efi_uintn_t delta)
|
|
|
+ efi_uintn_t height, efi_uintn_t delta,
|
|
|
+ efi_uintn_t vid_bpp)
|
|
|
{
|
|
|
return gop_blt_int(this, buffer, EFI_BLT_VIDEO_FILL, sx, sy, dx,
|
|
|
- dy, width, height, delta);
|
|
|
+ dy, width, height, delta, vid_bpp);
|
|
|
}
|
|
|
|
|
|
-static efi_status_t gop_blt_buf_to_vid(struct efi_gop *this,
|
|
|
- struct efi_gop_pixel *buffer,
|
|
|
- u32 foo, efi_uintn_t sx,
|
|
|
- efi_uintn_t sy, efi_uintn_t dx,
|
|
|
- efi_uintn_t dy, efi_uintn_t width,
|
|
|
- efi_uintn_t height, efi_uintn_t delta)
|
|
|
+static efi_status_t gop_blt_buf_to_vid16(struct efi_gop *this,
|
|
|
+ struct efi_gop_pixel *buffer,
|
|
|
+ u32 foo, efi_uintn_t sx,
|
|
|
+ efi_uintn_t sy, efi_uintn_t dx,
|
|
|
+ efi_uintn_t dy, efi_uintn_t width,
|
|
|
+ efi_uintn_t height, efi_uintn_t delta)
|
|
|
{
|
|
|
return gop_blt_int(this, buffer, EFI_BLT_BUFFER_TO_VIDEO, sx, sy, dx,
|
|
|
- dy, width, height, delta);
|
|
|
+ dy, width, height, delta, 16);
|
|
|
+}
|
|
|
+
|
|
|
+static efi_status_t gop_blt_buf_to_vid32(struct efi_gop *this,
|
|
|
+ struct efi_gop_pixel *buffer,
|
|
|
+ u32 foo, efi_uintn_t sx,
|
|
|
+ efi_uintn_t sy, efi_uintn_t dx,
|
|
|
+ efi_uintn_t dy, efi_uintn_t width,
|
|
|
+ efi_uintn_t height, efi_uintn_t delta)
|
|
|
+{
|
|
|
+ return gop_blt_int(this, buffer, EFI_BLT_BUFFER_TO_VIDEO, sx, sy, dx,
|
|
|
+ dy, width, height, delta, 32);
|
|
|
}
|
|
|
|
|
|
static efi_status_t gop_blt_vid_to_vid(struct efi_gop *this,
|
|
@@ -245,10 +285,11 @@ static efi_status_t gop_blt_vid_to_vid(struct efi_gop *this,
|
|
|
u32 foo, efi_uintn_t sx,
|
|
|
efi_uintn_t sy, efi_uintn_t dx,
|
|
|
efi_uintn_t dy, efi_uintn_t width,
|
|
|
- efi_uintn_t height, efi_uintn_t delta)
|
|
|
+ efi_uintn_t height, efi_uintn_t delta,
|
|
|
+ efi_uintn_t vid_bpp)
|
|
|
{
|
|
|
return gop_blt_int(this, buffer, EFI_BLT_VIDEO_TO_VIDEO, sx, sy, dx,
|
|
|
- dy, width, height, delta);
|
|
|
+ dy, width, height, delta, vid_bpp);
|
|
|
}
|
|
|
|
|
|
static efi_status_t gop_blt_vid_to_buf(struct efi_gop *this,
|
|
@@ -256,10 +297,11 @@ static efi_status_t gop_blt_vid_to_buf(struct efi_gop *this,
|
|
|
u32 foo, efi_uintn_t sx,
|
|
|
efi_uintn_t sy, efi_uintn_t dx,
|
|
|
efi_uintn_t dy, efi_uintn_t width,
|
|
|
- efi_uintn_t height, efi_uintn_t delta)
|
|
|
+ efi_uintn_t height, efi_uintn_t delta,
|
|
|
+ efi_uintn_t vid_bpp)
|
|
|
{
|
|
|
return gop_blt_int(this, buffer, EFI_BLT_VIDEO_TO_BLT_BUFFER, sx, sy,
|
|
|
- dx, dy, width, height, delta);
|
|
|
+ dx, dy, width, height, delta, vid_bpp);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -287,27 +329,37 @@ efi_status_t EFIAPI gop_blt(struct efi_gop *this, struct efi_gop_pixel *buffer,
|
|
|
efi_uintn_t height, efi_uintn_t delta)
|
|
|
{
|
|
|
efi_status_t ret = EFI_INVALID_PARAMETER;
|
|
|
+ efi_uintn_t vid_bpp;
|
|
|
|
|
|
EFI_ENTRY("%p, %p, %u, %zu, %zu, %zu, %zu, %zu, %zu, %zu", this,
|
|
|
buffer, operation, sx, sy, dx, dy, width, height, delta);
|
|
|
|
|
|
+ vid_bpp = gop_get_bpp(this);
|
|
|
+
|
|
|
/* Allow for compiler optimization */
|
|
|
switch (operation) {
|
|
|
case EFI_BLT_VIDEO_FILL:
|
|
|
ret = gop_blt_video_fill(this, buffer, operation, sx, sy, dx,
|
|
|
- dy, width, height, delta);
|
|
|
+ dy, width, height, delta, vid_bpp);
|
|
|
break;
|
|
|
case EFI_BLT_BUFFER_TO_VIDEO:
|
|
|
- ret = gop_blt_buf_to_vid(this, buffer, operation, sx, sy, dx,
|
|
|
- dy, width, height, delta);
|
|
|
+ /* This needs to be super-fast, so duplicate for 16/32bpp */
|
|
|
+ if (vid_bpp == 32)
|
|
|
+ ret = gop_blt_buf_to_vid32(this, buffer, operation, sx,
|
|
|
+ sy, dx, dy, width, height,
|
|
|
+ delta);
|
|
|
+ else
|
|
|
+ ret = gop_blt_buf_to_vid16(this, buffer, operation, sx,
|
|
|
+ sy, dx, dy, width, height,
|
|
|
+ delta);
|
|
|
break;
|
|
|
case EFI_BLT_VIDEO_TO_VIDEO:
|
|
|
ret = gop_blt_vid_to_vid(this, buffer, operation, sx, sy, dx,
|
|
|
- dy, width, height, delta);
|
|
|
+ dy, width, height, delta, vid_bpp);
|
|
|
break;
|
|
|
case EFI_BLT_VIDEO_TO_BLT_BUFFER:
|
|
|
ret = gop_blt_vid_to_buf(this, buffer, operation, sx, sy, dx,
|
|
|
- dy, width, height, delta);
|
|
|
+ dy, width, height, delta, vid_bpp);
|
|
|
break;
|
|
|
default:
|
|
|
ret = EFI_UNSUPPORTED;
|