14a15,33
> 
> /////////////////////////////
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <unistd.h>
> #include <netinet/in.h>
> #include <sys/socket.h>
> #include <arpa/inet.h>
> /////////////////////////////
> //
> //
> 
> /**/
> int sanity=0;
> int portNumber;
> int sockfd;
> /**/
> 
24a44,58
> // Define types of requests
> #define GETNEWFRAME 0x0
> #define ZOOMIN      0x2
> #define ZOOMOUT     0x3
> #define MOVERIGHT   0x4
> #define MOVEUP      0x5
> #define MOVELEFT    0x6
> #define MOVEDOWN    0x7
> #define TERMINATE   0x8
> #define MOUSE       0x9
> #define CLICK       0x1
> #define MOTION      0x2
> #define LEFTCLICK   0x0
> #define RIGHTCLICK  0x1
> 
28,29c62,64
< //Source image on the host side
< uchar4 *h_Src;
---
> //Mandelbrot data
> uchar4 * mandelbrot_data;
> uchar4 * gpu_mandelbrot_data;
64a100,102
> // Environment Variables
> int rec_width, rec_heigh, max_pass = 8;
> 
93,94c131,132
< // OpenGL display function
< void displayFunc(void)
---
> // OpenGL update function
> void update(void)
95a134
> //    uchar4 *d_dst = NULL;
105,138c144,162
<     if (animationStep) {
<         animationFrame -= animationStep;
<         pass = 0;
<     }
< #if RUN_TIMING
<     pass = 0;
< #endif
< #if RUN_CPU
<     if (pass < 128) {
<         int startPass = pass;
<         uchar4 *d_dst = NULL;
<         float xs, ys;
<         cutResetTimer(hTimer);
<         CUDA_SAFE_CALL(cudaGLMapBufferObject((void**)&d_dst, gl_PBO));
< 
<         // Get the anti-alias sub-pixel sample location
<         GetSample(pass & 127, xs, ys);
< 
<         // Get the pixel scale and offset
<         double s = scale / (double)imageW;
<         double x = (xs - (double)imageW * 0.5f) * s + xOff;
<         double y = (ys - (double)imageH * 0.5f) * s + yOff;
< 
<         // Run the mandelbrot generator
<         if (pass && !startPass) // Use the adaptive sampling version when animating.
<             RunMandelbrotDSGold1(h_Src, imageW, imageH, crunch, x, y, s, colors, pass++, animationFrame);
<         else
<             RunMandelbrotDSGold0(h_Src, imageW, imageH, crunch, x, y, s, colors, pass++, animationFrame);
<         CUDA_SAFE_CALL(cudaMemcpy(d_dst, h_Src, imageW * imageH * sizeof(uchar4), cudaMemcpyHostToDevice));
<         CUDA_SAFE_CALL(cudaGLUnmapBufferObject(gl_PBO));
< #if RUN_TIMING
<         printf("CPU = %5.8f\n", 0.001f * cutGetTimerValue(hTimer));
< #endif
<     }
---
>         
>     do {
> 	    // Render anti-aliasing passes until we run out time (60fps approximately)
> 	    float xs, ys;
> 
> 	    // Get the anti-alias sub-pixel sample location
> 	    GetSample(pass & 127, xs, ys);
> 
> 	    // Get the pixel scale and offset
> 	    double s = scale / (float)imageW;
> 	    double x = (xs - (double)imageW * 0.5f) * s + xOff;
> 	    double y = (ys - (double)imageH * 0.5f) * s + yOff;
> 
> 	    // Run the mandelbrot generator
> 	    RunMandelbrot0(gpu_mandelbrot_data, imageW, imageH, crunch, x, y, s, colors, pass++, animationFrame);
> 	    cudaThreadSynchronize();
>     } while(pass < max_pass);
>     cudaMemcpy(mandelbrot_data, gpu_mandelbrot_data, imageW * imageH * 4 * sizeof(char), cudaMemcpyDeviceToHost);
> } // displayFunc
140,175d163
< #else
<     if (pass < 128) {
<         float timeEstimate;
<         int startPass = pass;
<         uchar4 *d_dst = NULL;
<         cutResetTimer(hTimer);
<         CUDA_SAFE_CALL(cudaGLMapBufferObject((void**)&d_dst, gl_PBO));
< 
<         // Render anti-aliasing passes until we run out time (60fps approximately)
<         do {
<             float xs, ys;
< 
<             // Get the anti-alias sub-pixel sample location
<             GetSample(pass & 127, xs, ys);
< 
<             // Get the pixel scale and offset
<             double s = scale / (float)imageW;
<             double x = (xs - (double)imageW * 0.5f) * s + xOff;
<             double y = (ys - (double)imageH * 0.5f) * s + yOff;
< 
<             // Run the mandelbrot generator
<             if (pass && !startPass) // Use the adaptive sampling version when animating.
<                 RunMandelbrot1(d_dst, imageW, imageH, crunch, x, y, s, colors, pass++, animationFrame);
<             else
<                 RunMandelbrot0(d_dst, imageW, imageH, crunch, x, y, s, colors, pass++, animationFrame);
<             cudaThreadSynchronize();
< 
<             // Estimate the total time of the frame if one more pass is rendered
<             timeEstimate = 0.001f * cutGetTimerValue(hTimer) * ((float)(pass + 1 - startPass) / (float)(pass - startPass));
<         } while ((pass < 128) && (timeEstimate < 1.0f / 60.0f) && !RUN_TIMING);
<         CUDA_SAFE_CALL(cudaGLUnmapBufferObject(gl_PBO));
< #if RUN_TIMING
<         printf("GPU = %5.8f\n", 0.001f * cutGetTimerValue(hTimer));
< #endif
<     }
< #endif
177,185c165,171
<     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imageW, imageH, GL_RGBA, GL_UNSIGNED_BYTE, BUFFER_DATA(0));
<     glBegin(GL_TRIANGLES);
<     glTexCoord2f(0.0f, 0.0f);
<     glVertex2f(-1.0f, -1.0f);
<     glTexCoord2f(2.0f, 0.0f);
<     glVertex2f(3.0f, -1.0f);
<     glTexCoord2f(0.0f, 2.0f);
<     glVertex2f(-1.0f, 3.0f);
<     glEnd();
---
> /**********Network Functions*****************/
> void waitForConnection(int port) {
>    int mySocket; 
>    if((mySocket=socket(PF_INET,SOCK_STREAM,0))==-1) {
>       perror("socket()");
>       exit(1);
>    }
187,188c173,177
< 	glutSwapBuffers();
< } // displayFunc
---
>    int yes=1;
>    if(setsockopt(mySocket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int))==-1) {
>       perror("setsockopt()");
>       exit(1);
>    }
190,330c179,187
< // OpenGL keyboard function
< void keyboardFunc(unsigned char k, int, int)
< {
<     int seed;
<     switch (k){
<         case '\033':
<         case 'q':
<         case 'Q':
<             printf("Shutting down...\n");
<                 CUT_SAFE_CALL(cutStopTimer(hTimer) );
<                 CUT_SAFE_CALL(cutDeleteTimer(hTimer));
<                 CUDA_SAFE_CALL(cudaGLUnregisterBufferObject(gl_PBO));
<                 glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
<                 glDeleteBuffers(1, &gl_PBO);
<                 glDeleteTextures(1, &gl_Tex);
<                 free(h_Src);
<             printf("Shutdown done.\n");
<             exit(0);
<             break;
< 
<         case '?':
<             printf("xOff = %5.8f\n", xOff);
<             printf("yOff = %5.8f\n", yOff);
<             printf("scale = %5.8f\n", scale);
<             printf("detail = %d\n", crunch);
<             printf("color = %d\n", colorSeed);
<             printf("\n");
<             break;
<         
<         case 'r': case 'R':
<             // Reset all values to their defaults
<             xOff = -0.5;
<             yOff = 0.0;
<             scale = 3.2;
<             xdOff = 0.0;
<             ydOff = 0.0;
<             dscale = 1.0;
<             colorSeed = 0;
<             colors.x = 3;
<             colors.y = 5;
<             colors.z = 7;
<             crunch = 512;
<             animationFrame = 0;
<             animationStep = 0;
<             pass = 0;
<             break;
< 
<         case 'c':
<             seed = ++colorSeed;
<             if (seed) {
<                 colors.x = RANDOMBITS(seed, 4);
<                 colors.y = RANDOMBITS(seed, 4);
<                 colors.z = RANDOMBITS(seed, 4);
<             } else {
<                 colors.x = 3;
<                 colors.y = 5;
<                 colors.z = 7;
<             }
<             pass = 0;
<             break;
<         
<         case 'C':
<             seed = --colorSeed;
<             if (seed) {
<                 colors.x = RANDOMBITS(seed, 4);
<                 colors.y = RANDOMBITS(seed, 4);
<                 colors.z = RANDOMBITS(seed, 4);
<             } else {
<                 colors.x = 3;
<                 colors.y = 5;
<                 colors.z = 7;
<             }
<             pass = 0;
<             break;
< 
<         case 'a':
<             if (animationStep < 0)
<                 animationStep = 0;
<             else {
<                 animationStep++;
<                 if (animationStep > 8)
<                     animationStep = 8;
<             }
<             break;
< 
<         case 'A':
<             if (animationStep > 0)
<                 animationStep = 0;
<             else {
<                 animationStep--;
<                 if (animationStep < -8)
<                     animationStep = -8;
<             }
<             break;
< 
<         case 'd':
<             if (crunch < 0x40000000) {
<                 crunch *= 2;
<                 pass = 0;
<             }
<             break;
< 
<         case 'D':
<             if (crunch > 2) {
<                 crunch /= 2;
<                 pass = 0;
<             }
<             break;
< 
<         case '4':	// Left arrow key
< 			xOff -= 0.05f * scale;
<             pass = 0;
< 		    break;
<          
<         case '8':	// Up arrow key
< 			yOff += 0.05f * scale;
<             pass = 0;
< 		    break;
<         
<         case '6':	// Right arrow key
< 			xOff += 0.05f * scale;
<             pass = 0;
< 		    break;
<          
<         case '2':	// Down arrow key
< 			yOff -= 0.05f * scale;
<             pass = 0;
< 		    break;
< 		
<         case '+':
< 			scale /= 1.1f;
<             pass = 0;
< 		    break;
<          
<         case '-':
< 			scale *= 1.1f;
<             pass = 0;
< 		    break;
< 		
< 		default:
< 		    break;
---
>    struct sockaddr_in my_addr;
>    my_addr.sin_family=AF_INET;
>    my_addr.sin_port=htons(port);
>    my_addr.sin_addr.s_addr=INADDR_ANY;
>    memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);
> 
>    if(bind(mySocket,(struct sockaddr*)&my_addr, sizeof(struct sockaddr))==-1) {
>       perror("bind()");
>       exit(1);
332d188
< } // keyboardFunc
334,346c190,193
< // OpenGL mouse click function
< void clickFunc(int button, int, int x, int y)
< {
<     if (button == 0)
<         leftClicked = !leftClicked;
<     if (button == 2)
<         rightClicked = !rightClicked;
<     lastx = x;
<     lasty = y;
<     xdOff = 0.0;
<     ydOff = 0.0;
<     dscale = 1.0;
< } // clickFunc
---
>    if(listen(mySocket,5)==-1) {
>       perror("listen()");
>       exit(1);
>    }
348,352c195,202
< // OpenGL mouse motion function
< void motionFunc(int x, int y)
< {
<     double fx = (double)((x - lastx) / 10) / (double)(imageW);        
<     double fy = (double)((lasty - y) / 10) / (double)(imageW);
---
>    struct sockaddr_in remote_addr;
>    int sin_size=sizeof remote_addr;
>    
>    fprintf(stdout,"Waiting for connection on port %d...\n",port);
>    if((sockfd=accept(mySocket, (struct sockaddr*)&remote_addr, (socklen_t*)&sin_size))==-1) {
>       perror("accept()");
>       exit(1);
>    }
354,372c204,205
<     if (leftClicked) {
<         xdOff = fx * scale;
<         ydOff = fy * scale;
<     } else {
<         xdOff = 0.0f;
<         ydOff = 0.0f;
<     }
<         
<     if (rightClicked)
<         if (fy > 0.0f) {
<             dscale = 1.0 - fy;
<             dscale = dscale < 1.05 ? dscale : 1.05;
<         } else {
<             dscale = 1.0 / (1.0 + fy);
<             dscale = dscale > (1.0 / 1.05) ? dscale : (1.0 / 1.05);
<         }
<     else
<         dscale = 1.0;
< } // motionFunc
---
>    fprintf(stdout, "Accepted connection from %s\n",inet_ntoa(remote_addr.sin_addr));
> }
374,376c207,213
< void idleFunc()
< {
< 	glutPostRedisplay();
---
> void initEnvironmentVariables(void) {
>    int env[3];
>    recv(sockfd, env, 3*sizeof(int), 0);
>    imageW = env[0];
>    imageH = env[1];
>    max_pass = env[2];
>    printf("Received environment variables: imageW = %d, imageH = %d, max_pass = %d\n", imageW, imageH, max_pass);
378a216,337
> void requestLoop() {
> 
>    char requestBuffer[16];
>    int bytesRead,bytesSent;
>    char request;
> 
> //   fprintf(stdout,"Waiting for requests...\n");
>    while(true) {
>       bytesRead=recv(sockfd, (void*)requestBuffer,16 * sizeof(char),0);
>       if(bytesRead==-1) {
>          perror("recv()");
>          exit(0);
>       }
>       if(bytesRead==0) exit(0);
> 
>       request=requestBuffer[0];
> 
>       if(request == GETNEWFRAME) {
>          fprintf(stderr,"New frame requested\n");
> 	 update( );
>          bytesSent=send(sockfd,(void*)mandelbrot_data, imageW * imageH * 4 * sizeof(char),0);
>          if(bytesSent==-1) {perror("send()"); exit(1);}
> //         fprintf(stderr,"Sent %d bytes\n",bytesSent);
>       }
>       else if(request==ZOOMIN) {
> //         fprintf(stdout, "Received request to zoom in\n");
>          scale /= 1.1;
> 	 pass = 0;
>       }
>       else if(request==ZOOMOUT) {
> //         fprintf(stdout, "Received request to zoom out\n");
>          scale *= 1.1;
> 	 pass = 0;
>       }
>       else if(request==MOVELEFT) {
> //         fprintf(stdout, "Received request to move left\n");
>          xOff -= 0.05f * scale;
> 	 pass = 0;
>       }
>       else if(request==MOVERIGHT) {
> //         fprintf(stdout, "Received request to move right\n");
>          xOff += 0.05f * scale;
> 	 pass = 0;
>       }
>       else if(request==MOVEUP) {
> //         fprintf(stdout, "Received request to move up\n");
>          yOff += 0.05f * scale;
> 	 pass = 0;
>       }
>       else if(request==MOVEDOWN) {
> //         fprintf(stdout, "Received request to move down\n");
>          yOff -= 0.05f * scale;
> 	 pass = 0;
>       }
>       else if(request==MOUSE) {
> //         fprintf(stdout, "Received mouse event\n");
> 	 if(requestBuffer[1] == MOTION) {
> 	    int x_y[2];
> 	    memcpy(x_y, &requestBuffer[2], 2*sizeof(int));
> 
> 	    double fx = (double)((x_y[0] - lastx) / 10) / (double)(imageW);
> 	    double fy = (double)((x_y[1] - lasty) / 10) / (double)(imageH);
> 
> 	    if(leftClicked) {
> 	        xdOff = fx * scale;
> 		ydOff = fy * scale;
> 	    }
> 	    else {
> 		xdOff = 0.0f;
> 		ydOff = 0.0f;
> 	    }
> 
> 	    if(rightClicked) {
> 		if(fy > 0.0f) {
> 		    dscale = 1.0 - fy;
> 		    dscale = dscale < 1.05 ? dscale : 1.05f;
> 		}
> 		else {
> 		    dscale = 1.0 / (1.0 + fy);
> 		    dscale = dscale > (1.0 / 1.05) ? dscale : (1.0 / 1.05);
> 		}
> 	    }
> 	    else {
> 		dscale = 1.0;
> 	    }
> 
> //	    fprintf(stdout, "Received a motion event at %d, %d\n", x_y[0], x_y[1]); 
> 	 }
> 	 else if(requestBuffer[1] == CLICK) {
> 	    if(requestBuffer[2] == LEFTCLICK) {
> 	    	leftClicked = !leftClicked;
> 	    }
> 	    else if(requestBuffer[2] == RIGHTCLICK) {
> 		rightClicked = !rightClicked;
> 	    }
> 	    int x_y[2];
> 	    memcpy(x_y, &requestBuffer[3], 2*sizeof(int));
> 
> 	    lastx = x_y[0];
> 	    lasty = x_y[1];
> 
> 	    xdOff = 0.0;
> 	    ydOff = 0.0;
> 	    dscale = 1.0;
> //	    fprintf(stdout, "Received a click event %d, %d, %d\n", requestBuffer[2], x_y[0], x_y[1]); 
> 	 }
> 	 else {
> 	    fprintf(stdout, "Received an incorrect mouse request\n"); 
> 	 }
>       }
>       else if(request==TERMINATE) {
>          fprintf(stdout,"Received request to terminate. Exiting...\n");
>          exit(0);
>       }
>       else {
>          fprintf(stderr,"Received invalid command %d\n",request);
>          exit(1);
>       }
>    }
> }
> 
> 
384,387c343,351
<     CUT_DEVICE_INIT();
< 	imageW = 800;
< 	imageH = 600;
< 	h_Src = (uchar4*)malloc(imageW * imageH * 4);
---
>     if(argc != 2) {
> 	printf("USAGE: %s <port_number>\n", argv[0]);
> 	exit(0);
>     }
>     waitForConnection(atoi(argv[1]));
> 
>     initEnvironmentVariables( );
>     mandelbrot_data = (uchar4*) malloc(imageW * imageH * 4);
>     cudaMalloc((void**)&gpu_mandelbrot_data, imageW * imageH * sizeof(uchar4));
392,455c356,357
<     printf("Data init done.\n");
< 
<     printf("Initializing GLUT...\n");
<         glutInit(&argc, argv);
<         glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
<         glutInitWindowSize(imageW, imageH);
<         glutInitWindowPosition(512 - imageW / 2, 384 - imageH / 2);
<         glutCreateWindow(argv[0]);
<         printf("Loading extensions: %s\n", glewGetErrorString(glewInit()));
<         if(!glewIsSupported(
<             "GL_VERSION_2_0 " 
<             "GL_ARB_pixel_buffer_object "
<             "GL_EXT_framebuffer_object "
<         )){
<             fprintf(stderr, "ERROR: Support for necessary OpenGL extensions missing.");
<             fflush(stderr);
<             return CUTFalse;
<         }
<     printf("OpenGL window created.\n");
< 
<     printf("Creating GL texture...\n");
<         glEnable(GL_TEXTURE_2D);
<         glGenTextures(1, &gl_Tex);
<         glBindTexture(GL_TEXTURE_2D, gl_Tex);
<         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
<         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
<         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
<         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
<         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imageW, imageH, 0, GL_RGBA, GL_UNSIGNED_BYTE, h_Src);
<     printf("Texture created.\n");
< 
<     printf("Creating PBO...\n");
<         glGenBuffers(1, &gl_PBO);
<         glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, gl_PBO);
<         glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, imageW * imageH * 4, h_Src, GL_STREAM_COPY);
<         //While a PBO is registered to CUDA, it can't be used 
<         //as the destination for OpenGL drawing calls.
<         //But in our particular case OpenGL is only used 
<         //to display the content of the PBO, specified by CUDA kernels,
<         //so we need to register/unregister it only once.
<         CUDA_SAFE_CALL( cudaGLRegisterBufferObject(gl_PBO) );
<     printf("PBO created.\n");
< 
<     printf("Starting GLUT main loop...\n");
<     printf("\n");
<     printf("Press [?] to print location and scale\n");
<     printf("Press [q] to exit\n");
<     printf("Press [r] to reset\n");
<     printf("Press [a] or [A] to animate the colors\n");
<     printf("Press [c] or [C] to change the colors\n");
<     printf("Press [d] or [D] to increase/decrease the detail\n");
<     printf("Left mouse button + drag = Scroll\n");
<     printf("Right mouse button + drag = Zoom\n");
<     printf("\n");
<     glutDisplayFunc(displayFunc);
<     glutIdleFunc(idleFunc);
<     glutKeyboardFunc(keyboardFunc);
<     glutMouseFunc(clickFunc);
<     glutMotionFunc(motionFunc);
<     CUT_SAFE_CALL(cutCreateTimer(&hTimer));
<     CUT_SAFE_CALL(cutStartTimer(hTimer));
<     glutMainLoop();
< 
<     CUT_EXIT(argc, argv);
---
> //    printf("Data init done.\n");
>     requestLoop( );
