Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

blit_dx.cpp

Go to the documentation of this file.
00001 
00002 #include "Core/precomp.h"
00003 #include <windows.h>
00004 #include "blit_dx.h"
00005 #include <API/Display/Display/surfaceprovider.h>
00006 #include "../Generic/colormap.h"
00007 #include "../Generic/blit_alphamask_rle.h"
00008 #include "../Generic/pixeldata.h"
00009 
00010 std::list<CL_Blit_DX*> CL_Blit_DX::m_loaded_surfaces;
00011 
00012 CL_Blit_DX::CL_Blit_DX(
00013         CL_DisplayCard_DirectDraw *target,
00014         CL_SurfaceProvider *provider)
00015 {
00016         m_target = target;
00017         m_provider = provider;
00018         m_surface = NULL;
00019         m_alphablitter = NULL;
00020 }
00021 
00022 CL_Blit_DX::~CL_Blit_DX()
00023 {
00024         if (m_surface != NULL) 
00025         {
00026                 m_surface->Release();
00027                 m_loaded_surfaces.remove(this);
00028         }
00029         if (m_alphablitter != NULL) delete m_alphablitter;
00030 }
00031 
00032 bool CL_Blit_DX::init_surface(CL_Blitters *blitters)
00033 {
00034         if (!reload(false, true)) return false;
00035 
00036         blitters->set_clip(this);
00037         blitters->set_noclip(this);
00038         blitters->set_scale_noclip(this);
00039         blitters->set_scale_clip(this);
00040 
00041         m_loaded_surfaces.push_back(this);
00042 
00043         return true;
00044 }
00045 
00046 void CL_Blit_DX::blt_noclip(
00047         CL_Target *target,
00048         int x,
00049         int y,
00050         int spr_no)
00051 {
00052         DWORD flags = DDBLTFAST_WAIT;
00053         if (m_transparent)
00054         {
00055                 flags|=DDBLTFAST_SRCCOLORKEY; 
00056         }
00057         else
00058         {
00059                 flags|=DDBLTFAST_NOCOLORKEY;
00060         }
00061 
00062         RECT source;
00063         int delta = spr_no*m_height;
00064 
00065         source.left=0;
00066         source.top=delta;
00067         source.right=m_width;
00068         source.bottom=m_height+delta;
00069 
00070         m_target->get_back_buffer()->get_surface()->BltFast(x, y, m_surface, &source, flags);
00071 
00072         if (m_alphablitter != NULL) m_alphablitter->blt_noclip(target, x, y, spr_no);
00073 }
00074 
00075 void CL_Blit_DX::blt_clip(
00076         CL_Target *target,
00077         int x,
00078         int y,
00079         int spr_no,
00080         const CL_ClipRect &clip)
00081 {
00082         DDBLTFX ddbltfx;
00083         ddbltfx.dwSize = sizeof(ddbltfx);
00084 
00085         DWORD flags = DDBLT_WAIT;
00086         if (m_transparent)
00087         {
00088                 flags|=DDBLT_KEYSRC; 
00089         }
00090 
00091         RECT dest, source;
00092         source.left=0;
00093         source.top=0;
00094         source.right=m_width;
00095         source.bottom=m_height;
00096 
00097         dest.left = x;
00098         dest.top = y;
00099         dest.right = dest.left + m_width;
00100         dest.bottom = dest.top + m_height;
00101 
00102         if (dest.left < clip.m_x1)
00103         {
00104                 source.left = clip.m_x1-dest.left;
00105                 dest.left = clip.m_x1;
00106         }
00107 
00108         if (dest.top < clip.m_y1)
00109         {
00110                 source.top = clip.m_y1-dest.top;
00111                 dest.top = clip.m_y1;
00112         }
00113 
00114         if (dest.right > clip.m_x2)
00115         {
00116                 source.right -= dest.right-clip.m_x2;
00117                 dest.right = clip.m_x2;
00118         }
00119 
00120         if (dest.bottom > clip.m_y2)
00121         {
00122                 source.bottom -= dest.bottom-clip.m_y2;
00123                 dest.bottom = clip.m_y2;
00124         }
00125 
00126         if (dest.right<dest.left || dest.bottom<dest.top) return; // Out of clipping borders
00127 
00128         int delta = spr_no*m_height;
00129         source.top += delta;
00130         source.bottom += delta;
00131 
00132         m_target->get_back_buffer()->get_surface()->Blt(&dest, m_surface, &source, flags, &ddbltfx);
00133         if (m_alphablitter != NULL) m_alphablitter->blt_clip(target, x, y, spr_no, clip);
00134 }
00135 
00136 void CL_Blit_DX::blt_scale_noclip(
00137         CL_Target *target,
00138         int x,
00139         int y,
00140         int dest_width,
00141         int dest_height,
00142         int spr_no)
00143 {
00144         DDBLTFX ddbltfx;
00145         ddbltfx.dwSize = sizeof(ddbltfx);
00146 
00147         DWORD flags = DDBLT_WAIT;
00148         if (m_transparent)
00149         {
00150                 flags|=DDBLT_KEYSRC; 
00151         }
00152 
00153         RECT dest, source;
00154         source.left=0;
00155         source.top=0;
00156         source.right=m_width;
00157         source.bottom=m_height;
00158 
00159         dest.left = x;
00160         dest.top = y;
00161         dest.right = dest.left + dest_width;
00162         dest.bottom = dest.top + dest_height;
00163 
00164         int delta = spr_no*m_height;
00165         source.top += delta;
00166         source.bottom += delta;
00167 
00168         m_target->get_back_buffer()->get_surface()->Blt(&dest, m_surface, &source, flags, &ddbltfx);
00169         if (m_alphablitter != NULL) m_alphablitter->blt_scale_noclip(target, x, y, dest_width, dest_height, spr_no);
00170 }
00171 
00172 void CL_Blit_DX::blt_scale_clip(
00173         CL_Target *target,
00174         int x,
00175         int y,
00176         int dest_width,
00177         int dest_height,
00178         int spr_no,
00179         const CL_ClipRect &clip)
00180 {
00181         DDBLTFX ddbltfx;
00182         ddbltfx.dwSize = sizeof(ddbltfx);
00183 
00184         DWORD flags = DDBLT_WAIT;
00185         if (m_transparent)
00186         {
00187                 flags|=DDBLT_KEYSRC; 
00188         }
00189 
00190         RECT dest, source;
00191         source.left=0;
00192         source.top=0;
00193         source.right=m_width;
00194         source.bottom=m_height;
00195 
00196         dest.left = x;
00197         dest.top = y;
00198         dest.right = dest.left + dest_width;
00199         dest.bottom = dest.top + dest_height;
00200 
00201         float dx = float(m_width)/dest_width;
00202         float dy = float(m_height)/dest_height;
00203 
00204         if (dest.left < clip.m_x1)
00205         {
00206                 source.left = int((clip.m_x1-dest.left)*dx+0.5);
00207                 dest.left = clip.m_x1;
00208         }
00209 
00210         if (dest.top < clip.m_y1)
00211         {
00212                 source.top = int((clip.m_y1-dest.top)*dy+0.5);
00213                 dest.top = clip.m_y1;
00214         }
00215 
00216         if (dest.right > clip.m_x2)
00217         {
00218                 source.right -= int((dest.right-clip.m_x2)*dx+0.5);
00219                 dest.right = clip.m_x2;
00220         }
00221 
00222         if (dest.bottom > clip.m_y2)
00223         {
00224                 source.bottom -= int((dest.bottom-clip.m_y2)*dy+0.5);
00225                 dest.bottom = clip.m_y2;
00226         }
00227 
00228         if (dest.right<dest.left || dest.bottom<dest.top) return; // Out of clipping borders
00229 
00230         int delta = spr_no*m_height;
00231         source.top += delta;
00232         source.bottom += delta;
00233 
00234         m_target->get_back_buffer()->get_surface()->Blt(&dest, m_surface, &source, flags, &ddbltfx);
00235         if (m_alphablitter != NULL) m_alphablitter->blt_scale_clip(target, x, y, dest_width, dest_height, spr_no, clip);
00236 }
00237 
00238 bool CL_Blit_DX::reload(bool lock_provider, bool create_surface)
00239 {
00240         unsigned int y;
00241 
00242         if (lock_provider) m_provider->lock();
00243 
00244         unsigned int num_lines = m_provider->get_height()*m_provider->get_num_frames();
00245 
00246         CL_PixelData alpha(
00247                 0,
00248                 0,
00249                 0,
00250                 255,
00251                 m_provider,
00252                 1);
00253 
00254         int bytes_pr_line = alpha.get_bytes_pr_line();
00255         unsigned char *alpha_data = new unsigned char[num_lines*bytes_pr_line];
00256 
00257         bool has_alpha = false;
00258         m_transparent = false;
00259 
00260         int alpha_width = alpha.get_width();
00261         for (y=0;y<num_lines;y++)
00262         {
00263                 unsigned char *l = &alpha_data[y*bytes_pr_line];
00264                 alpha.get_line_pixel_to_dest(y, l);
00265 
00266                 for (int x=0;x<alpha_width;x++)
00267                 {
00268                         if (l[x] == 0) m_transparent = true;
00269                         if (l[x] != 0 && l[x] != 255) 
00270                         {
00271                                 m_transparent = true;
00272                                 has_alpha = true;
00273                                 break;
00274                         }
00275                 }
00276         }
00277 
00278         CL_PixelData input(
00279                 m_target->get_target()->get_red_mask(),
00280                 m_target->get_target()->get_green_mask(),
00281                 m_target->get_target()->get_blue_mask(),
00282                 m_target->get_target()->get_alpha_mask(),
00283                 m_provider,
00284                 (m_target->get_target()->get_depth()+7)/8);
00285 
00286         m_width = m_provider->get_width();
00287         m_height = m_provider->get_height();
00288 
00289         if (create_surface)
00290         {
00291                 DDSURFACEDESC sur_desc;
00292                 sur_desc.dwSize = sizeof(DDSURFACEDESC);
00293                 sur_desc.dwFlags=DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
00294                 sur_desc.dwWidth=m_width;
00295                 sur_desc.dwHeight=m_height*m_provider->get_num_frames();
00296                 sur_desc.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
00297 /*              
00298                 if (m_target->m_target->m_system_backbuffer != NULL)
00299                 {
00300                         sur_desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
00301                 }
00302                 else*/
00303                 {
00304                         sur_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
00305                 }
00306 
00307                 HRESULT err;
00308                 err = m_target->get_directdraw()->CreateSurface(&sur_desc, &m_surface, NULL);
00309                 if (err != DD_OK)
00310                 {
00311                         delete[] alpha_data;
00312                         return false;
00313                 }
00314         }
00315         else
00316         {
00317                 m_surface->Restore();
00318         }
00319 
00320         DDSURFACEDESC surface_desc;
00321         memset(&surface_desc, 0, sizeof(DDSURFACEDESC));
00322         surface_desc.dwSize = sizeof(DDSURFACEDESC);
00323 
00324         HRESULT err = m_surface->Lock(
00325                 NULL,
00326                 &surface_desc,
00327                 DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
00328                 NULL);
00329         if (err != DD_OK) 
00330         {
00331                 delete[] alpha_data;
00332                 m_surface->Release();
00333                 m_surface = NULL;
00334                 return false;
00335         }
00336 
00337         CL_ColorMap color_map(m_target->get_target());
00338         unsigned int fill_color = color_map.calc_color(1, 0, 1, 0);
00339 
00340         unsigned char *surface_data = (unsigned char *) surface_desc.lpSurface;
00341 
00342         if (m_transparent)
00343         {
00344                 int input_bytes_pr_line = input.get_bytes_pr_line();
00345                 unsigned char *image_data = new unsigned char[num_lines*input_bytes_pr_line];
00346 
00347                 switch ((m_target->get_target()->get_depth()+7)/8)
00348                 {
00349                 case 1:
00350                         {
00351                                 unsigned char col = (unsigned char) fill_color;
00352 
00353                                 for (y=0;y<num_lines;y++)
00354                                 {
00355                                         unsigned char *input_data = &image_data[y*input_bytes_pr_line];
00356                                         input.get_line_pixel_to_dest(y, input_data);
00357 
00358                                         unsigned char *a = &alpha_data[y*bytes_pr_line];
00359                                         for (unsigned int x=0;x<m_width;x++)
00360                                         {
00361                                                 if (a[x] == 255)
00362                                                 {
00363                                                         surface_data[x] = input_data[x];
00364                                                 }
00365                                                 else
00366                                                 {
00367                                                         surface_data[x] = col;
00368                                                 }
00369                                         }
00370                                         surface_data += surface_desc.lPitch;
00371                                 }
00372 //                              m_alphablitter = new CL_Blit_Transparent_RLE_8(m_provider, 1, m_target->get_target());
00373                         }
00374                         break;
00375                 case 2:
00376                         {
00377                                 unsigned short col = (unsigned short) fill_color;
00378 
00379                                 for (y=0;y<num_lines;y++)
00380                                 {
00381                                         unsigned char *input_data = &image_data[y*input_bytes_pr_line];
00382                                         input.get_line_pixel_to_dest(y, input_data);
00383                                         unsigned char *a = &alpha_data[y*bytes_pr_line];
00384 
00385                                         for (unsigned int x=0;x<m_width;x++)
00386                                         {
00387                                                 if (a[x] == 255)
00388                                                 {
00389                                                         ((unsigned short *) surface_data)[x] = ((unsigned short *) input_data)[x];
00390                                                 }
00391                                                 else
00392                                                 {
00393                                                         ((unsigned short *) surface_data)[x] = col;
00394                                                 }
00395                                         }
00396                                         surface_data += surface_desc.lPitch;
00397                                 }
00398                                 if (has_alpha) m_alphablitter = new CL_Blit_AlphaMask_RLE(
00399                                         m_target,
00400                                         m_provider,
00401                                         image_data,
00402                                         input_bytes_pr_line,
00403                                         alpha_data,
00404                                         bytes_pr_line);
00405                         }
00406                         break;
00407                 case 3:
00408                         {
00409                                 // Our 24 bit support really sucks!
00410                                 cl_assert(false);
00411                         }
00412                         break;
00413                 case 4:
00414                         {
00415                                 for (y=0;y<num_lines;y++)
00416                                 {
00417                                         unsigned char *input_data = &image_data[y*input_bytes_pr_line];
00418                                         input.get_line_pixel_to_dest(y, input_data);
00419                                         unsigned char *a = &alpha_data[y*bytes_pr_line];
00420 
00421                                         for (unsigned int x=0;x<m_width;x++)
00422                                         {
00423                                                 if (a[x] == 255)
00424                                                 {
00425                                                         ((unsigned int *) surface_data)[x] = ((unsigned int *) input_data)[x];
00426                                                 }
00427                                                 else
00428                                                 {
00429                                                         ((unsigned int *) surface_data)[x] = fill_color;
00430                                                 }
00431                                         }
00432                                         surface_data += surface_desc.lPitch;
00433                                 }
00434                                 if (has_alpha) m_alphablitter = new CL_Blit_AlphaMask_RLE(
00435                                         m_target,
00436                                         m_provider,
00437                                         image_data,
00438                                         input_bytes_pr_line,
00439                                         alpha_data,
00440                                         bytes_pr_line);
00441                         }
00442                         break;
00443                 }
00444                 delete[] image_data;
00445         }
00446         else
00447         {
00448                 int bytes_per_line = input.get_bytes_per_pixel()*input.get_width();
00449                 for (unsigned int y=0;y<num_lines;y++)
00450                 {
00451                         memcpy(
00452                                 &surface_data[y*surface_desc.lPitch],
00453                                 input.get_line_pixel(y),
00454                                 bytes_per_line);
00455                 }
00456         }
00457 
00458         err = m_surface->Unlock(surface_data);
00459         cl_assert(err == DD_OK);
00460 
00461         if (m_transparent)
00462         {
00463                 DDCOLORKEY key;
00464                 key.dwColorSpaceLowValue = fill_color;
00465                 key.dwColorSpaceHighValue = fill_color;
00466 
00467                 err = m_surface->SetColorKey(DDCKEY_SRCBLT, &key);
00468                 cl_assert(err == DD_OK);
00469         }
00470 
00471         if (lock_provider) m_provider->unlock();
00472         delete[] alpha_data;
00473 
00474         return true;
00475 }
00476 
00477 void CL_Blit_DX::reload_all_surfaces()
00478 {
00479         for (
00480                 std::list<CL_Blit_DX*>::iterator counter = m_loaded_surfaces.begin();
00481                 counter != m_loaded_surfaces.end();
00482                 counter++)
00483         {
00484                 (*counter)->reload(true, false);
00485         }
00486 }
00487 
00488 void CL_Blit_DX::release_all_surfaces()
00489 {
00490         for (
00491                 std::list<CL_Blit_DX*>::iterator counter = m_loaded_surfaces.begin();
00492                 counter != m_loaded_surfaces.end();
00493                 counter++)
00494         {
00495                 (*counter)->m_surface->Release();
00496                 (*counter)->m_surface = NULL;
00497         }
00498 }
00499 
00500 void CL_Blit_DX::create_all_surfaces()
00501 {
00502         for (
00503                 std::list<CL_Blit_DX*>::iterator counter = m_loaded_surfaces.begin();
00504                 counter != m_loaded_surfaces.end();
00505                 counter++)
00506         {
00507                 (*counter)->reload(true, true);
00508         }
00509 }

Generated at Wed Apr 4 19:53:58 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001