Thread: Software blitter

  1. #1
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485

    Software blitter

    Hallo,

    I have posted questions about software blitting a few times before, but now im back again with a new question.

    After reading this article I started wondering about using OR and AND to do the blitting
    Wiki_Link

    Would it be possible to blitt line by line instead of pixel by pixel using the mentioned operators? From reading the article it looks like it, but I am not sure on how. Could someone please explain a bit or tell me what I need to read up on?

    Thanks

  2. #2
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    I'm not sure what you mean...you have to perform the operation on every set of pixels so it just isn't possible to process it any other way. whether the API you're using is efficient at doing this I don't know. if not you could always do the masking yourself.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by h3ro View Post
    Would it be possible to blitt line by line instead of pixel by pixel using the mentioned operators? From reading the article it looks like it, but I am not sure on how. Could someone please explain a bit or tell me what I need to read up on?
    No, because a "line" is an abstract notion. It is a sequence of pixels. The bitwise operators AND and OR operate only on fundamental quantities like char, short, or int.

    So "blitting a line" is synonymous with blitting every pixel in the line.

  4. #4
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    The blitting is done in software so Im not really using an API for it.

    Right now im doing this
    Code:
    for(each pixel)
      if(alpha != 0)
         do pixel calculations
    But is it possible to somehow use logic operators to copy only the pixels that have a color over to the screen one line at the time?

    From the article:
    The first blit uses the raster operator of AND with the background and the mask of the sprites. Because any value ANDed with 0 equals 0, and any value ANDed with 1 is unchanged, we can create black areas where the actual sprites will appear, and leave the rest of the background alone.

    The second blit uses the raster operator of OR with the altered background and the actual sprite. Because any value OR'd with 0 is unchanged, the background is unaffected and the black areas are filled with the actual sprite image.

  5. #5
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Quote Originally Posted by brewbuck View Post
    No, because a "line" is an abstract notion. It is a sequence of pixels. The bitwise operators AND and OR operate only on fundamental quantities like char, short, or int.

    So "blitting a line" is synonymous with blitting every pixel in the line.
    By drawing a line I mean using memcpy() instead of doing it pixel by pixel.

    So sort of using a the alpha channel to set the size to copy and the color value for what to copy.

  6. #6
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    A faster way of blitting (though its quite a bit of work) is to build a list counting the number of masked pixels, followed by the number of pixels to draw, followed by how many pixels to mask, pixels to draw, etc.

    That way you dont need to check before doing stuff with each pixel you just write x number of pixels, skip the pointer forward x number of steps, write the next x number of pixels, skip, write, skip.

  7. #7
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    So I should do some pre-processing when I load my sprites?

    Code:
    struct drawPart{
      byte startPixel;
      int size;
    }
    
    while(not at end of sprite)
       if(currentPixel.alpha != 0)
           increase drawPart.size;
       else
           create new drawPart;
    And then when drawing it I just draw all the drawParts that is created by the pre-processing?
    Thanks for the input so far

    EDIT:
    Clipping would break the data that is created when loading the sprite I think. The only way to get it to work this way is to create a list of drawParts each time I want to draw the sprite? I think that would be slower then what I have so far.
    Last edited by h3ro; 04-17-2008 at 12:29 PM.

  8. #8
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218

    Thumbs up

    Sort of, but remember you have to toggle between read/write states. I'm writing this off the top of my head so the pseudocode may still have errors in it, but something like:
    Code:
    Uint32 skip_write[10000];
    
    Precalc(image im)
        int size = im.x * im.y;
        bool state = 0;
        int index = 0;
        int count = 0;
        for(int i=0; i<size; i++)
            if(state)
                if(im.pixel[i] == MASK)
                      count++;
                else
                      skip_write[index] = count;
                      count = 1;
                      index++;
                      state = false;
            else
               if(im.pixel[i] != MASK)
                      count++;
               else
                      skip_write[index] = count;
                      count =1;
                      index++;
                      state = true;
    Edit: you also need to note if the first pixel is masked or not, also using a linked list for this can save a lot of memory.
    Last edited by mike_g; 04-17-2008 at 12:39 PM.

  9. #9
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Thank you very much mike_g, Ill try to implement it to see how much faster it is.

    One last question, coming from this article:
    gameDev_Link

    In the article the author combines two 16bit pixels into one int so he can process two at the same time. Would that work with a two 32 bits colors on a 64bits system?

  10. #10
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Pretty much, but many people dont have 64bit systems. Also, this is something I havent done yet, but with a little ASM you can use the intel MMX, or AMD 3dnow registers. These can apply the same instruction to 4 32bit numbers at the same time so its like 4x the speed.

    Edit: lol the links about MMX. For some reason the page dident display properly for me tho o_0
    Edit2: now it does. thanks for the link, looks interesting.
    Last edited by mike_g; 04-17-2008 at 12:51 PM.

  11. #11
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    4x speed would indeed be nice. My aim is to make the alphaBlitt function so fast that I can use it to draw everything in my game. Right now the game slows down to much when there are to many players at the screen at the same time.

    I dont know anything about ASM (= black Magic), so not sure how possible it would be to use that for me.

    If I switch to 16bit color (not sure if I can do that), I would be possible to do 8 x 16bits at the same time?

    mike_g: I looked at your homepage. Looks like you have made several good 2d projects. For the tile engine you say that I can create mini-maps, could you please share some points on how you do this? I assume you dont just take the whole map and scale it down?

  12. #12
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Erm yeah, thanks. That site is kind of lame, and all the stuff on there is really old. I had a new one on sitesled but they kept deleting my account, probably cos I was direct linking all my files and not sending anyone to my site. Anyway, the tile editor was left as a bit of a mess really. Making minimaps isent too hard though. The way I did it was to precalc the average colour of each tile at the start and then draw tiny squares in it. Alternatively you could just resize the tiles very small and draw them to a minimap image.

    And yeah, if you switch to 16bit colour you shoudl be able to do double the amount like you said.
    Last edited by mike_g; 04-17-2008 at 01:08 PM.

  13. #13
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Using AND OR to do blitting is a waste unless you are in GDI or something. This technique requires two blits and is wasteful.

    Without MMX the most you can blit at one time is:

    8 bits per pixel - 4 pixels
    16 bits per pixel - 2 pixels
    32 bit per pixel - 1 pixel

    A stosd is the most you can blit without using SIMD instructions.

    Code:
    void Blit(DWORD *pScreen,RGBA *pImage,int x,int y,int image_width,int image_height,int buffer_pitch)
    {
        unsigned long buffer_offset = y * buffer_pitch + x;
        unsigned long actual_buffer_offset = buffer_offset;
        unsigned long image_offset = 0;
        int y_counter = 0;
        int x_counter = 0;
    
        while (y_counter < image_height)
        {
            pScreen[actual_buffer_offset] = pImage[image_offset];
            actual_buffer_offset++;
            image_offset++;
            x_counter++;
            
            if (x_counter > image_width)
            {
                x_counter = 0;
                y_counter++;
                buffer_offset += buffer_pitch;
                actual_buffer_offset = buffer_offset;
            }
        }
    }
    This blit does not take into account the edges of the screen. It also does not take into account transparent pixels or alpha.
    Last edited by VirtualAce; 04-17-2008 at 07:21 PM.

  14. #14
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    Using AND OR to do blitting is a waste unless you are in GDI or something. This technique requires two blits and is wasteful.
    What is GDI? Never heard that term before, but if you say that this is the wrong way to go about it ill take your word for it.

    A stosd is the most you can blit without using SIMD instructions.
    What is stosd?

    This blit does not take into account the edges of the screen. It also does not take into account transparent pixels or alpha.
    Thanks for your function. But it is a lot slower then the one I am already using.

    Without MMX the most you can blit at one time is:

    8 bits per pixel - 4 pixels
    16 bits per pixel - 2 pixels
    32 bit per pixel - 1 pixel
    Would it be better for me to look at how to program in MMX then in assembly for this kind of things?
    When doing several pixels in one cycle, the alpha of them has to be the same right?

    On a 64bit processor I could do twice what you listed right?

    I find the whole concept of calculating several pixels at the same time very very confusing =\

    EDIT:
    It looks like I would be better of using 16bit colors instead of 32bits. The difference in picture quality is not very big, and considering that I am making a top down shooter that plays at less then 600x400 no one would really tell the difference anyway.

    But is it possible to change it? Right now im using 32bit colors and there is no option in the API to change it to 16bits. But I do all the blitting my self so maybe I can do it there?
    Last edited by h3ro; 04-19-2008 at 03:51 AM.

  15. #15
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Would it be better for me to look at how to program in MMX then in assembly for this kind of things?
    MMX is basically just a set of registers Intel added to their chips for parallel processing. AFAIK to access these you need to use ASM. Someone may have made a C++ wrapper for this, but I don't know of one. A problem with MMX is that its Intel specific. If you want to run the prog on an AMD you need to find out what processor is being used, and if you want AMD acceleration you will need to have it use their equivalent: 3DNow. When stuff becomes system specific, you are going to end up with a lot of extra complications.

    16 bit colour can still look nice, but you will lose your alpha channel. In the 2d APIs I have used you can set the bit depth when setting up the screen. The parameters usually go something like: graphics width, graphics height, bit depth, display mode. However, without knowing what api you are using its impossible for anyone to answer that accurately.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Software Developer Opportunity in Delaware
    By Jdorazio in forum Projects and Job Recruitment
    Replies: 0
    Last Post: 04-28-2009, 10:58 AM
  2. Software Design/Test - Redmond, WA
    By IRVolt in forum Projects and Job Recruitment
    Replies: 2
    Last Post: 06-11-2008, 10:26 AM
  3. Why C Matters
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 136
    Last Post: 01-16-2008, 09:09 AM
  4. Adding trial period to software
    By BobS0327 in forum C Programming
    Replies: 17
    Last Post: 01-03-2006, 02:13 PM