Information
I wrote my Rhythm game(like DJ Max, Jubeat, etc) code with using C, OpenGL and GLUT.
My custom display function is called every 10ms with glutTimerFunc().
In my display funtion, I used glFlush() to draw notes with single buffer, it shows good speed but has some flickering.
When I changed glFlush() to glutSwapBuffers() with double buffers, its speed getting slower so the timer function is not called every 10ms exactly.
Question
How can I implement faster animation(or re-drawing) without any flickering that refresh the screen at every 10ms?
Here is my code.
Code
Init and start music and game.
void musicStart(int id) {
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(1600, 900);
glutCreateWindow("Rhythm And Lines - Evnas");
glutDisplayFunc(displayMainWindow);
enter code hereglutKeyboardFunc(keyboardMainWindow);
glutKeyboardUpFunc(keyboardUpMainWindow);
glutTimerFunc(10, timerMainWindow, 1);
score = 0;
g_maxNotes = 6000;
myTmpNotes = (TmpNote*)malloc(sizeof(TmpNote)*MAXSIZE);
loadData(id);
initMainWindow();
playMusic(id);
glutMainLoop();
}
display function
void displayMainWindow(){
int tmpIdx=0;
int j,k;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
drawLines();
if (line < g_maxNotes) {
for (j = line; j < line+MAXSIZE; j++) {
strcpy(myTmpNotes[tmpIdx].noteId, g_notes[j].noteId);
myTmpNotes[tmpIdx].timeslice = g_notes[j].timeslice;
myTmpNotes[tmpIdx].originIdx = j;
tmpIdx++;
}
for (k=0; k<=MAXSIZE; k++) {
printNoteGUI(myTmpNotes[k].noteId, k);
}
}
highlightKey();
sprintf(scoreStr, "%d", score);
drawText(MAX_X/2, MAX_Y/2, scoreStr);
//glFlush(); -> Fast but flickering
glutSwapBuffers(); // -> No flickering but slow
}
timer functions that repeats display every 10ms
void timerMainWindow(){
line++;
glutPostRedisplay();
glutTimerFunc(10, timerMainWindow, 1);
}
I have to use only C, OpenGL and GLUT because is my school project's rule.
Related
\
I'm working on code have that simulate Knight rider leds. I want to control Led via bluetooth as i can switch off.
but i tried several things but doesn't work .
any help.
*/I'm working on code have that simulate Knight rider leds. I want to control Led via bluetooth as i can switch off.
but i tried several things but doesn't work .
any help
code:
#include "BluetoothSerial.h"
#include <Adafruit_NeoPixel.h>
#define N_LEDS 8
#define PIN 23
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_LEDS, PIN, NEO_GRB +
NEO_KHZ800);
BluetoothSerial ESP_BT;
int incoming;
int r;
int pos = 0, dir = 1;
void setup() {
strip.begin();
Serial.begin(9600);
ESP_BT.begin("ESP32_LED_Control");
Serial.println("Bluetooth Device is Ready to Pair");
}
void loop() {
strip.setPixelColor(pos - 2, 0x100000); // Dark red
strip.setPixelColor(pos - 1, 0x800000); // Medium red
strip.setPixelColor(pos , 0xFF3000); // Center pixel is brightest
strip.setPixelColor(pos + 1, 0x800000); // Medium red
strip.setPixelColor(pos + 2, 0x100000); // Dark red
strip.show();
delay(85); // control speed
for (r=-2; r<= 2; r++) strip.setPixelColor(pos+r, 0);
pos += dir;
if (pos < 0) {
pos = 1;
dir = -dir;
} else if (pos >= strip.numPixels()) {
pos = strip.numPixels() - 2;
dir = -dir;
}
if (ESP_BT.available()) //Check if we receive anything from Bluetooth
{
incoming = ESP_BT.read(); //Read what we recevive
Serial.print("Received:"); Serial.println(incoming);
}
if (incoming == 48)
{
//Should put here code that works on stop strip led//
ESP_BT.println("LED turned OFF");
}
}
To turn off all LEDs I would do something like:
/**
* Turn off all LEDs
*/
void allBlack()
{
for (uint16_t indexPixel = 0; indexPixel < N_LEDS; indexPixel++)
{
strip.SetPixelColor(indexPixel, 0x000000);
}
strip.show();
}
I know is maybe not the scope of this question, but I recommend to test this library:
https://github.com/Makuna/NeoPixelBus
Since it has a lot of good examples and it would be in my opinion a lot better not to use delay but give a certain time like it's shown on Makuna examples to have more control over the animation.
I also have another animation examples in this small project that is triggered by UDP commands.
#include <stdio.h>
#include <math.h>
#include<time.h>
#include<stdlib.h>
#include <GL/glut.h>
clock_t t;
double X1, Y1, X2, Y2;
void delay(int number_of_seconds)
{
// Converting time into milli_seconds
int milli_seconds = 1000 * number_of_seconds;
// Stroing start time
clock_t start_time = clock();
// looping till required time is not acheived
while (clock() < start_time + milli_seconds)
;
}
float round_value(float v)
{
return floor(v + 0.5);
}
void MP(void)
{
double x,y,p;
x=X1;
y=Y1;
double dx=(X2-X1);
double dy=(Y2-Y1);
p=2*dy-dx;
double steps;
/* Clears buffers to preset values */
glClear(GL_COLOR_BUFFER_BIT);
/* Plot the points */
glBegin(GL_POINTS);
/* Plot the first point */
glVertex2d(x,y);
int k;
/* For every step, find an intermediate vertex */
/* printf("%0.6lf %0.6lf\n",floor(x), floor(y)); */
while(x<X2)
{
if(p>=0)
{
glVertex2d(round_value(x), round_value(y));
y=y+1;
p=p+2*dy-2*dx;
}
else
{
glVertex2d(round_value(x), round_value(y));
p=p+2*dy;
}
x=x+1;
}
glEnd();
glFlush();
}
void LineDDA(void)
{
glClear(GL_COLOR_BUFFER_BIT);
double dx=(X2-X1);
double dy=(Y2-Y1);
double steps;
float xInc,yInc,x=X1,y=Y1;
/* Find out whether to increment x or y */
steps=(abs(dx)>abs(dy))?(abs(dx)):(abs(dy));
xInc=dx/(float)steps;
yInc=dy/(float)steps;
/* Clears buffers to preset values */
glClear(GL_COLOR_BUFFER_BIT);
/* Plot the points */
glBegin(GL_POINTS);
/* Plot the first point */
glVertex2d(x,y);
int k;
/* For every step, find an intermediate vertex */
for(k=0;k<steps;k++)
{
x+=xInc;
y+=yInc;
/* printf("%0.6lf %0.6lf\n",floor(x), floor(y)); */
glVertex2d(round_value(x), round_value(y));
}
glEnd();
glFlush();
}
void Init()
{
/* Set clear color to white */
glClearColor(1.0,1.0,1.0,0);
/* Set fill color to black */
glColor3f(0.0,0.0,0.0);
/* glViewport(0 , 0 , 640 , 480); */
/* glMatrixMode(GL_PROJECTION); */
/* glLoadIdentity(); */
gluOrtho2D(0 , 640 , 0 , 480);
}
void main(int argc, char **argv)
{
char ch='n';
int choice;
/* Initialise GLUT library */
glutInit(&argc,argv);
/* Set the initial display mode */
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
/* Set the initial window position and size */
glutInitWindowPosition(0,0);
glutInitWindowSize(640,480);
do
{
printf("Enter two end points of the line to be drawn:\n");
printf("\n************************************");printf("\nEnter Point1( X1 , Y1):\n");
scanf("%lf%lf",&X1,&Y1);
printf("\n************************************");
printf("\nEnter Point1( X2 , Y2):\n");
scanf("%lf%lf",&X2,&Y2);
glFlush();
/* Create the window with title "DDA_Line" */
printf("!----------------Menu---------------!\n");
printf("!---------------1.DDA---------------!\n");
printf("!------------2.Brehanham------------!\n");
scanf("%d",&choice);
glutCreateWindow("Compare b/w DDA and Bresenham");
/* Initialize drawing colors */
Init();
/* Call the displaying function */
t=clock();
if(choice==1)
glutDisplayFunc(LineDDA);
else if(choice==2)
glutDisplayFunc(MP);
else
printf("\nWrong choice");
t=clock()-t;
double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds
printf("Algorithm took %f seconds to execute \n", time_taken);
printf("Question?\n");
scanf(" %c",&ch);
delay(3000);
glutDestroyWindow(1);
}while(ch=='Y');
/* Keep displaying until the program is closed */
glutMainLoop();
}
I am trying to implement comparison between to algorithms. (Midpoint and DDA). But when I try to open the window it takes screenshot of background instead of the actual algorithm. How do I flush the frame buffer to avoid this? I put glFlush in multiple places but that does not seem to do the trick.
Any help would be deeply appreciated.
I am afraid you misunderstand how to use GLUT.
What glutMainLoop does is invoke your set glutDisplayFunc every time the window is asked to repaint.
What you describe as "taking a screenshot of the background" is actually "my window is not being repainted".
One way forward is as follows:
First collect all user input (coordinates and drawing mechanism) and store them in memory (global variables will do, initially).
Next, set your glutDisplayFunc to a function of your own that will render the stored inputs to screen, keeping in mind the drawing algorithm selected by the user.
Finally, enter the glutMainLoop. This will run until the user exits the program, at which point the loop will exit and you can destroy the window.
I'm working on an application in Visual Studio 2010 and I'm coding in C++/CLI.
In my previous questions I had issue with data series from a serial port. Now it seems ok and now I'm trying to plot them.
I don't want to use Chart, so I would like to use handmade functions that use the class Graphics. In order to test my code, I created two arrays: the first one is filled with values coming from a Gaussian. The second one is filled with random numbers.
When I plot the values, I would like to see my plot growing and updating just like an oscilloscope. The second Do_Plot manages to "remove point" plotting them by the BackColor.
All the code works as intended but I'm experiencing problem with performances. If I run the code on my Pc, my series is plotted every 500/700 ms.
Sometimes it slows down to 1500ms and then it comes back faster.
I tried to run the code on my coworkers' Pc and I noticed the series is plotted every 170ms on the first one, whereas the series is plotted every 950ms on the second one.
This is the code:
System::Void Form1::button1_Click(System::Object^ sender, System::EventArgs^ e) {
button1->Enabled = false;
array<float,1>^ Gauss = gcnew array<float,1>(1001);
array<float,1>^ Rumore = gcnew array<float,1>(1001);
/*Some useful variables*/
Random^ generatore = gcnew Random;
float a = safe_cast<float>(Math::Round(5/(SIGMA*Math::Sqrt(2*PI)), 2));
float b = safe_cast<float>(2*(SIGMA*SIGMA));
/*Start */
float portante;
float r;
float s;
int convX =1000/1000;
int convY =500/2;
/*time variables */
int bias = 50;
int dif =600;
/*Gap between drawing and removing*/
int k = 3;
int e1 = 0;
for ( ; ; ) {
/*Start*/
clock_t Start = clock();
if(textBox1->Text==""){
portn = 5;
}
else
portn = float::Parse(textBox1->Text);
/*temp variables to go out the for cycle */
portante = portn;
r = rand;
s = sig;
/ckeck state is OK */
check = 0;
for(int i = 1; i<=1000; i++) {
Gauss[i] = safe_cast<float>(Math::Round( a*s*Math::Exp(-Math::Pow(((0.01*1*(i))-portante), 2)/b), 2));
Rumore[i] = safe_cast<float>(Math::Round(r*generatore->NextDouble(), 2));
bool clipSup = ClipSup(2, Gauss[i]+Rumore[i]);
if(clipSup==true) {
Gauss[i] = 1.99f;
Rumore[i] = 0;
}
Do_Plot(g, disegna, i-1, Gauss[i-1]+Rumore[i-1], i, Gauss[i]+Rumore[i], convX, convY);
e1 =(k+i)%1000;
Do_Plot(g, rimuovi, e1, Gauss[e1]+Rumore[e1], e1+1, Gauss[e1+1]+Rumore[e1+1], convX, convY);
/*Ckeck if go out for cycle*/
if(check == CODE_1 ) {
portante = portn;
break;
}
if(check == CODE_2 ) {
r = rand;
break;
}
if(check == CODE_3 ) {
s = sig;
break;
}
}
clock_t Stop = clock();
int Diff = Stop-Start;
label8->Text = Convert::ToString(Diff);
int tempDiff = (Stop-Start)+bias;
if(tempDiff>dif)
{
//Do_Axes(g); /*Do Axes*/
//Do_Grid(g); /*Do Grid */
Application::DoEvents();
dif = 600;
bias = 0;
}
else
bias +=50; //Else bias grows
}
}
Where Do_Plot is:
void Do_Plot(Graphics^ g, Pen^ penna, int Xi, float Yi, int Xf, float Yf, int convX, int convY) {
g->DrawLine(penna, (convX*Xi+50), safe_cast<int>(500-(Yi*convY)+50),
(convX*Xf+50), safe_cast<int>(500-(Yf*convY)+50));
}
I have declared Graphics^ g here:
public ref class Form1 : public System::Windows::Forms::Form
{
Graphics^ g;
public:
Form1(void)
{
InitializeComponent();
//
//TODO: aggiungere qui il codice del costruttore.
//
g = pictureBox1->CreateGraphics();
}
Onestly I don't know why my code works so differently when it runs on another Pc. I think the problem is g = pictureBox1->CreateGraphics(); but I'm just doing some hypothesis. Any kind of help would be really appreciated cause I'm stuck on this one since the previous week!!
Thanks a lot!
Emiliano
I am going to give you the code in c/c++. Will then find how to do it in c++/cli
First initialize the objects we will use (begining of button_click):
RECT rt = {0, 0, 1200, 600};
HBITMAP hBitmap = NULL;
HPEN hLinePen = NULL;
HDC hdcPctrBox = NULL, hdc = NULL, hdcMemTempImage = NULL;
HBRUSH hBrush = NULL;
POINT arrayPnt[1000]; //array of points
hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
hdcPctrBox = GetWindowDC(hwndPctrBox); //hwndPctrBox is the handle of picturebox
hdcMemTempImage = CreateCompatibleDC(hdc);
hBitmap = CreateCompatibleBitmap(hdc, 1200, 600);
SelectObject(hdcMemTempImage, hBitmap);
hLinePen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); //width of pen = 1,and color (255, 0, 0)
SelectObject(hdcMemTempImage, hLinePen);
hBrush = CreateSolidBrush(RGB(100, 100, 255)); //color of picturebox
Then:
for ( ; ; ) {
/*Start*/
clock_t Start = clock();
FillRect(hdcMemTempImage, &rt, hBrush); //clear the hdcMemTempImage with the picturebox color
//your code continues...
In the for(int i = 1; i<=1000; i++) add one point at a time:
arrayPnt[i - 1].x = X; //calculate X
arrayPnt[i - 1].x = Y; ////calculate Y
And finaly we draw it, after the for loop and before the clock_t Stop (we dont need the Do_Plot()):
Polyline(hdcMemTempImage, &arrayPnt, 1000);
BitBlt(hdcPctrBox, 0, 0, 1200, 600, hdcMemTempImage, 0, 0, SRCCOPY);
clock_t Stop = clock();
//your code continues...
EDIT: use your original code(you dont need rt, hBitmap, hBrush, hdcMemTempImage, arrayPnt and hdc) and instead of calling Do_Plot() add this code:
//create two pens, one with the color you want hLinePen, and another with the color of picturebox hLinePenErase
//inside for(int i = 1; i<=1000; i++)
(some code...)
if(clipSup==true) {
Gauss[i] = 1.99f;
Rumore[i] = 0;
}
SelectObject(hdcPctrBox, hLinePen); //the pen to draw the line
MoveToEx(hdcPctrBox, xStart, yStart, NULL); //start point of line
LineTo(hdcPctrBox, xEnd, yEnd); //end point of line
SelectObject(hdcPctrBox, hLinePenErase); //the pen to erase the line
MoveToEx(hdcPctrBox, xStartErase, yStartErase, NULL); //start point of line to erase
LineTo(hdcPctrBox, xEndErase, yEndErase); //end point of line to erase
(code continues...)
To delete your resources:
HPEN hLinePen = NULL, hLinePenErase = NULL, originalPen = NULL;
HDC hdcPctrBox = NULL;
hdcPctrBox = GetWindowDC(hwndPctrBox); //hwndPctrBox is the handle of picturebox
originalPen = SelectObject(hdcPctrBox, GetStockObject(DC_PEN));
//create the two pens
//in the end release resources
SelectObject(hdcPctrBox, originalPen);
DeleteObject(hLinePen);
DeleteObject(hLinePenErase);
ReleaseDC(hwndPctrBox, hdcPctrBox);
valter
I suggest to implement your own painting class. Derive your own class from "Panel" or "UserControl" and do the following in the constructor, which activates double buffering and optimized drawing:
public ref class MyPaintControl : public System::Windows::Forms::UserControl
{
public:
MyPaintControl()
{
this->SetStyle(System::Windows::Forms::ControlStyles::AllPaintingInWmPaint, true);
this->SetStyle(System::Windows::Forms::ControlStyles::DoubleBuffer, true);
this->SetStyle(System::Windows::Forms::ControlStyles::ResizeRedraw, true);
this->SetStyle(System::Windows::Forms::ControlStyles::UserPaint, true);
}
// And then implement your painting in OnPaint:
protected:
virtual void OnPaint(PaintEventArgs^ e)
{
// Do painting...
System::Drawing::Brush^ br = gcnew System::Drawing::SolidBrush(this->BackColor);
e->Graphics->FillRectangle(br, this->ClientRectangle);
delete br;
// Do other paintings...
}
// This function might be called if new data arrived...
public:
void UpdateArea(int daten) // pass data here, if you want...
{
// Store the data in a member variable...
// force a redraw:
this->InvalidateRect(); // this will force a "OnPaint"
}
}
Then embedd this control in your UI. This should improve your painting very much!
Also this works, even if you move or resize your window. Be aware, that painting should always be done in "OnPaint"!
I would like to update the state of my coding.
I used the method posted by Jochen. It is very fast but it does not suit my application or maybe I'm not able to adapt it. What I need to do, is to update constantly my plot. At time t0, I should draw a line. At time t1, when I store a new line, I should draw the new line and add this to the previous one. The plot must be "alive". I tried to derive a panel class and override the OnPaintevent but my plot refreshing only if all lines are stored and displayed.
I have picked up 'Learning OpenCV' and have been trying some of the code examples/exercises. In this code snippet, I want to get the slider to update its position with each video frame change, but for some reason it is slowing down the video playback speed.
The slider is updating the position during video playback using cvSetTrackbarPos() function but it is making the playback very slow.
#include <cv.h>
#include <highgui.h>
using namespace std;
int g_slider_position = 0;
CvCapture *g_capture = NULL;
void onTrackbarSlide(int pos)
{
cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);
}
int main(int argc, char *argv[])
{
if(argc<2)
{
printf("Usage: main <video-file-name>\n\7");
exit(0);
}
// create a window
cvNamedWindow("Playing Video With Slider", CV_WINDOW_AUTOSIZE);
g_capture = cvCreateFileCapture(argv[1]);
int frames = (int) cvGetCaptureProperty(g_capture, \
CV_CAP_PROP_FRAME_COUNT);
if(frames !=0)
{
cvCreateTrackbar("Slider","Playing Video With Slider", \
&g_slider_position,frames, onTrackbarSlide);
}
IplImage* frame = 0;
while(1)
{
frame = cvQueryFrame(g_capture);
if(!frame)
{
break;
}
cvShowImage("Playing Video With Slider", frame);
cvSetTrackbarPos("Slider","Playing Video With Slider", \
g_slider_position+1); //Slowing down playback
char c= cvWaitKey(33);
if(c == 27)
{
break;
}
}
// release the image
cvReleaseImage(&frame );
cvReleaseCapture(&g_capture);
// Destroy Window
cvDestroyWindow("Playing Video With Slider");
return 0;
}
This is an inefficiency in how opencv displays trackbars (the same problem occurs even if you don't update the slider, and in case when you refer to non-changing variable outside the processing loop).
A workaround might be to display the trackbar in a separate window.
Line char c= cvWaitKey(33); have problem.
It is in while(1) and every time it takes 33 milisecond to Wait for a pressed key.Make this number lesser.
EDITED LATER:
Make change as shown below
void onTrackbarSlide(int pos)
{
pos = g_slider_position;
cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);
}
The problem is that every time You call cvSetTrackbarPos("Slider","Playing Video With Slider", g_slider_position+1); callback onTrackbarSlide changing the video position another time and slowing down the program flow.
The way I find out to avoid that is with a flag. It tells the callback if the change in the Trackbar is produced by the normal update flow or is produced by You.
int g_slider_position = 0;
int g_update_slider = 0;//flag
CvCapture *g_capture = NULL;
void onTrackbarSlide(int pos)
{
if (!g_update_slider)//if not changed by the video flow
{
cvSetCaptureProperty(
g_capture,
CV_CAP_PROP_POS_FRAMES,
pos
);
}
}
void updateSlider(int pos)
{
g_update_slider = 1; //Changed by the video flow
cvSetTrackbarPos("Position", "Example3", pos);
g_update_slider = 0; //Returns the flag when the change is performed
}
In the main I call for updateSlider instead of cvSetTrackbarPos.
I've been trying to flip surfaces and have been successful if I'm only flipping a single surface (the same surface I got back from SDL_SetVideoMode). If I try to flip the surface I get back from SDL_DisplayFormat, nothing happens. I've attached demo code that demonstrates my problem:
#include <stdio.h>
#include <stdlib.h>
#include "SDL/SDL.h"
void main()
{
int i;
SDL_Surface *mysurface1;
SDL_Surface *mysurface2;
char *pxl;
SDL_Init( SDL_INIT_EVERYTHING );
mysurface1 = SDL_SetVideoMode( 640, 480, 8, SDL_DOUBLEBUF|SDL_HWSURFACE );
for (i = 0; i < 20; i++)
{
pxl = (char *)mysurface1->pixels + i*mysurface1->pitch + i;
*pxl = 100; // Red Line
}
SDL_Flip(mysurface1); // Works, we see a red line
sleep(5);
printf("Sleeping for 5...\n");
mysurface2 = SDL_DisplayFormat(mysurface1);
for (i = 0; i < 20; i++)
{
pxl = (char *)mysurface2->pixels + i*mysurface2->pitch + i;
*pxl = 255; // White line
}
SDL_Flip(mysurface2); // White line doesnt appear
printf("Done... No white line\n");
sleep(10);
}
Has anyone ever seen this before? Again, I think I tracked it down to surfaces that wont display if its a surface I got back from SDL_DisplayFormat. If I do it on the surface I get back from SDL_SetVideoMode, then I see the red line and everything works fine.
You can only flip the main display surface (the one created with SDL_SetVideoMode). In order to make your other surface visible, you need to blit it onto the main surface. Lookup SDL_BlitSurface for details on how to do that.
Pass the screen to the SDL_Flip function. The flip function modifies the value of screen->pixels so that it points to the surface that isn't visible on the screen.
However, this is only applicable to video devices such as SVGA and DGA. On X11, calling SDL_Flip(screen) is equivalent to calling SDL_UpdateRect(screen, 0, 0, 0, 0).
#include <stdio.h>
#include <stdlib.h>
#include "SDL/SDL.h"
void main()
{
int i;
SDL_Surface *screen;
char *pxl;
SDL_Init( SDL_INIT_EVERYTHING );
screen = SDL_SetVideoMode( 640, 480, 8, SDL_DOUBLEBUF|SDL_HWSURFACE );
printf("Drawing the red line ...\n");
printf("screen->pixels = %p\n", screen->pixels);
for (i = 0; i < 100; i++)
{
pxl = (char *)screen->pixels + i*screen->pitch + i;
*pxl = 100; // Red Line
}
printf("Flip screens\n");
SDL_Flip(screen); // Display the red line
printf("Drawing the white line ...\n");
printf("screen->pixels = %p\n", screen->pixels);
for (i = 0; i < 100; i++)
{
pxl = (char *)screen->pixels + i*screen->pitch + i;
*pxl = 255; // White line
}
sleep(3);
printf("Flip screens\n");
SDL_Flip(screen); // Display the white line
sleep(10);
}
On my Linux notebook, this prints:
Drawing the red line ...
screen->pixels = 0xb6c8c008
Flip screens
Drawing the white line ...
screen->pixels = 0xb6c8c008
Flip screens
The value of screen->pixels is the same, but this is only because on X11 the flip operation is a no-operation. On a video device such as SVGA or DGA, the two values would be different.
First, it seems SDL_Flip() only works on surfaces that correspond to the screen or a window, like those created by SDL_SetVideoMode(). Your other surface is off-screen; it doesn't make much sense to double-buffer it (or flip it), and it most likely isn't double-buffered anyway. Being an off screen surface, it won't appear until you blit it to your display surface with SDL_BlitSurface() or a similar function -- then, the changes will be visible next time you flip the display surface.
Essentially, mysurface2 isn't actually on your display until you put it there, by blitting it onto a surface that is on your display. If you replace the following:
SDL_Flip(mysurface2); // White line doesnt appear
With this:
SDL_BlitSurface(mysurface2,NULL,mysurface1,NULL);
SDL_Flip(mysurface1);
...then your code will probably work as you expect.