00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "Core/precomp.h"
00018
00019 #include "blit_alphamask_rle.h"
00020 #include "displaycard_generic.h"
00021 #include <API/Display/Display/surfaceprovider.h>
00022
00023 BltRLERow_AlphaMask<unsigned short> *CL_Blit_AlphaMask_RLE::bltrow_16bit = NULL;
00024 BltRLERow_AlphaMask<unsigned int> *CL_Blit_AlphaMask_RLE::bltrow_32bit = NULL;
00025
00026 CL_Blit_AlphaMask_RLE::CL_Blit_AlphaMask_RLE(
00027 CL_DisplayCard_Generic *card,
00028 CL_SurfaceProvider *provider,
00029 unsigned char *image_data,
00030 int image_bytes_pr_line,
00031 unsigned char *alpha_data,
00032 int alpha_bytes_pr_line)
00033 {
00034 m_num_lines = provider->get_height()*provider->get_num_frames();
00035 m_width = provider->get_width();
00036 m_height = provider->get_height();
00037
00038 m_lines = new unsigned char*[m_num_lines];
00039 m_alpha_lines = new unsigned char*[m_num_lines];
00040
00041 for (unsigned int y=0;y<m_num_lines;y++)
00042 {
00043 m_lines[y] = NULL;
00044 m_alpha_lines[y] = NULL;
00045
00046 make_line(
00047 card->get_target(),
00048 provider,
00049 y,
00050 &image_data[y*image_bytes_pr_line],
00051 &alpha_data[y*alpha_bytes_pr_line]);
00052 }
00053 }
00054
00055 CL_Blit_AlphaMask_RLE::~CL_Blit_AlphaMask_RLE()
00056 {
00057 for (unsigned int i=0;i<m_num_lines;i++)
00058 {
00059 delete[] m_lines[i];
00060 delete[] m_alpha_lines[i];
00061 }
00062 delete[] m_lines;
00063 delete[] m_alpha_lines;
00064 }
00065
00066 void CL_Blit_AlphaMask_RLE::make_line(
00067 CL_Target *target,
00068 CL_SurfaceProvider *provider,
00069 int line_num,
00070 unsigned char *input_data,
00071 unsigned char *alpha_data)
00072 {
00073 int dest_bytes_pr_pixel = target->get_depth()/8;
00074 cl_assert((dest_bytes_pr_pixel == 2) || (dest_bytes_pr_pixel == 4));
00075
00076 unsigned char *data = new unsigned char[dest_bytes_pr_pixel*m_width*4];
00077
00078 int cur_state = CL_Blit_AlphaMask_RLE::cmd_skip;
00079 int cmd_pos = 0;
00080 int cmd_start = 0;
00081 unsigned short *cmd_set_size = NULL;
00082
00083 bool line_has_data = true;
00084
00085 CL_ColorMap colormap(target);
00086
00087 for (unsigned int x=0;x<m_width;x++)
00088 {
00089 if (alpha_data[x] != 0 &&
00090 alpha_data[x] != 255)
00091 {
00092 if (cur_state == CL_Blit_AlphaMask_RLE::cmd_skip)
00093 {
00094 unsigned short *data_ptr = (unsigned short *) (&data[cmd_pos]);
00095 *data_ptr = x-cmd_start;
00096 cmd_pos += 2;
00097
00098 cmd_start = x;
00099
00100 cmd_set_size = (unsigned short *) (&data[cmd_pos]);
00101 cmd_pos += 2;
00102
00103 cur_state = cmd_alpha;
00104 }
00105
00106 if (dest_bytes_pr_pixel == 2)
00107 {
00108 PixelConstructor_AlphaMask<unsigned short>::save_pixel(
00109 target,
00110 &colormap,
00111 input_data,
00112 &data[cmd_pos],
00113 alpha_data[x],
00114 x,
00115 &cmd_pos);
00116 }
00117 else
00118 {
00119 PixelConstructor_AlphaMask<unsigned int>::save_pixel(
00120 target,
00121 &colormap,
00122 input_data,
00123 &data[cmd_pos],
00124 alpha_data[x],
00125 x,
00126 &cmd_pos);
00127 }
00128 }
00129 else
00130 {
00131 if (cur_state == cmd_alpha)
00132 {
00133 *cmd_set_size = x - cmd_start;
00134 cmd_start = x;
00135
00136 cur_state = CL_Blit_AlphaMask_RLE::cmd_skip;
00137 }
00138 }
00139 }
00140 if (cur_state == CL_Blit_AlphaMask_RLE::cmd_skip)
00141 {
00142 if (cmd_start == 0) line_has_data = false;
00143
00144 unsigned short *data_ptr = (unsigned short *) &data[cmd_pos];
00145 *data_ptr = m_width-cmd_start;
00146 cmd_pos += 2;
00147 }
00148 else
00149 {
00150 *cmd_set_size = m_width - cmd_start;
00151 }
00152
00153 if (line_has_data)
00154 {
00155 m_lines[line_num] = new unsigned char[cmd_pos];
00156 memcpy(m_lines[line_num], data, cmd_pos);
00157
00158 int provider_width = provider->get_width();
00159 m_alpha_lines[line_num] = new unsigned char[provider_width];
00160 for (int i=0;i<provider_width;i++)
00161 {
00162 m_alpha_lines[line_num][i] = 255 - alpha_data[i];
00163 }
00164 }
00165 else
00166 {
00167 m_lines[line_num] = NULL;
00168 }
00169
00170 delete[] data;
00171 }
00172
00173 void CL_Blit_AlphaMask_RLE::check_16bit_rowblitter(CL_Target *target)
00174 {
00175 if (bltrow_16bit == NULL)
00176 {
00177 CL_ColorMap colormap(target);
00178
00179 unsigned short rmask = target->get_red_mask();
00180 unsigned short gmask = target->get_green_mask();
00181 unsigned short bmask = target->get_blue_mask();
00182
00183 if (target->is_video())
00184 {
00185 bltrow_16bit = new BLTRLERow_AlphaMask_Buffered<unsigned short>(
00186 rmask, gmask, bmask,
00187 colormap.m_red_start,
00188 colormap.m_green_start,
00189 colormap.m_blue_start,
00190 colormap.m_red_length,
00191 colormap.m_green_length,
00192 colormap.m_blue_length);
00193 }
00194 else
00195 {
00196 bltrow_16bit = new BLTRLERow_AlphaMask_Direct<unsigned short>(
00197 rmask, gmask, bmask,
00198 colormap.m_red_start,
00199 colormap.m_green_start,
00200 colormap.m_blue_start,
00201 colormap.m_red_length,
00202 colormap.m_green_length,
00203 colormap.m_blue_length);
00204 }
00205 }
00206 }
00207
00208 void CL_Blit_AlphaMask_RLE::check_32bit_rowblitter(CL_Target *target)
00209 {
00210 if (bltrow_32bit == NULL)
00211 {
00212 CL_ColorMap colormap(target);
00213
00214 unsigned int rmask = target->get_red_mask();
00215 unsigned int gmask = target->get_green_mask();
00216 unsigned int bmask = target->get_blue_mask();
00217
00218 if (target->is_video())
00219 {
00220 bltrow_32bit = new BLTRLERow_AlphaMask_Buffered<unsigned int>(
00221 rmask, gmask, bmask,
00222 colormap.m_red_start,
00223 colormap.m_green_start,
00224 colormap.m_blue_start,
00225 colormap.m_red_length,
00226 colormap.m_blue_length,
00227 colormap.m_green_length);
00228 }
00229 else
00230 {
00231 bltrow_32bit = new BLTRLERow_AlphaMask_Direct<unsigned int>(
00232 rmask, gmask, bmask,
00233 colormap.m_red_start,
00234 colormap.m_green_start,
00235 colormap.m_blue_start,
00236 colormap.m_red_length,
00237 colormap.m_blue_length,
00238 colormap.m_green_length);
00239 }
00240 }
00241 }
00242
00243 template <class T>
00244 void SubBlitter_AlphaMask<T>::blt_noclip(
00245 CL_Blit_AlphaMask_RLE *parent,
00246 CL_Target *target,
00247 BltRLERow_AlphaMask<T> *row_blitter,
00248 int x,
00249 int y,
00250 int spr_no)
00251 {
00252 unsigned int dest_pitch = target->get_pitch();
00253
00254 unsigned char *dest = (unsigned char *) target->get_data();
00255 dest += x*sizeof(T) + y*dest_pitch;
00256
00257 int cur_line = parent->m_height*spr_no;
00258 for (unsigned int yy=0; yy<parent->m_height; yy++)
00259 {
00260 unsigned char *line_data = parent->m_lines[cur_line+yy];
00261 if (line_data == NULL) continue;
00262
00263 unsigned char *alpha_data = parent->m_alpha_lines[cur_line+yy];
00264
00265 T *dd = (T *) (dest+yy*dest_pitch);
00266 int cur_state = CL_Blit_AlphaMask_RLE::cmd_alpha;
00267
00268 unsigned int x = *((unsigned short *) (&line_data[0]));
00269 int lpos = 2;
00270
00271 while (x<parent->m_width)
00272 {
00273 if (cur_state == CL_Blit_AlphaMask_RLE::cmd_alpha)
00274 {
00275 unsigned short rep = *((unsigned short *) &line_data[lpos]);
00276 lpos += 2;
00277
00278 row_blitter->show_alpha_row(
00279 (T *) &(line_data[lpos]),
00280 &dd[x],
00281 &alpha_data[x],
00282 rep);
00283
00284 x += rep;
00285 lpos += sizeof(T)*rep;
00286
00287 cur_state = CL_Blit_AlphaMask_RLE::cmd_skip;
00288 }
00289 else
00290 {
00291 unsigned short *skip_pos = (unsigned short *) (&line_data[lpos]);
00292 unsigned short skip = *skip_pos;
00293 x += skip;
00294 lpos += 2;
00295 cur_state = CL_Blit_AlphaMask_RLE::cmd_alpha;
00296 }
00297 }
00298 }
00299 }
00300
00301 void CL_Blit_AlphaMask_RLE::blt_noclip(
00302 CL_Target *target,
00303 int x,
00304 int y,
00305 int spr_no)
00306 {
00307 target->lock();
00308
00309 unsigned int dest_bytes_per_pixel = (target->get_depth()+7)/8;
00310 switch (dest_bytes_per_pixel)
00311 {
00312 case 2:
00313 check_16bit_rowblitter(target);
00314 SubBlitter_AlphaMask<unsigned short>::blt_noclip(this, target, bltrow_16bit, x, y, spr_no);
00315 break;
00316 case 4:
00317 check_32bit_rowblitter(target);
00318 SubBlitter_AlphaMask<unsigned int>::blt_noclip(this, target, bltrow_32bit, x, y, spr_no);
00319 break;
00320 default:
00321 cl_assert(false);
00322 }
00323
00324 target->unlock();
00325 }
00326
00327 template <class T>
00328 void SubBlitter_AlphaMask<T>::blt_clip(
00329 CL_Blit_AlphaMask_RLE *parent,
00330 CL_Target *target,
00331 BltRLERow_AlphaMask<T> *row_blitter,
00332 int x,
00333 int y,
00334 int spr_no,
00335 const CL_ClipRect &clip)
00336 {
00337 CL_ClipRect dest_clip(x, y, x+parent->m_width, y+parent->m_height);
00338 CL_ClipRect clipped = clip.clip(dest_clip);
00339
00340 if (clipped.m_x1 >= clipped.m_x2 ||
00341 clipped.m_y1 >= clipped.m_y2) return;
00342
00343 target->lock();
00344
00345 unsigned int dest_pitch = target->get_pitch();
00346
00347 unsigned char *dest = (unsigned char *) target->get_data();
00348 dest += clipped.m_x1*sizeof(T) + clipped.m_y1*dest_pitch;
00349
00350 int src_delta_x = clipped.m_x1-dest_clip.m_x1;
00351 int src_delta_y = clipped.m_y1-dest_clip.m_y1;
00352
00353 unsigned int size_x = clipped.m_x2-clipped.m_x1;
00354 unsigned int size_y = clipped.m_y2-clipped.m_y1;
00355
00356 int offset_line = parent->m_height*spr_no + src_delta_y;
00357
00358 for (unsigned int yy=0; yy<size_y; yy++)
00359 {
00360 unsigned char *line_data = parent->m_lines[offset_line+yy];
00361 if (line_data == NULL) continue;
00362
00363 unsigned char *alpha_data = parent->m_alpha_lines[offset_line+yy];
00364 T *dd = (T *) (dest+yy*dest_pitch);
00365
00366 unsigned short src_pos = *((unsigned short *) (&line_data[0]));
00367 int cur_state = CL_Blit_AlphaMask_RLE::cmd_alpha;
00368 int lpos = 2;
00369
00370 while (src_pos < src_delta_x)
00371 {
00372 if (cur_state == CL_Blit_AlphaMask_RLE::cmd_alpha)
00373 {
00374 unsigned short rep = *((unsigned short *) &line_data[lpos]);
00375 lpos += 2;
00376
00377 if (src_pos+rep >= src_delta_x)
00378 {
00379 unsigned short skip = src_delta_x-src_pos;
00380 unsigned short clip_rep = rep - skip;
00381
00382 if (int(src_pos+rep) >= int(size_x+src_delta_x))
00383 {
00384 clip_rep -= (src_pos+rep)-(size_x+src_delta_x);
00385 }
00386
00387 if (clip_rep > 0)
00388 {
00389 row_blitter->show_alpha_row(
00390 (T *) &(line_data[lpos+sizeof(T)*skip]),
00391 dd,
00392 &alpha_data[src_pos+skip],
00393 clip_rep);
00394 }
00395 }
00396
00397 src_pos += rep;
00398 lpos += sizeof(T)*rep;
00399
00400 cur_state = CL_Blit_AlphaMask_RLE::cmd_skip;
00401 }
00402 else
00403 {
00404 unsigned short *skip_pos = (unsigned short *) (&line_data[lpos]);
00405 unsigned short skip = *skip_pos;
00406 src_pos += skip;
00407 lpos += 2;
00408 cur_state = CL_Blit_AlphaMask_RLE::cmd_alpha;
00409 }
00410 }
00411
00412 unsigned int x = src_pos - src_delta_x;
00413
00414 while (x<size_x)
00415 {
00416 if (cur_state == CL_Blit_AlphaMask_RLE::cmd_alpha)
00417 {
00418 unsigned short rep = *((unsigned short *) &line_data[lpos]);
00419 lpos += 2;
00420
00421 unsigned short clip_rep = rep;
00422
00423 if (x+rep >= size_x)
00424 {
00425 clip_rep = size_x - x;
00426 }
00427
00428 if (clip_rep > 0)
00429 {
00430 row_blitter->show_alpha_row(
00431 (T *) &(line_data[lpos]),
00432 &dd[x],
00433 &alpha_data[src_delta_x+x],
00434 clip_rep);
00435 }
00436
00437 x += rep;
00438 lpos += sizeof(T)*rep;
00439
00440 cur_state = CL_Blit_AlphaMask_RLE::cmd_skip;
00441 }
00442 else
00443 {
00444 unsigned short *skip_pos = (unsigned short *) (&line_data[lpos]);
00445 unsigned short skip = *skip_pos;
00446 x += skip;
00447 lpos += 2;
00448 cur_state = CL_Blit_AlphaMask_RLE::cmd_alpha;
00449 }
00450 }
00451 }
00452
00453 target->unlock();
00454 }
00455
00456 void CL_Blit_AlphaMask_RLE::blt_clip(
00457 CL_Target *target,
00458 int x,
00459 int y,
00460 int spr_no,
00461 const CL_ClipRect &clip)
00462 {
00463 unsigned int dest_bytes_per_pixel = (target->get_depth()+7)/8;
00464 switch (dest_bytes_per_pixel)
00465 {
00466 case 2:
00467 check_16bit_rowblitter(target);
00468 SubBlitter_AlphaMask<unsigned short>::blt_clip(this, target, bltrow_16bit, x, y, spr_no, clip);
00469 break;
00470 case 4:
00471 check_32bit_rowblitter(target);
00472 SubBlitter_AlphaMask<unsigned int>::blt_clip(this, target, bltrow_32bit, x, y, spr_no, clip);
00473 break;
00474 }
00475 }
00476
00477 template <class T>
00478 void SubBlitter_AlphaMask<T>::unpack_line(
00479 T *dest,
00480 unsigned char *transparent_dest,
00481 unsigned char *source_data,
00482 int num_pixels)
00483 {
00484 int cur_state = CL_Blit_AlphaMask_RLE::cmd_skip;
00485 int x = 0;
00486 int lpos = 0;
00487 while (x < num_pixels)
00488 {
00489 if (cur_state == CL_Blit_AlphaMask_RLE::cmd_alpha)
00490 {
00491 unsigned short rep = *((unsigned short *) &source_data[lpos]);
00492 lpos += 2;
00493
00494 memset(&transparent_dest[x], 0, rep);
00495
00496 for (;rep>0;rep--)
00497 {
00498 dest[x++] = *((T *) &source_data[lpos]);
00499 lpos += sizeof(T);
00500 }
00501
00502 cur_state = CL_Blit_AlphaMask_RLE::cmd_skip;
00503 }
00504 else
00505 {
00506 unsigned short *skip_pos = (unsigned short *) (&source_data[lpos]);
00507 unsigned short skip = *skip_pos;
00508 memset(&transparent_dest[x], 1, skip);
00509 x += skip;
00510 lpos += 2;
00511 cur_state = CL_Blit_AlphaMask_RLE::cmd_alpha;
00512 }
00513 }
00514 }
00515
00516 template <class T>
00517 void SubBlitter_AlphaMask<T>::blt_scale_noclip(
00518 CL_Blit_AlphaMask_RLE *parent,
00519 CL_Target *target,
00520 BltRLERow_AlphaMask<T> *row_blitter,
00521 int x,
00522 int y,
00523 int dest_width,
00524 int dest_height,
00525 int spr_no)
00526 {
00527 if (dest_width <= 0 || dest_height <= 0) return;
00528 target->lock();
00529
00530 unsigned int dest_pitch = target->get_pitch();
00531
00532 unsigned char *dest = (unsigned char*) target->get_data();
00533 dest += x*sizeof(T) + y*dest_pitch;
00534
00535 unsigned int stepX = (parent->m_width<<16) / dest_width;
00536 unsigned int stepY = (parent->m_height<<16) / dest_height;
00537 unsigned int posX = 0;
00538 unsigned int posY = 0;
00539
00540 T *unpacked_line = new T[parent->m_width];
00541 unsigned char *is_transparent = new unsigned char[parent->m_width];
00542
00543 for (int yy=0; yy<dest_height; yy++)
00544 {
00545 unsigned char *line_data = parent->m_lines[posY>>16];
00546 if (line_data != NULL)
00547 {
00548 unsigned char *alpha_data = parent->m_alpha_lines[posY>>16];
00549
00550 unpack_line(unpacked_line, is_transparent, line_data, parent->m_width);
00551
00552 T *dd = (T *) (dest+yy*dest_pitch);
00553
00554 posX = 0;
00555 for (int xx=0;xx<dest_width;xx++)
00556 {
00557 int ix = (posX>>16);
00558 if (!is_transparent[ix])
00559 {
00560 row_blitter->show_alpha_row(
00561 &unpacked_line[ix],
00562 &dd[xx],
00563 &alpha_data[ix],
00564 1);
00565 }
00566 posX += stepX;
00567 }
00568 }
00569 posY+=stepY;
00570 }
00571
00572 delete[] unpacked_line;
00573 delete[] is_transparent;
00574
00575 target->unlock();
00576 }
00577
00578 void CL_Blit_AlphaMask_RLE::blt_scale_noclip(
00579 CL_Target *target,
00580 int x,
00581 int y,
00582 int dest_width,
00583 int dest_height,
00584 int spr_no)
00585 {
00586 unsigned int dest_bytes_per_pixel = (target->get_depth()+7)/8;
00587 switch (dest_bytes_per_pixel)
00588 {
00589 case 2:
00590 check_16bit_rowblitter(target);
00591 SubBlitter_AlphaMask<unsigned short>::blt_scale_noclip(
00592 this,
00593 target,
00594 bltrow_16bit,
00595 x,
00596 y,
00597 dest_width,
00598 dest_height,
00599 spr_no);
00600 break;
00601 case 4:
00602 check_32bit_rowblitter(target);
00603 SubBlitter_AlphaMask<unsigned int>::blt_scale_noclip(
00604 this,
00605 target,
00606 bltrow_32bit,
00607 x,
00608 y,
00609 dest_width,
00610 dest_height,
00611 spr_no);
00612 break;
00613 }
00614 }
00615
00616 template <class T>
00617 void SubBlitter_AlphaMask<T>::blt_scale_clip(
00618 CL_Blit_AlphaMask_RLE *parent,
00619 CL_Target *target,
00620 BltRLERow_AlphaMask<T> *row_blitter,
00621 int x,
00622 int y,
00623 int dest_width,
00624 int dest_height,
00625 int spr_no,
00626 const CL_ClipRect &clip)
00627 {
00628 if (dest_width <= 0 || dest_height <= 0) return;
00629
00630 CL_ClipRect dest_clip(x, y, x+dest_width, y+dest_height);
00631 CL_ClipRect clipped = clip.clip(dest_clip);
00632
00633 if (clipped.m_x1 >= clipped.m_x2 ||
00634 clipped.m_y1 >= clipped.m_y2) return;
00635 target->lock();
00636
00637 unsigned int dest_pitch = target->get_pitch();
00638
00639 unsigned char *dest = (unsigned char*) target->get_data();
00640 dest += clipped.m_x1*sizeof(T) + clipped.m_y1*dest_pitch;
00641
00642 unsigned int stepX = (parent->m_width<<16) / dest_width;
00643 unsigned int stepY = (parent->m_height<<16) / dest_height;
00644
00645 unsigned int clipX = stepX*(clipped.m_x1-x);
00646 unsigned int clipY = stepY*(clipped.m_y1-y);
00647
00648 unsigned int posX = clipX;
00649 unsigned int posY = clipY;
00650
00651 dest_width = clipped.m_x2-clipped.m_x1;
00652 dest_height = clipped.m_y2-clipped.m_y1;
00653
00654 T *unpacked_line = new T[parent->m_width];
00655 unsigned char *is_transparent = new unsigned char[parent->m_width];
00656
00657 for (int yy=0; yy<dest_height; yy++)
00658 {
00659 unsigned char *line_data = parent->m_lines[posY>>16];
00660 if (line_data != NULL)
00661 {
00662 unsigned char *alpha_data = parent->m_alpha_lines[posY>>16];
00663
00664 unpack_line(unpacked_line, is_transparent, line_data, parent->m_width);
00665
00666 T *dd = (T *) (dest+yy*dest_pitch);
00667
00668 posX = clipX;
00669 for (int xx=0;xx<dest_width;xx++)
00670 {
00671 int ix = (posX>>16);
00672 if (!is_transparent[ix])
00673 {
00674 row_blitter->show_alpha_row(
00675 &unpacked_line[ix],
00676 &dd[xx],
00677 &alpha_data[ix],
00678 1);
00679 }
00680 posX += stepX;
00681 }
00682 }
00683 posY+=stepY;
00684 }
00685
00686 delete[] unpacked_line;
00687 delete[] is_transparent;
00688
00689 target->unlock();
00690 }
00691
00692 void CL_Blit_AlphaMask_RLE::blt_scale_clip(
00693 CL_Target *target,
00694 int x,
00695 int y,
00696 int dest_width,
00697 int dest_height,
00698 int spr_no,
00699 const CL_ClipRect &clip)
00700 {
00701 unsigned int dest_bytes_per_pixel = (target->get_depth()+7)/8;
00702 switch (dest_bytes_per_pixel)
00703 {
00704 case 2:
00705 check_16bit_rowblitter(target);
00706 SubBlitter_AlphaMask<unsigned short>::blt_scale_clip(
00707 this,
00708 target,
00709 bltrow_16bit,
00710 x,
00711 y,
00712 dest_width,
00713 dest_height,
00714 spr_no,
00715 clip);
00716 break;
00717 case 4:
00718 check_32bit_rowblitter(target);
00719 SubBlitter_AlphaMask<unsigned int>::blt_scale_clip(
00720 this,
00721 target,
00722 bltrow_32bit,
00723 x,
00724 y,
00725 dest_width,
00726 dest_height,
00727 spr_no,
00728 clip);
00729 break;
00730 }
00731 }