2bffb1ae92f0b932eccaf4bda790c02964c55db3
[tpg/acess2.git] / KernelLand / Kernel / drvutil_video.c
1 /*
2  * Acess2 Kernel
3  * - By John Hodge
4  *
5  * drvutil.c
6  * - Video Driver Helper Functions
7  */
8 #define DEBUG   0
9 #include <acess.h>
10 #include <api_drv_video.h>
11
12 // === TYPES ===
13
14 // === PROTOTYPES ===
15 //int   DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length, tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers);
16 //size_t        DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, void *Src);
17 //void  DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bitmap);
18 //void  DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y);
19 void    DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf);
20 //void  DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf);
21 void    DrvUtil_Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);
22 void    DrvUtil_Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H);
23
24 // === GLOBALS ===
25 tDrvUtil_Video_2DHandlers       gDrvUtil_Stub_2DFunctions = {
26         NULL,
27         DrvUtil_Video_2D_Fill,
28         DrvUtil_Video_2D_Blit
29 };
30 tVideo_IOCtl_Bitmap     gDrvUtil_TextModeCursor = {
31         8, 16,
32         0, 0,
33         {
34                 0, 0, 0         , 0, 0, 0, 0, 0,
35                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
36                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
37                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
38                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
39                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
40                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
41                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
42                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
43                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
44                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
45                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
46                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
47                 0,-1, 0xFF000000, 0, 0, 0, 0, 0,
48                 0, 0, 0         , 0, 0, 0, 0, 0,
49                 0, 0, 0         , 0, 0, 0, 0, 0
50         }
51 };
52
53 // === CODE ===
54 // --- Video Driver Helpers ---
55 int DrvUtil_Video_2DStream(void *Ent, const void *Buffer, int Length,
56         tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers)
57 {
58         const Uint8     *stream = Buffer;
59          int    rem = Length;
60          int    op;
61
62         Uint16  tmp[6];
63
64         while( rem )
65         {
66                 rem --;
67                 op = *stream;
68                 stream ++;
69                 
70                 if(op > NUM_VIDEO_2DOPS) {
71                         Log_Warning("DrvUtil",
72                                 "DrvUtil_Video_2DStream: Unknown operation %i",
73                                 op);
74                         return Length-rem;
75                 }
76                 
77                 if(op*sizeof(void*) > SizeofHandlers) {
78                         Log_Warning("DrvUtil",
79                                 "DrvUtil_Video_2DStream: Driver does not support op %i",
80                                 op);
81                         return Length-rem;
82                 }
83                 
84                 switch(op)
85                 {
86                 case VIDEO_2DOP_NOP:    break;
87                 
88                 case VIDEO_2DOP_FILL:
89                         if(rem < 12)    return Length-rem;
90                         memcpy(tmp, stream, 6*2);
91                         
92                         if(!Handlers->Fill) {
93                                 Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
94                                         " does not support VIDEO_2DOP_FILL");
95                                 return Length-rem;
96                         }
97                         
98                         Handlers->Fill(
99                                 Ent, 
100                                 tmp[0], tmp[1], tmp[2], tmp[3],
101                                 tmp[4] | ((Uint32)tmp[5] << 16)
102                                 );
103                         
104                         rem -= 12;
105                         stream += 12;
106                         break;
107                 
108                 case VIDEO_2DOP_BLIT:
109                         if(rem < 12)    return Length-rem;
110                         memcpy(tmp, stream, 6*2);
111                         
112                         if(!Handlers->Blit) {
113                                 Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
114                                         " does not support VIDEO_2DOP_BLIT");
115                                 return Length-rem;
116                         }
117                         
118                         Handlers->Blit(
119                                 Ent,
120                                 tmp[0], tmp[1], tmp[2], tmp[3],
121                                 tmp[4], tmp[5]
122                                 );
123                         
124                         rem -= 12;
125                         stream += 12;
126                         break;
127                 
128                 }
129         }
130         return 0;
131 }
132
133 int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, const void *Buffer)
134 {
135         Uint8   *dest;
136         const Uint32    *src = Buffer;
137          int    csr_x, csr_y;
138          int    x, y;
139          int    bytes_per_px = (FBInfo->Depth + 7) / 8;
140         size_t  ofs;
141         ENTER("pFBInfo xOffset xLength pBuffer",
142                 FBInfo, Offset, Length, Buffer);
143
144         csr_x = FBInfo->CursorX;
145         csr_y = FBInfo->CursorY;
146
147         if( FBInfo->BackBuffer )
148                 dest = FBInfo->BackBuffer;
149         else
150                 dest = FBInfo->Framebuffer;
151         
152         DrvUtil_Video_RemoveCursor(FBInfo);
153
154         switch( FBInfo->BufferFormat )
155         {
156         case VIDEO_BUFFMT_TEXT:
157                 {
158                 const tVT_Char  *chars = Buffer;
159                  int    widthInChars = FBInfo->Width/giVT_CharWidth;
160                  int    heightInChars = FBInfo->Height/giVT_CharHeight;
161                  int    i;
162         
163                 LOG("bytes_per_px = %i", bytes_per_px);
164                 LOG("widthInChars = %i, heightInChars = %i", widthInChars, heightInChars);
165         
166                 Length /= sizeof(tVT_Char);     Offset /= sizeof(tVT_Char);
167                 
168                 x = Offset % widthInChars;      y = Offset / widthInChars;
169                 LOG("x = %i, y = %i", x, y);    
170         
171                 // Sanity Check
172                 if(Offset > heightInChars * widthInChars)       LEAVE_RET('i', 0);
173                 if(y >= heightInChars)  LEAVE_RET('i', 0);
174                 
175                 if( Offset + Length > heightInChars*widthInChars )
176                 {
177                         Length = heightInChars*widthInChars - Offset;
178                 }
179                 
180                 LOG("dest = %p", dest);
181                 ofs = y * giVT_CharHeight * FBInfo->Pitch;
182                 dest += ofs;
183                 
184                 for( i = 0; i < Length; i++ )
185                 {
186                         if( y >= heightInChars )
187                         {
188                                 Log_Notice("DrvUtil", "Stopped at %i", i);
189                                 break;
190                         }
191
192                         VT_Font_Render(
193                                 chars->Ch,
194                                 dest + x*giVT_CharWidth*bytes_per_px, FBInfo->Depth, FBInfo->Pitch,
195                                 VT_Colour12toN(chars->BGCol, FBInfo->Depth),
196                                 VT_Colour12toN(chars->FGCol, FBInfo->Depth)
197                                 );
198                         
199                         chars ++;
200                         x ++;
201                         if( x >= widthInChars )
202                         {
203                                 x = 0;
204                                 y ++;
205                                 dest += FBInfo->Pitch*giVT_CharHeight;
206                                 LOG("dest = %p", dest);
207                         }
208                 }
209                 if( x > 0 ) 
210                         dest += FBInfo->Pitch*giVT_CharHeight;
211                 Length = i * sizeof(tVT_Char);
212                 
213                 break; }
214         
215         case VIDEO_BUFFMT_FRAMEBUFFER:
216                 if(FBInfo->Width*FBInfo->Height*4 < Offset+Length)
217                 {
218                         Log_Warning("DrvUtil", "DrvUtil_Video_WriteLFB - Framebuffer Overflow");
219                         return 0;
220                 }
221                 
222                 switch(FBInfo->Depth)
223                 {
224                 case 15:
225                 case 16:
226                         Log_Warning("DrvUtil", "TODO: Support 15/16 bpp modes in LFB write");
227                         dest = NULL;
228                         break;
229                 case 24:
230                         x = Offset % FBInfo->Width;
231                         y = Offset / FBInfo->Width;
232                         ofs = y*FBInfo->Pitch;
233                         dest += ofs;
234                         for( ; Length >= 4; Length -= 4 )
235                         {
236                                 dest[x*3+0] = *src & 0xFF;
237                                 dest[x*3+1] = (*src >> 8) & 0xFF;
238                                 dest[x*3+2] = (*src >> 16) & 0xFF;
239                                 x ++;
240                                 if(x == FBInfo->Width) {
241                                         dest += FBInfo->Pitch;
242                                         x = 0;
243                                 }
244                         }
245                         break;
246                 case 32:
247                         // Copy to Frambuffer
248                         if( FBInfo->Pitch != FBInfo->Width*4 )
249                         {
250                                 Uint32  *px;
251                                 // Pitch isn't 4*Width
252                                 x = Offset % FBInfo->Width;
253                                 y = Offset / FBInfo->Height;
254                                 
255                                 ofs = y*FBInfo->Pitch;
256                                 dest += ofs;
257                                 px = (void*)dest;
258
259                                 for( ; Length >= 4; Length -= 4 )
260                                 {
261                                         px[x++] = *src ++;
262                                         if( x == FBInfo->Width ) {
263                                                 x = 0;
264                                                 dest += FBInfo->Pitch;
265                                                 px = (void*)dest;
266                                         }
267                                 }
268                                 if( x > 0 ) {
269                                         dest += FBInfo->Pitch;
270                                 }
271                         }
272                         else
273                         {
274                                 ofs = Offset;
275                                 dest += ofs;
276                                 memcpy(dest, Buffer, Length);
277                                 dest += Length;
278                         }
279                         break;
280                 default:
281                         Log_Warning("DrvUtil", "DrvUtil_Video_WriteLFB - Unknown bit depth %i", FBInfo->Depth);
282                         dest = NULL;
283                         break;
284                 }
285                 break;
286         
287         case VIDEO_BUFFMT_2DSTREAM:
288                 Length = DrvUtil_Video_2DStream(
289                         FBInfo, Buffer, Length,
290                         &gDrvUtil_Stub_2DFunctions, sizeof(gDrvUtil_Stub_2DFunctions)
291                         );
292                 dest = NULL;
293                 break;
294         
295         default:
296                 LEAVE('i', -1);
297                 return -1;
298         }
299         if( FBInfo->BackBuffer && dest ) {
300                 void    *_dst = (char*)FBInfo->Framebuffer + ofs;
301                 void    *_src = (char*)FBInfo->BackBuffer + ofs;
302                 size_t  len = ((tVAddr)dest - (tVAddr)FBInfo->BackBuffer) - ofs;
303         //      Log_Debug("DrvUtil", "Copy from BB %p to FB %p 0x%x bytes", _src, _dst, len);
304                 memcpy(_dst, _src, len);
305         }
306
307         DrvUtil_Video_DrawCursor(FBInfo, csr_x, csr_y);
308
309         LEAVE('x', Length);
310         return Length;
311 }
312
313 int DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bitmap)
314 {
315          int    csrX = Buf->CursorX, csrY = Buf->CursorY;
316         size_t  size;
317
318         ENTER("pBuf pBitmap", Buf, Bitmap);
319
320         // Clear old bitmap
321         if( Buf->CursorBitmap )
322         {
323                 LOG("Clearing old cursor");
324                 DrvUtil_Video_RemoveCursor(Buf);
325                 if( !Bitmap || Bitmap->W != Buf->CursorBitmap->W || Bitmap->H != Buf->CursorBitmap->H )
326                 {
327                         free( Buf->CursorSaveBuf );
328                         Buf->CursorSaveBuf = NULL;
329                 }
330                 if( Buf->CursorBitmap != &gDrvUtil_TextModeCursor)
331                         free(Buf->CursorBitmap);
332                 Buf->CursorBitmap = NULL;
333         }
334         
335         // If the new bitmap is null, disable drawing
336         if( !Bitmap )
337         {
338                 Buf->CursorX = -1;
339                 Buf->CursorY = -1;
340                 LEAVE('i', 0);
341                 return 0;
342         }
343
344         // Sanity check the bitmap
345         LOG("Sanity checking plox");
346         if( !CheckMem(Bitmap, sizeof(*Bitmap)) || !CheckMem(Bitmap->Data, Bitmap->W*Bitmap->H*sizeof(Uint32)) )
347         {
348                 Log_Warning("DrvUtil", "DrvUtil_Video_SetCursor: Bitmap (%p) is in invalid memory", Bitmap);
349                 errno = -EINVAL;
350                 LEAVE('i', -1);
351                 return -1;
352         }
353         ASSERTCR(Bitmap->W, >, 0, -1);
354         ASSERTCR(Bitmap->H, >, 0, -1);
355         ASSERTCR(Bitmap->XOfs, <, Bitmap->W, -1);
356         ASSERTCR(Bitmap->XOfs, >, -Bitmap->W, -1);
357         ASSERTCR(Bitmap->YOfs, <, Bitmap->H, -1);
358         ASSERTCR(Bitmap->YOfs, >, -Bitmap->H, -1);
359
360         // Don't take a copy of the DrvUtil provided cursor
361         if( Bitmap == &gDrvUtil_TextModeCursor )
362         {
363                 LOG("No copy (provided cursor)");
364                 Buf->CursorBitmap = Bitmap;
365         }
366         else
367         {
368                 LOG("Make copy");
369                 size = sizeof(tVideo_IOCtl_Bitmap) + Bitmap->W*Bitmap->H*4;
370                 
371                 // Take a copy
372                 Buf->CursorBitmap = malloc( size );
373                 memcpy(Buf->CursorBitmap, Bitmap, size);
374         }
375         
376         // Restore cursor position
377         LOG("Drawing");
378         DrvUtil_Video_DrawCursor(Buf, csrX, csrY);
379         LEAVE('i', 0);
380         return 0;
381 }
382
383 void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y)
384 {
385          int    render_ox=0, render_oy=0, render_w, render_h;
386
387         ENTER("pBuf iX iY", Buf, X, Y);
388         DrvUtil_Video_RemoveCursor(Buf);
389
390         // X < 0 disables the cursor
391         if( X < 0 ) {
392                 Buf->CursorX = -1;
393                 LEAVE('-');
394                 return ;
395         }
396
397         // Sanity checking
398         if( X < 0 || Y < 0 || X >= Buf->Width || Y >= Buf->Height ) {
399                 LEAVE('-');
400                 return ;
401         }
402
403         // Ensure the cursor is enabled
404         if( !Buf->CursorBitmap ) {
405                 LEAVE('-');
406                 return ;
407         }
408         
409         // Save cursor position (for changing the bitmap)
410         Buf->CursorX = X;       Buf->CursorY = Y;
411         // Apply cursor's center offset
412         X -= Buf->CursorBitmap->XOfs;
413         Y -= Buf->CursorBitmap->YOfs;
414         
415         // Get the width of the cursor on screen (clipping to right/bottom edges)
416         ASSERTC(Buf->Width, >, 0);
417         ASSERTC(Buf->Height, >, 0);
418         ASSERTC(Buf->CursorBitmap->W, >, 0);
419         ASSERTC(Buf->CursorBitmap->H, >, 0);
420         
421         render_w = MIN(Buf->Width  - X, Buf->CursorBitmap->W);
422         render_h = MIN(Buf->Height - Y, Buf->CursorBitmap->H);
423         //render_w = X > Buf->Width  - Buf->CursorBitmap->W ? Buf->Width  - X : Buf->CursorBitmap->W;
424         //render_h = Y > Buf->Height - Buf->CursorBitmap->H ? Buf->Height - Y : Buf->CursorBitmap->H;
425
426         ASSERTC(render_w, >=, 0);
427         ASSERTC(render_h, >=, 0);
428
429         // Clipp to left/top edges
430         if(X < 0) {     render_ox = -X; X = 0;  }
431         if(Y < 0) {     render_oy = -Y; Y = 0;  }
432
433         // Save values
434         Buf->CursorRenderW = render_w;  Buf->CursorRenderH = render_h;
435         Buf->CursorDestX   = X;         Buf->CursorDestY = Y;
436         Buf->CursorReadX   = render_ox; Buf->CursorReadY = render_oy;
437
438         LOG("%ix%i at %i,%i offset %i,%i",
439                 render_w, render_h, X, Y, render_ox, render_oy);
440
441         // Call render routine
442         DrvUtil_Video_RenderCursor(Buf);
443         LEAVE('-');
444 }
445
446 void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf)
447 {
448          int    src_x = Buf->CursorReadX, src_y = Buf->CursorReadY;
449          int    render_w = Buf->CursorRenderW, render_h = Buf->CursorRenderH;
450          int    dest_x = Buf->CursorDestX, dest_y = Buf->CursorDestY;
451          int    bytes_per_px = (Buf->Depth + 7) / 8;
452          int    save_pitch = Buf->CursorBitmap->W * bytes_per_px;
453         void    *dest;
454         Uint32  *src;
455          int    x, y;
456
457         dest = (Uint8*)Buf->Framebuffer + dest_y*Buf->Pitch + dest_x*bytes_per_px;
458         src = Buf->CursorBitmap->Data + src_y * Buf->CursorBitmap->W + src_x;
459         
460         LOG("dest = %p, src = %p", dest, src);
461
462         // Allocate save buffer if not already
463         if( !Buf->CursorSaveBuf )
464                 Buf->CursorSaveBuf = malloc( Buf->CursorBitmap->W*Buf->CursorBitmap->H*bytes_per_px );
465
466         ASSERTC(render_w, >=, 0);
467         ASSERTC(render_h, >=, 0);
468
469         LOG("Saving back");
470         // Save behind the cursor
471         for( y = 0; y < render_h; y ++ )
472                 memcpy(
473                         (Uint8*)Buf->CursorSaveBuf + y*save_pitch,
474                         (Uint8*)dest + y*Buf->Pitch,
475                         render_w*bytes_per_px
476                         );
477
478         // Draw the cursor
479         switch(Buf->Depth)
480         {
481         case 15:
482         case 16:
483                 //Log_Warning("DrvUtil", "TODO: Support 15/16 bpp modes in cursor draw");
484                 //Proc_PrintBacktrace();
485                 break;
486         case 24:
487                 LOG("24-bit render");
488                 for( y = 0; y < render_h; y ++ )
489                 {
490                         Uint8   *px;
491                         px = dest;
492                         for(x = 0; x < render_w; x ++, px += 3)
493                         {
494                                 Uint32  value = src[x];
495                                 // TODO: Should I implement alpha blending?
496                                 if(value & 0xFF000000)
497                                 {
498                                         px[0] = value & 0xFF;
499                                         px[1] = (value >> 8) & 0xFF;
500                                         px[2] = (value >> 16) & 0xFF;
501                                 }
502                                 else
503                                         ;
504                         }
505                         src += Buf->CursorBitmap->W;
506                         dest = (Uint8*)dest + Buf->Pitch;
507                 }
508                 break;
509         case 32:
510                 LOG("32-bit render");
511                 for( y = 0; y < render_h; y ++ )
512                 {
513                         Uint32  *px;
514                         px = dest;
515                         for(x = 0; x < render_w; x ++, px ++)
516                         {
517                                 Uint32  value = src[x];
518                                 // TODO: Should I implement alpha blending?
519                                 if(value & 0xFF000000)
520                                         *px = value;
521                                 else
522                                         ;       // NOP, completely transparent
523                         }
524                         LOG("row %i/%i (%p-%P) done", y+1, render_h, dest, MM_GetPhysAddr(dest));
525                         src += Buf->CursorBitmap->W;
526                         dest = (Uint8*)dest + Buf->Pitch;
527                 }
528                 break;
529         default:
530                 Log_Error("DrvUtil", "RenderCursor - Unknown bit depth %i", Buf->Depth);
531                 Buf->CursorX = -1;
532                 break;
533         }
534 }
535
536 void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf)
537 {
538          int    bytes_per_px = (Buf->Depth + 7) / 8;
539
540         // Just a little sanity
541         if( !Buf->CursorBitmap || Buf->CursorX == -1 )  return ;
542         if( !Buf->CursorSaveBuf )       return ;
543
544 //      Debug("DrvUtil_Video_RemoveCursor: (Buf=%p) dest_x=%i, dest_y=%i", Buf, Buf->CursorDestX, Buf->CursorDestY);
545
546         // Set up
547         size_t  save_pitch = Buf->CursorBitmap->W * bytes_per_px;
548         Uint8   *dst = (Uint8*)Buf->Framebuffer + Buf->CursorDestY * Buf->Pitch + Buf->CursorDestX*bytes_per_px;
549         const Uint8     *src = Buf->CursorSaveBuf;
550
551         ASSERT(Buf->Framebuffer);
552         ASSERT(src);
553         ASSERT(CheckMem(dst, Buf->CursorRenderH*Buf->Pitch));
554         ASSERT(CheckMem(src, Buf->CursorRenderH*save_pitch));
555
556         // Copy each line back
557         for( int y = 0; y < Buf->CursorRenderH; y ++ )
558         {
559                 memcpy( dst, src, Buf->CursorRenderW * bytes_per_px );
560                 src += save_pitch;
561                 dst += Buf->Pitch;
562         }
563         
564         // Set the cursor as removed
565         Buf->CursorX = -1;
566 }
567
568 void DrvUtil_Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour)
569 {
570         tDrvUtil_Video_BufInfo  *FBInfo = Ent;
571
572         switch( FBInfo->Depth )
573         {
574         case 32: {
575                 // TODO: Be less hacky
576                 size_t  pitch = FBInfo->Pitch/4;
577                 size_t  ofs = Y*pitch + X;
578                 Uint32  *buf = (Uint32*)FBInfo->Framebuffer + ofs;
579                 Uint32  *cbuf = NULL;
580                 if( FBInfo->BackBuffer )
581                         cbuf = (Uint32*)FBInfo->BackBuffer + ofs;
582                 while( H -- )
583                 {
584                         Uint32 *line;
585                         line = buf;
586                         for(int i = W; i--; line++)
587                                 *line = Colour;
588                         buf += pitch;
589                         if( cbuf ) {
590                                 line = cbuf;
591                                 for(int i = W; i--; line++ )
592                                         *line = Colour;
593                                 cbuf += pitch;
594                         }
595                 }
596                 break; }
597         default:
598                 // TODO: Handle non-32bit modes
599                 Log_Warning("DrvUtil", "TODO: <32bpp _Fill");
600                 break;
601         }
602 }
603
604 void DrvUtil_Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H)
605 {
606         tDrvUtil_Video_BufInfo  *FBInfo = Ent;
607          int    scrnpitch = FBInfo->Pitch;
608          int    bytes_per_px = (FBInfo->Depth + 7) / 8;
609          int    dst = DstY*scrnpitch + DstX;
610          int    src = SrcY*scrnpitch + SrcX;
611          int    tmp;
612         Uint8   *framebuffer = FBInfo->Framebuffer;
613         Uint8   *backbuffer = FBInfo->BackBuffer;
614         Uint8   *sourcebuffer = (FBInfo->BackBuffer ? FBInfo->BackBuffer : FBInfo->Framebuffer);
615         
616         //Log("Vesa_2D_Blit: (Ent=%p, DstX=%i, DstY=%i, SrcX=%i, SrcY=%i, W=%i, H=%i)",
617         //      Ent, DstX, DstY, SrcX, SrcY, W, H);
618         
619         if(SrcX + W > FBInfo->Width)    W = FBInfo->Width - SrcX;
620         if(DstX + W > FBInfo->Width)    W = FBInfo->Width - DstX;
621         if(SrcY + H > FBInfo->Height)   H = FBInfo->Height - SrcY;
622         if(DstY + H > FBInfo->Height)   H = FBInfo->Height - DstY;
623         
624         //Debug("W = %i, H = %i", W, H);
625         
626         if(W == FBInfo->Width && FBInfo->Pitch == FBInfo->Width*bytes_per_px)
627         {
628                 memmove(framebuffer + dst, sourcebuffer + src, H*FBInfo->Pitch);
629                 if( backbuffer )
630                         memmove(backbuffer + dst, sourcebuffer + src, H*FBInfo->Pitch);
631         }
632         else if( dst > src )
633         {
634                 // Reverse copy
635                 dst += H*scrnpitch;
636                 src += H*scrnpitch;
637                 while( H -- )
638                 {
639                         dst -= scrnpitch;
640                         src -= scrnpitch;
641                         tmp = W*bytes_per_px;
642                         for( tmp = W; tmp --; )
643                         {
644                                 size_t  src_o = src + tmp;
645                                 size_t  dst_o = src + tmp;
646                                 framebuffer[dst_o] = sourcebuffer[src_o];
647                                 if( backbuffer )
648                                         backbuffer[dst_o] = sourcebuffer[src_o];
649                         }
650                 }
651         }
652         else {
653                 // Normal copy is OK
654                 while( H -- )
655                 {
656                         memcpy(framebuffer + dst, sourcebuffer + src, W*bytes_per_px);
657                         if( backbuffer )
658                                 memcpy(backbuffer + dst, sourcebuffer + src, W*bytes_per_px);
659                         dst += scrnpitch;
660                         src += scrnpitch;
661                 }
662         }
663         //Log("Vesa_2D_Blit: RETURN");
664 }
665         
666

UCC git Repository :: git.ucc.asn.au