int main(int argc, char **argv) { // init global vars initSharedMem(); // register exit callback atexit(exitCB); // init GLUT and GL glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL); glutInitWindowSize(screenWidth, screenHeight); glutInitWindowPosition(200, 200); int handle = glutCreateWindow(argv[0]); glutDisplayFunc(displayCB); glutReshapeFunc(reshapeCB); glutKeyboardFunc(keyboardCB); glewInit(); if (glewIsSupported("GL_VERSION_2_1")) { MYLOG("Ready for OpenGL 2.1\n"); } else { MYLOG("OpenGL 2.1 not supported\n"); exit(1); } if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader && GL_EXT_geometry_shader4) { MYLOG("Ready for GLSL - vertex, fragment, and geometry units\n"); } else { MYLOG("Not totally ready :( \n"); exit(1); } initRS(); glutMainLoop(); return 0; }
int main(int argc, char **argv) { ACQ_MessagePacketType *packet; int currentPacket, intSlot; int lastId; int numChannels, numSamples, sampleNumber; host_t host; pthread_t tcpserverThread, convertThread; /* Parse command line arguments */ if (argc == 1) { /* Put defaults in case no arguments given */ strcpy(host.name, "-"); host.port = 1972; } else if (argc == 3) { strncpy(host.name, argv[1], sizeof(host.name)); host.name[sizeof(host.name)-1]=0; host.port = atoi(argv[2]); if (host.port <= 0) { fputs("Port number must be positive\n\n",stderr); fputs(usage, stderr); return 1; } } else { fputs(usage, stderr); return 1; } /* Create socket pair */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, mySockets)) { perror("Could not create socket pair for internal communication: "); return 1; } /* Internal ringbuffer uses same mechanism as Acq: free slots are marked with ACQ_MSGQ_INVALID. To avoid polling in the converter thread, the main thread sends the index of the latest slot over the socket pair. If the converter thread does not manage to clear the ringbuffer quickly enough, the program will report an error. */ for (intSlot=0;intSlot<INT_RB_SIZE;intSlot++) { intPackets[intSlot].message_type = ACQ_MSGQ_INVALID; } /* Spawn conversion thread */ if (pthread_create(&convertThread, NULL, dataToFieldTripThread, NULL)) { fprintf(stderr, "Could not spawn conversion thread\n"); return 1; } /* Spawn tcpserver or connect to remote buffer */ if (strcmp(host.name, "-") == 0) { int rc; rc = pthread_create(&tcpserverThread, NULL, tcpserver, &host); if (rc) { fprintf(stderr, "Could not spawn tcpserver thread (%d)\n", rc); return 1; } ftSocket = 0; /* dma */ } else { ftSocket = open_connection(host.name, host.port); if (ftSocket < 0) { fprintf(stderr, "Could not connect to remote buffer\n"); return 1; } } printf("Trying to set up shared memory...\n"); packet = createSharedMem(); if (packet == NULL) { fprintf(stderr, "Could not set up shared memory - exiting\n"); exit(1); } initSharedMem(packet); /* register CTRL-C handler */ signal(SIGINT, abortHandler); /* Both ringbuffers start at 0 */ currentPacket = intSlot = 0; printf("Entering main loop. Press CTRL-C to stop operation.\n\n"); while (keepRunning) { int size; char *dataset; int code = waitPacket(&packet[currentPacket].message_type); switch(code) { case ACQ_MSGQ_SETUP_COLLECTION: lastId = packet[currentPacket].messageId; dataset = (char *) packet[currentPacket].data; printf("Setup | ID=%i | %.255s\n", lastId, dataset); size = 5*sizeof(int) + strlen(dataset) + 1; if (size >= sizeof(ACQ_MessagePacketType)) { fprintf(stderr, "Dataset name not zero-terminated -- ignoring\n"); continue; } if (intPackets[intSlot].message_type != ACQ_MSGQ_INVALID) { fprintf(stderr, "Internal converter thread does not keep up with the load.\n"); } else { memcpy(&intPackets[intSlot], &packet[currentPacket], size); write(mySockets[0], &intSlot, sizeof(int)); if (++intSlot == INT_RB_SIZE) intSlot=0; } packet[currentPacket].message_type = ACQ_MSGQ_INVALID; if (++currentPacket == ACQ_MSGQ_SIZE) currentPacket=0; break; case ACQ_MSGQ_DATA: lastId = packet[currentPacket].messageId; numChannels = packet[currentPacket].numChannels; numSamples = packet[currentPacket].numSamples; sampleNumber = packet[currentPacket].sampleNumber; printf("Data | %3i channels x %3i samples | nr = %6i | ID=%4i | slot=%3i\n", numChannels, numSamples, sampleNumber, lastId, currentPacket); size = 5*sizeof(int) + numSamples*numChannels*sizeof(int); if (size > sizeof(ACQ_OverAllocType)) { fprintf(stderr, "Acq wrote far too much data -- cannot handle this\n"); } else { if (intPackets[intSlot].message_type != ACQ_MSGQ_INVALID) { fprintf(stderr, "Internal converter thread does not keep up with the load.\n"); } else { memcpy(&intPackets[intSlot], &packet[currentPacket], size); write(mySockets[0], &intSlot, sizeof(int)); if (++intSlot == INT_RB_SIZE) intSlot=0; } } if (numSamples * numChannels > 28160) { fprintf(stderr, "Warning: Acq wrote too much data into this block!\n"); /* clear this packet */ packet[currentPacket].message_type = ACQ_MSGQ_INVALID; /* next packet last in ringbuffer? */ if (++currentPacket == ACQ_MSGQ_SIZE) { currentPacket = 0; } else { /* make sure the next packet is marked as free */ packet[currentPacket].message_type = ACQ_MSGQ_INVALID; } } else { packet[currentPacket].message_type = ACQ_MSGQ_INVALID; if (++currentPacket == ACQ_MSGQ_SIZE) currentPacket=0; } break; case ACQ_MSGQ_CLOSE_CONNECTION: printf("Stop | ID=%i \n", lastId); /* Does this mean anything for the buffer as well ? */ packet[currentPacket].message_type = ACQ_MSGQ_INVALID; currentPacket = 0; break; case ACQ_MSGQ_INVALID: printf("Waiting (on %i)\n",currentPacket); break; default: fprintf(stderr, "Warning: Unexpected ID in packet %i\n", currentPacket); break; } } printf("Closing sockets / stopping tcpserver...\n"); close(mySockets[0]); /* the other one will be closed in the thread */ if (ftSocket > 0) { close_connection(ftSocket); } else { pthread_cancel(tcpserverThread); pthread_detach(tcpserverThread); } printf("Closing shared memory...\n"); closeSharedMem(packet); printf("Joining conversion thread...\n"); pthread_join(convertThread, NULL); printf("Done.\n"); return 0; }
int main(int argc, char **argv) { ACQ_MessagePacketType *packet; int currentPacket = 0; int numChannels = 356; int blockSize = 70; /* > 28160/356 is too much for regular operation! */ int sampleNumber = 0; int ID = 0; int sampleFreq = 1200; struct timeval timerInterval = {0,50000}; /* 50ms */ struct timeval timerValue = {0,50000}; /* 200ms */ struct itimerval timerOpts; timerOpts.it_value = timerValue; timerOpts.it_interval = timerInterval; if (argc>=2) { sampleFreq = atoi(argv[1]); if (sampleFreq>0) { timerOpts.it_interval.tv_usec = timerOpts.it_value.tv_usec = 1000000*blockSize/sampleFreq; } } printf("Trying to set up shared memory...\n"); packet = createSharedMem(); if (packet == NULL) { fprintf(stderr, "Could not set up shared memory - exiting\n"); exit(1); } initSharedMem(packet); packet[0].messageId = 0; packet[0].sampleNumber = 0; packet[0].numSamples = 0; packet[0].numChannels = numChannels; strcpy((char *)(packet[0].data), "test.ds"); packet[0].message_type = ACQ_MSGQ_SETUP_COLLECTION; currentPacket = 1; printf("Wrote setup packet at 0\n"); usleep(200000); /* 0.2 sec */ setitimer(ITIMER_REAL, &timerOpts, NULL); signal(SIGALRM, alarmHandler); /* register CTRL-C handler */ signal(SIGINT, abortHandler); while (keepRunning) { ++ID; if (packet[currentPacket].message_type != ACQ_MSGQ_INVALID) { printf("Packet #%i not free...\n", currentPacket); break; } packet[currentPacket].messageId = ID; packet[currentPacket].sampleNumber = sampleNumber; packet[currentPacket].numSamples = blockSize; packet[currentPacket].numChannels = numChannels; memset(packet[currentPacket].data, 0, numChannels * blockSize * sizeof(int)); //packet[currentPacket].data[0] = i+1; //packet[currentPacket].data[10*numChannels] = 10; packet[currentPacket].numChannels = numChannels; packet[currentPacket].message_type = ACQ_MSGQ_DATA; printf("Wrote data packet %i at %i\n", ID, currentPacket); sampleNumber += blockSize; if (++currentPacket == ACQ_MSGQ_SIZE) currentPacket = 0; sleep(1); } packet[currentPacket].message_type = ACQ_MSGQ_CLOSE_CONNECTION; usleep(100000); closeSharedMem(packet); return 0; }
int main(int argc, char* argv[]) { struct sockaddr_in client; //Validate input if (argc != 2) { cout << "Usage: panserver <portnumber>" << endl; return -1; } // initialize shared memory initSharedMem(); // Initialize the ports panel.server.sin_port = htons(atoi(argv[1])); audience.server.sin_port = htons(atoi(argv[1])+1); /** Create socket on which to send and receive */ if ( panel.CreatSocket() < 0 ) // create panel socket return -1; if ( audience.CreatSocket() < 0 ) // create panel socket return -1; reusePort(panel.socket_s); //reuse the binding port when execute program if ( panel.BindConnection() < 0 ) // Check for binding errors return -1; reusePort(audience.socket_s);//reuse the binding port when execute program if ( audience.BindConnection() < 0 ) // Check for binding errors return -1; /** get panel port information and prints it out */ if ( panel.GetSocketName() ) // check socket name validity return -1; /** get audience port information and prints it out */ if ( audience.GetSocketName() ) // check socket name validity return -1; /** accept TCP connections from clients and fork a process to serve each */ listen(panel.socket_s,10); listen(audience.socket_s,10); for(;;){ audience_pid = fork(); /* This is the audience server */ if ( audience_pid == 0) { signal (SIGQUIT, SIG_IGN); signal (SIGINT, SIG_IGN); signal (SIGTSTP,SIG_IGN); signal (SIGTERM,SIG_IGN); cout << "Forked AUDIENCE Server, PID=" << getpid() << endl; ServAudience(audience, client); } else { //This is to handle the quit function if (signal(SIGQUIT, CloseMeeting) == SIG_ERR) { fprintf(stderr, "cannot set handler for SIGQUIT\n"); } //list people in the room if (signal(SIGINT, inthandle) == SIG_ERR) { fprintf(stderr, "cannot set handler for SIGINT\n"); } //Handle dead signal if (signal(SIGTERM, SomeoneIsLeaving) == SIG_ERR) { fprintf(stderr, "cannot set handler for SIGTERM\n"); } //Handle ctrl+Z if (signal(SIGTSTP, AllowQA) == SIG_ERR) { fprintf(stderr, "cannot set handler for SIGTSTP\n"); } cout << "AUDIENCE server started at port: (" << ntohs(audience.server.sin_port) << ")" << endl; cout << "PANELIST server started at port: (" << ntohs(panel.server.sin_port) << ")" << endl; ServPanelist(panel, client); } wait(NULL); } }
int main (int argc, char **argv) { #ifdef CLEAR strcpy(table_path, dirname(argv[0])); strcat(table_path, "/"); strcat(table_path, argv[2]); shm_unlink(table_path); #else // verifies if the number of arguments is correct if (argc != 4) { printf("usage: %s <player's name> <table's name> <nr. players>\n", argv[0]); return -1; } if (verifyCmdArgs(argv) == -1) { return -1; } // installs an exit handler if (atexit(exitHandler) == -1) { perror("atexit()"); exit(-1); } blockSignals(); initFIFO(argv[1]); initSharedMem(argv); waitForPlayers(); pthread_t tid; if (is_dealer) { initDefaultDeck(); printCardsList(cards, NULL); shuffleDeck(); randomiseFirstPlayer(); if ((errno = pthread_create(&tid, NULL, dealCards, NULL)) != 0) { perror("pthread_create()"); exit(-1); } } receiveCards(); reorderCardsList(hand); if (is_dealer) { pthread_join(tid, NULL); } //call thread responsible for showing info about the game and manage the game pthread_t tidG; if ((errno = pthread_create(&tidG, NULL, playGame, NULL)) != 0) { perror("pthread_create()"); exit(-1); } pthread_join(tidG, NULL); #endif return 0; }
int main(int argc, char **argv) { initSharedMem(); // register exit callback atexit(exitCB); // init GLUT and GL initGLUT(argc, argv); initGL(); // get OpenGL info glInfo glInfo; glInfo.getInfo(); glInfo.printSelf(); #ifdef _WIN32 // check PBO is supported by your video card if(glInfo.isExtensionSupported("GL_ARB_pixel_buffer_object")) { // get pointers to GL functions glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB"); glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB"); glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB"); glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)wglGetProcAddress("glBufferSubDataARB"); glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)wglGetProcAddress("glDeleteBuffersARB"); glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)wglGetProcAddress("glGetBufferParameterivARB"); glMapBufferARB = (PFNGLMAPBUFFERARBPROC)wglGetProcAddress("glMapBufferARB"); glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)wglGetProcAddress("glUnmapBufferARB"); // check once again PBO extension if(glGenBuffersARB && glBindBufferARB && glBufferDataARB && glBufferSubDataARB && glMapBufferARB && glUnmapBufferARB && glDeleteBuffersARB && glGetBufferParameterivARB) { pboSupported = pboUsed = true; std::cout << "Video card supports GL_ARB_pixel_buffer_object." << std::endl; } else { pboSupported = pboUsed = false; std::cout << "Video card does NOT support GL_ARB_pixel_buffer_object." << std::endl; } } // check EXT_swap_control is supported if(glInfo.isExtensionSupported("WGL_EXT_swap_control")) { // get pointers to WGL functions wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT"); if(wglSwapIntervalEXT && wglGetSwapIntervalEXT) { // disable v-sync wglSwapIntervalEXT(0); std::cout << "Video card supports WGL_EXT_swap_control." << std::endl; } } #else // for linux, do not need to get function pointers, it is up-to-date if(glInfo.isExtensionSupported("GL_ARB_pixel_buffer_object")) { pboSupported = pboUsed = true; std::cout << "Video card supports GL_ARB_pixel_buffer_object." << std::endl; } else { pboSupported = pboUsed = false; std::cout << "Video card does NOT support GL_ARB_pixel_buffer_object." << std::endl; } #endif if(pboSupported) { // create 2 pixel buffer objects, you need to delete them when program exits. // glBufferDataARB with NULL pointer reserves only memory space. glGenBuffersARB(PBO_COUNT, pboIds); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[0]); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, DATA_SIZE, 0, GL_STREAM_READ_ARB); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[1]); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, DATA_SIZE, 0, GL_STREAM_READ_ARB); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); } // start timer, the elapsed time will be used for updateVertices() timer.start(); // the last GLUT call (LOOP) // window will be shown and display callback is triggered by events // NOTE: this call never return main(). glutMainLoop(); /* Start GLUT event-processing loop */ return 0; }
int main(int argc, char **argv) { gfxInitDefault(); PrintConsole botScreen; PrintConsole topScreen; consoleInit(GFX_TOP, &topScreen); consoleInit(GFX_BOTTOM, &botScreen); consoleSelect(&topScreen); constexpr size_t NUM_SAMPLES = 160*200; u32 *audio_buffer = (u32*)linearAlloc(NUM_SAMPLES * sizeof(u32)); fillBuffer(audio_buffer, NUM_SAMPLES); AudioState state; { auto dspfirm = loadDspFirmFromFile(); if (!dspfirm) { printf("Couldn't load firmware\n"); goto end; } auto ret = audioInit(*dspfirm); if (!ret) { printf("Couldn't init audio\n"); goto end; } state = *ret; } state.waitForSync(); initSharedMem(state); state.write().dsp_configuration->mixer1_enabled_dirty = true; state.write().dsp_configuration->mixer1_enabled = true; //state.write().dsp_configuration->limiter_enabled = 1; state.notifyDsp(); printf("init\n"); state.waitForSync(); state.notifyDsp(); state.waitForSync(); for (auto& gain : state.write().source_configurations->config[0].gain) { for (auto& g : gain) { g = 0.0; } } state.write().source_configurations->config[0].gain[0][0] = 1.0; state.write().source_configurations->config[0].gain[1][0] = 1.0; state.write().source_configurations->config[0].gain[1][1] = 0.5; state.write().source_configurations->config[0].gain_1_dirty = true; state.notifyDsp(); state.waitForSync(); state.notifyDsp(); state.waitForSync(); state.notifyDsp(); { while (true) { state.waitForSync(); printf("sync = %i, play = %i, cbi = %i\n", state.read().source_statuses->status[0].sync, state.read().source_statuses->status[0].is_enabled, state.read().source_statuses->status[0].current_buffer_id); if (state.read().source_statuses->status[0].sync == 1) break; state.notifyDsp(); } printf("fi: %i\n", state.frame_id); u16 buffer_id = 0; //unsigned next_queue_position = 0; state.write().source_configurations->config[0].play_position = 0; state.write().source_configurations->config[0].physical_address = osConvertVirtToPhys(audio_buffer); state.write().source_configurations->config[0].length = NUM_SAMPLES; state.write().source_configurations->config[0].mono_or_stereo = DSP::HLE::SourceConfiguration::Configuration::MonoOrStereo::Stereo; state.write().source_configurations->config[0].format = DSP::HLE::SourceConfiguration::Configuration::Format::PCM16; state.write().source_configurations->config[0].fade_in = false; state.write().source_configurations->config[0].adpcm_dirty = false; state.write().source_configurations->config[0].is_looping = false; state.write().source_configurations->config[0].buffer_id = ++buffer_id; state.write().source_configurations->config[0].partial_reset_flag = true; state.write().source_configurations->config[0].play_position_dirty = true; state.write().source_configurations->config[0].embedded_buffer_dirty = true; state.write().source_configurations->config[0].enable = true; state.write().source_configurations->config[0].enable_dirty = true; state.notifyDsp(); bool continue_reading = true; for (size_t frame_count = 0; continue_reading; frame_count++) { state.waitForSync(); if (state.read().source_statuses->status[0].current_buffer_id) { printf("%i cbi = %i\n", frame_count, state.read().source_statuses->status[0].current_buffer_id); } for (size_t i = 0; i < 160; i++) { if (state.write().intermediate_mix_samples->mix1.pcm32[0][i]) { printf("[intermediate] frame=%i, sample=%i\n", frame_count, i); for (size_t j = 0; j < 20; j++) { printf("%08lx ", (u32)state.write().intermediate_mix_samples->mix1.pcm32[0][j]); } printf("\n"); break; } } for (size_t i = 0; i < 160 * 2; i++) { if (state.read().final_samples->pcm16[i]) { printf("[final] frame=%i, sample=%i\n", frame_count, i); for (size_t j = 0; j < 20; j++) { printf("%04x ", (u16)state.read().final_samples->pcm16[j]); } printf("\n"); continue_reading = false; break; } } state.notifyDsp(); } state.waitForSync(); state.write().source_configurations->config[0].sync = 2; state.write().source_configurations->config[0].sync_dirty = true; state.notifyDsp(); while (true) { state.waitForSync(); printf("sync = %i, play = %i\n", state.read().source_statuses->status[0].sync, state.read().source_statuses->status[0].is_enabled); if (state.read().source_statuses->status[0].sync == 2) break; state.notifyDsp(); } state.notifyDsp(); printf("Done!\n"); } end: audioExit(state); waitForKey(); gfxExit(); return 0; }
int main(int argc, char **argv) { // init global vars initSharedMem(); // register exit callback atexit(exitCB); // init GLUT and GL initGLUT(argc, argv); initGL(); // create a texture object glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); //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_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap generation included in OpenGL v1.4 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, 0); // get OpenGL info glInfo glInfo; glInfo.getInfo(); //glInfo.printSelf(); #ifdef _WIN32 // check if FBO is supported by your video card if(glInfo.isExtensionSupported("GL_ARB_framebuffer_object")) { // get pointers to GL functions glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffers"); glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffers"); glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer"); glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatus"); glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)wglGetProcAddress("glGetFramebufferAttachmentParameteriv"); glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)wglGetProcAddress("glGenerateMipmap"); glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)wglGetProcAddress("glFramebufferTexture1D"); glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2D"); glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)wglGetProcAddress("glFramebufferTexture3D"); glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)wglGetProcAddress("glFramebufferTextureLayer"); glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress("glFramebufferRenderbuffer"); glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)wglGetProcAddress("glIsFramebuffer"); glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)wglGetProcAddress("glBlitFramebuffer"); glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)wglGetProcAddress("glGenRenderbuffers"); glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress("glDeleteRenderbuffers"); glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)wglGetProcAddress("glBindRenderbuffer"); glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)wglGetProcAddress("glRenderbufferStorage"); glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)wglGetProcAddress("glRenderbufferStorageMultisample"); glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)wglGetProcAddress("glGetRenderbufferParameteriv"); glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)wglGetProcAddress("glIsRenderbuffer"); // check once again FBO extension if(glGenFramebuffers && glDeleteFramebuffers && glBindFramebuffer && glCheckFramebufferStatus && glGetFramebufferAttachmentParameteriv && glGenerateMipmap && glFramebufferTexture1D && glFramebufferTexture2D && glFramebufferTexture3D && glFramebufferTextureLayer && glFramebufferRenderbuffer && glIsFramebuffer && glBlitFramebuffer && glGenRenderbuffers && glDeleteRenderbuffers && glBindRenderbuffer && glRenderbufferStorage && glRenderbufferStorageMultisample && glGetRenderbufferParameteriv && glIsRenderbuffer) { fboSupported = fboUsed = true; std::cout << "Video card supports GL_ARB_framebuffer_object." << std::endl; } else { fboSupported = fboUsed = false; std::cout << "Video card does NOT support GL_ARB_framebuffer_object." << std::endl; } } // check EXT_swap_control is supported if(glInfo.isExtensionSupported("WGL_EXT_swap_control")) { // get pointers to WGL functions wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT"); if(wglSwapIntervalEXT && wglGetSwapIntervalEXT) { // disable v-sync wglSwapIntervalEXT(0); std::cout << "Video card supports WGL_EXT_swap_control." << std::endl; } } #else // for linux, do not need to get function pointers, it is up-to-date if(glInfo.isExtensionSupported("GL_ARB_framebuffer_object")) { fboSupported = fboUsed = true; std::cout << "Video card supports GL_ARB_framebuffer_object." << std::endl; } else { fboSupported = fboUsed = false; std::cout << "Video card does NOT support GL_ARB_framebuffer_object." << std::endl; } #endif if(fboSupported) { // create a MSAA framebuffer object // NOTE: All attachment images must have the same # of samples. // Ohterwise, the framebuffer status will not be completed. glGenFramebuffers(1, &fboMsaaId); glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId); // create a MSAA renderbuffer object to store color info glGenRenderbuffers(1, &rboColorId); glBindRenderbuffer(GL_RENDERBUFFER, rboColorId); glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaaCount, GL_RGB8, TEXTURE_WIDTH, TEXTURE_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, 0); // create a MSAA renderbuffer object to store depth info // NOTE: A depth renderable image should be attached the FBO for depth test. // If we don't attach a depth renderable image to the FBO, then // the rendering output will be corrupted because of missing depth test. // If you also need stencil test for your rendering, then you must // attach additional image to the stencil attachement point, too. glGenRenderbuffers(1, &rboDepthId); glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId); glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaaCount, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, 0); // attach msaa RBOs to FBO attachment points glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboColorId); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepthId); // create a normal (no MSAA) FBO to hold a render-to-texture glGenFramebuffers(1, &fboId); glBindFramebuffer(GL_FRAMEBUFFER, fboId); glGenRenderbuffers(1, &rboId); glBindRenderbuffer(GL_RENDERBUFFER, rboId); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, 0); // attach a texture to FBO color attachement point glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); // attach a rbo to FBO depth attachement point glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId); //@@ disable color buffer if you don't attach any color buffer image, //@@ for example, rendering the depth buffer only to a texture. //@@ Otherwise, glCheckFramebufferStatus will not be complete. //glDrawBuffer(GL_NONE); //glReadBuffer(GL_NONE); // check FBO status printFramebufferInfo(fboMsaaId); bool status = checkFramebufferStatus(fboMsaaId); if(!status) fboUsed = false; glBindFramebuffer(GL_FRAMEBUFFER, 0); } // start timer, the elapsed time will be used for rotating the teapot timer.start(); // the last GLUT call (LOOP) // window will be shown and display callback is triggered by events // NOTE: this call never return main(). glutMainLoop(); /* Start GLUT event-processing loop */ return 0; }