13 Replies Latest reply on Jul 2, 2013 10:17 AM by MattBolt

    Blank screen when using SDL. What have I done wrong? :-)

    jimb0h

      Hey everyone,

       

       

      I've come here cap in hand hoping to find a bit of help with getting SDL to work with FlasCC. I've followed the quake example and have tried to set up a basic SDL project that draws a green square to the screen but no matter what I try, the screen or rather the bitmap that represents the screen, remains black.

       

       

      I tried a little test to see if SDL was actually writing screen pixels by directly referencing the SDL surface's screen pixels and writing them into the bitmap. This worked (I saw a green square) but I have a project that uses a screen that isn't 32 bit colour which means I can't directly write the SDL pixels into the bitmap also it seems wrong to be circumventing vgl. Actually that leads me to my next question - I am right in thinking that if you set up a 16bit colour screen in SDL, when SDL writes to the vgl buffer it's 32bit aligned (ARGB). I think I made that assumption as the Quake demo used indexed colour and at some point this 256 colour output was converted to 32bit colour.

       

       

      Any help or clues with this would be most appreciated as it's probably something really elementary that I'm messing up! :-)

       

       

      I've pasted my code below (it's as short and dirty as possible to keep this post succint)

       

       

      Cheers,

      Jimmy

       

       

      ------------------------------------------------------------

       

       

      #include <SDL.h>

      #include <iostream>

      #include "AS3/AS3.h"

       

       

      SDL_Surface* _sdlSurface = NULL;

       

       

      extern "C" void update() {

          if (_sdlSurface != NULL) {

                    SDL_FillRect(_sdlSurface, NULL, 0xFF00FF00);

                    SDL_UpdateRect(_sdlSurface, 0, 0, 0, 0); // when trying double buffering I used SDL_Flip here

                }

      }

       

       

      int main(int argc, char* argv[]) {

          SDL_Init(SDL_INIT_VIDEO);

       

       

          // NOTE: I have tried SDL_DOUBLEBUF and SDL_HWSURFACE to no avail

          _sdlSurface = SDL_SetVideoMode(320, 240, 32, SDL_SWSURFACE);

       

                std::cout << "SDL initialised" << std::endl;

       

       

                AS3_GoAsync();

      }

       

       

      ----------------------------------------------------------------

       

       

      In console.as I setup a bitmap and add it to stage exactly has shown in the quake demo. I then call CModule.startAsync(this) and then get the following two pointers:

       

       

            updatePtr = CModule.getPublicSymbol("update")

            vbuffer = CModule.getPublicSymbol("__avm2_vgl_argb_buffer")

       

       

      I add an enter frame listener which looks like this:

       

       

          protected function enterFrame(e:Event):void

          {

            if (vbuffer == 0) {

              trace("vbuffer is zero!");

              vbuffer = CModule.getPublicSymbol("__avm2_vgl_argb_buffer")

            }

       

       

            CModule.callI(updatePtr, emptyArgs);

       

       

            var ram:ByteArray = CModule.ram;

            ram.position = CModule.read32(vbuffer)

            if (ram.position != 0) {

              frameCount++

              bmd.setPixels(bmr, ram)

            }

          }

        • 1. Re: Blank screen when using SDL. What have I done wrong? :-)
          MattBolt

          I'm having a very similar problem. I even tried a pure C example (compiled with the flascc gcc vs g++), and got the same results. I also tried switching the SDL_Flip(surface) with SDL_UpdateRect(surface) since this is how the quake example handles it, but I haven't had any success.

           

          Were you able to figure this out? Can someone at Adobe respond?

           

           

          To answer your question concerning the ARGB conversion, I think I can answer that with the following stack trace from a demo app I'm tinkering with:

          call-stack1.png

           

          call-stack2.png

          The code from this stacktrace is below (with some screen shots of the results). I'm also a bit confused why the SDL_Delay is writing to the CModule? Maybe related to the mangled image below.

           

           

          Update:

          I was able to get *something* to render, but it required that I compile a debug version using:

          -O0 -g
          

          instead of:

          -O4 -flto-api=exports.txt -fno-stack-protector
          

          wrong.png

           

          However, it's supposed to look like this:

          right.png

           

          Here is my code:

          renderer.h


          #ifndef RENDERER_H
          #define RENDERER_H
          
          
          #include <iostream>
          #include <SDL/SDL.h>
          #include "snake.h"
          #include "globs.h"
          
          
          using namespace std;
          
          
          class Renderer {
              private:
                  SDL_Rect screenRect;
                  SDL_Surface* surface;
                  unsigned bgColor;
          
              public:
                  Renderer();
          
                  bool Init(unsigned width, unsigned height);
                  void SetBackground(unsigned r, unsigned g, unsigned b);
                  unsigned ToColor(unsigned r, unsigned g, unsigned b);
          
                  void Render(Snake* snake);
          };
          
          #endif // RENDERER_H
          
          

           

          renderer.cpp

          #include "renderer.h"
          
          
          Renderer::Renderer() {
            bgColor = 0;
          }
          
          bool Renderer::Init(unsigned width, unsigned height) {
            if (SDL_Init(SDL_INIT_VIDEO) < 0) {
              std::cerr << "SDL_Init Failed: " << SDL_GetError() << std::endl;
              return false;
            }
          
            surface = SDL_SetVideoMode(width, height, 8, SDL_SWSURFACE); //SDL_HWSURFACE | SDL_DOUBLEBUF);
            if (surface == NULL) {
              std::cerr << "SDL_SetVideoMode Failed: " << SDL_GetError() << std::endl;
              return false;
            }
          
            screenRect.x = 0;
            screenRect.y = 0;
            screenRect.w = width;
            screenRect.h = height;
          
            SDL_WM_SetCaption("Snake", "Snake");
          
            return true;
          }
          
          unsigned Renderer::ToColor(unsigned r, unsigned g, unsigned b) {
            return SDL_MapRGB(surface->format, r, g, b);
          }
          
          void Renderer::SetBackground(unsigned r, unsigned g, unsigned b) {
            bgColor = this->ToColor(r, g, b);
          }
          
          void Renderer::Render(Snake* snake) {
            SDL_FillRect(surface, NULL, bgColor);
            snake->Render(surface);
            //SDL_Flip(surface);
            SDL_UpdateRects(surface, 1, &screenRect);
            SDL_Delay(20);
          }
          
          

           

          main.cpp

           

          #include <iostream>
          #include <SDL/SDL.h>
          #include "AS3/AS3.h"
          #include "renderer.h"
          #include "globs.h"
          
          int enableRunLoop = 0;
          
          unsigned snakeheadcolor;
          unsigned snakebodycolor;
          unsigned coincolor;
          
          bool isRunning = true;
          
          Renderer* renderer;
          Snake* snake;
          SDL_Event sdlEvent;
          
          extern int *vgl_cur_mx, *vgl_cur_my;
          
          bool updateInput();
          
          void *handleFrame(void *arg) {
            inline_as3(
              "import com.adobe.flascc.CModule;\n"
              "%0 = CModule.activeConsole.mx\n"
              "%1 = CModule.activeConsole.my\n"
              : "=r"(vgl_cur_mx),"=r"(vgl_cur_my) : );
          
            return NULL;
          }
          
          
          extern "C" void engineTick() {
            snake->Update();
          
            if (!updateInput()) {
              isRunning = false;
              return;
            }
          
            renderer->Render(snake);
          
            if(enableRunLoop) {
              // This call blocks until the main worker calls CModule.uithunk()
              // at that point the main thread will run the function pointer
              // *on the main thread* (but with the thread local state setup
              // to mimic the current thread). Once the function finishes on the
              // main thread this thread will be resumed
              avm2_ui_thunk(handleFrame, NULL);
            }
          }
          
          int main(int argc, char* argv[]) {
            enableRunLoop = argc > 0;
          
            renderer = new Renderer();
            if (!renderer->Init(WINDOW_WIDTH, WINDOW_HEIGHT)) {
              return -1;
            }
          
            renderer->SetBackground(0, 64, 0);
          
            snake = new Snake(
              renderer->ToColor(255, 0, 0), 
              renderer->ToColor(0, 255, 0), 
              renderer->ToColor(255, 255, 0));
          
          
            if(enableRunLoop) {
              while(isRunning) { 
                engineTick();
              }
            } else {
              AS3_GoAsync(); 
            }
          
          
            //SDL_Quit();
          
          
            return 0;
          }
          
          bool updateInput() {
            while(SDL_PollEvent(&sdlEvent)) {
              switch(sdlEvent.type) {
                case SDL_QUIT: {
                  return false;
                }
                break;
          
          
                case SDL_KEYDOWN: {
                  if (sdlEvent.key.keysym.sym == SDLK_ESCAPE) {
                    return false;
                  }
                  else if (sdlEvent.key.keysym.sym == SDLK_RETURN) {
                    if (snake->IsDead()) {
                      snake->Restart();
                    }
                  }
                }
                break;
              }
            }
          
            return true;
          }
          
          


           

          It's strange that the image is coming through mangled like that. Any ideas?

          • 2. Re: Blank screen when using SDL. What have I done wrong? :-)
            jimb0h Level 1

            Hi MattBolt,

             

            I did manage to get a bit further with this but I haven't had time to investigate a complete fix hence why I haven't posted anything on here (I also completely ran out of steam after hours if not days of hacking!).

             

            I managed to get something to display by having the bitmap in console.as be 1024 x 768 even though the screen I had opened in SDL was 320 x 240. I was seeing black because my 320 x 240 screen was being rendered in the middle of a 1024 x 768 rect and I was only rendering the top left of it (or perhaps just the first 76800 pixels).

             

            Seems encouraging that you managed to get somethign to display. To me the screen corruption looks like a pixel stride problem i.e. the bitmap width in console.as doesn't match the width of your SDL screen (this is a guess BTW)

             

            Hope you crack it! Please let me know if you get anywhere!

            • 3. Re: Blank screen when using SDL. What have I done wrong? :-)
              MattBolt Level 1

              Yeah - that was my guess as well! However, it matches up correctly (800x600). I wonder if I updated to 320x240 or 1024x768, it would display correctly...

               

              There was one other option that I was going to look into. Alex MacDonald with Adobe wrote a great article on the dev connection and links to flascc ported libs on github: https://github.com/alexmac/alcextra

               

              I'm not sure that the SDL related libraries here are different than the SDL that ships with FlasCC, but I figured it was worth tinkering with. I'll definitely post back here if I have any luck.

              • 4. Re: Blank screen when using SDL. What have I done wrong? :-)
                jimb0h Level 1

                Hey Matt,

                 

                Are you saying that your console bitmap is 800 x 600 which matches your SDL screen of 800 x 600?

                If so, have you tried 1024 x 768 in your console.as? If you have the same result as me, your game should render in the centre of the 1024 x 768 (even though the SDL screen is 800 x 600)

                 

                Jim

                • 5. Re: Blank screen when using SDL. What have I done wrong? :-)
                  jimb0h Level 1

                  Just as a test I made sure my compile arguments included '-swf-size=320x240' and set my bitmap to 320 x 240 and I got a black screen. I then set my console.as bitmap back to 1024 x 768 but kept the swf size to 320. The result was a 320 x 240 swf which contained a 1024 x 768 bitmap which if I resized the player to reveal the whole bitmap showed my stuff rendering in the centre.

                   

                  ..... weird .... no idea where it's getting this 1024 x 768 from! I could have overlooked something but I've been all over this a million times now :-D

                  • 6. Re: Blank screen when using SDL. What have I done wrong? :-)
                    MattBolt Level 1

                    Oh wow! Amazingly, I used -swf-size=800x600, (SDL dimensions were 800x600 as well), but then I used my bitmap/console size as 1024x768, and here were my results:

                     

                    2013-05-30_1433.png

                     

                    I'm at a complete loss as to why this is the case. Perhaps the vgl buffer which it's pulling the render data from is a hard-coded size. I'm going to update the remaining dimensions to 1024x768 to see if that gets rid of the black border.

                    • 7. Re: Blank screen when using SDL. What have I done wrong? :-)
                      MattBolt Level 1

                      And we have a winner! I updated the SDL dimensions to 1024x768 and also -swf-size=1024x768 ... It seems that 1024x768 arethe magic dimensions. There are most likely ways to account for this now that we have an idea of what's going on. However, it does seem like a bug that the __avm2_vgl_argb_buffer size is constant.

                       

                      I may push my luck later and see what happens if I make it larger than 1024x768 and make my console smaller

                      • 8. Re: Blank screen when using SDL. What have I done wrong? :-)
                        jimb0h Level 1

                        Nice one! Yeah I reckon the buffer size is hard coded too as I can't see 1024x768 anywhere.

                         

                        Embarrassingly it took me nearly a week to work that out as I didn't have any screen corruption or anything to give me a clue, just a black screen! I couldn't understand why Quake worked when suddenly it dawned on me :-O

                         

                        For some reason in the project I'm trying to get working it's only rendering the first pixel (I believe) across the whole screen so I'm only seeing a solid coloured rect. I know it's definitely writing the whole screen into the SDL buffer because if I direcly draw the contents of the surface everything is there albeit the wrong colour as it hasn't gone through the colour conversion.

                         

                        Good luck with your project and let me know if you manage to change the VGL buffer size

                         

                        Or maybe someone from Adobe could give us a hand.....

                        • 9. Re: Blank screen when using SDL. What have I done wrong? :-)
                          jimb0h Level 1

                          I've managed to get my test project to render the whole screen instead of just rendering the first pixel across the entire screen by setting the colour depth to 8!!

                           

                          I haven't tried displaying any 32bit images yet to see if it's really 8bpp but I have to say having to set the bpp to 8 is fairly misleading.

                           

                          I'm sure it can do more than 8bpp seeing as there are OpenGL demos... or is it that to render anything above 8bpp you have to render to an openGL texture?

                           

                          Anyone? :-)

                          • 10. Re: Blank screen when using SDL. What have I done wrong? :-)
                            MattBolt Level 1

                            It's like they got it to work for the quake demo, then just abandoned it.

                             

                            I changed the BPP to 32, and I got the green background, but that was it. Then I tried 16, and it worked, but the performance was somewhat sluggish; here's why:

                             

                            https://dl.dropboxusercontent.com/u/2297377/1second-render.png

                             

                            The bottleneck is always the copy. That part hasn't changed since the alpha version of Alchemy. It's really quite frustrating. Since the OpenGL stuff uses Stage3D, it's not a problem, but as long as we're rendering directly to a bitmap, anything over 8 is probably going to suck wind.

                            • 11. Re: Blank screen when using SDL. What have I done wrong? :-)
                              jimb0h Level 1

                              I'm not getting too bad a frame rate on the thing I'm working on and I'm now running it on 16bpp. What spec is your machine? 970ms is AGES!

                               

                              Also what profiler are you using BTW? I can try it on my project and see what figures I get...

                              • 12. Re: Blank screen when using SDL. What have I done wrong? :-)
                                dawgfoto

                                It's also unclear where the __avm2_vgl_argv_buffer is actually defined, neither in libSDL.a nor in libvgl.a.

                                What worked for me is to use the surface->pixels field instead.

                                • 13. Re: Blank screen when using SDL. What have I done wrong? :-)
                                  MattBolt Level 1

                                  the buffer is defined here:

                                  https://github.com/adobe-flash/crossbridge/blob/master/posix/vgl.c

                                   

                                  It's also in the distribution of flascc/crossbridge as well - i think it's in sdk/usr/share/vgl.c