void OpenGLTexture::unlock() { if (!mLock && mBuffer) { delete mBuffer; mBuffer = 0; glBindTexture(GL_TEXTURE_2D, 0); return; } MYGUI_PLATFORM_ASSERT(mLock, "Texture is not locked"); if (!OpenGLRenderManager::getInstance().isPixelBufferObjectSupported()) { //Fallback if PBO's are not supported glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, mPixelFormat, GL_UNSIGNED_BYTE, mBuffer); delete mBuffer; } else { // release the mapped buffer glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // copy pixels from PBO to texture object // Use offset instead of ponter. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, mPixelFormat, GL_UNSIGNED_BYTE, 0); // it is good idea to release PBOs with ID 0 after use. // Once bound with 0, all pixel operations are back to normal ways. glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } glBindTexture(GL_TEXTURE_2D, 0); mBuffer = 0; mLock = false; }
void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb) { void *pixels; int i; glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode); for (i = 0; i < pb->numbuffers; i++) { glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->bindcode[pb->current]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->datasize, NULL, GL_STREAM_DRAW_ARB); pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY); /*memcpy(pixels, _oImage.data(), pb->datasize);*/ if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) { fprintf(stderr, "Could not unmap opengl PBO\n"); break; } } glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0); }
/* ================================================================================ // Name: // Desc: ================================================================================ */ void CIndexBuffer::Unlock() { if ( false == m_bLocked ) { DEBUG_ASSERT( !"Try to unlock non-locked buffer" ); return; } if ( g_pRenderer->IsExtSupported( EXT_GL_VBO ) ) { glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, m_nBufferID ); GL_VALIDATE; glUnmapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB ); GL_VALIDATE; glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); GL_VALIDATE; } m_bLocked = false; return; }
enum piglit_result piglit_display(void) { GLboolean pass = GL_TRUE; static float red[] = {1.0, 0.0, 0.0, 0.0}; static float green[] = {0.0, 1.0, 0.0, 0.0}; uint32_t *addr; GLuint pbo; glGenBuffersARB(1, &pbo); glBindBufferARB(GL_PIXEL_PACK_BUFFER, pbo); glBufferDataARB(GL_PIXEL_PACK_BUFFER, 2 * 4, NULL, GL_STREAM_DRAW_ARB); glPixelStorei(GL_PACK_ALIGNMENT, 1); glColor4fv(green); piglit_draw_rect(0, 0, piglit_width / 2, piglit_height); glColor4fv(red); piglit_draw_rect(piglit_width / 2, 0, piglit_width / 2, piglit_height); glReadPixels(10, 10, 1, 1, GL_BGRA, GL_UNSIGNED_BYTE, (void *)(uintptr_t)0); glReadPixels(piglit_width - 10, 10, 1, 1, GL_BGRA, GL_UNSIGNED_BYTE, (void *)(uintptr_t)4); glutSwapBuffers(); addr = glMapBufferARB(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY_ARB); pass &= probe(10, 10, 0x0000ff00, addr[0]); pass &= probe(10, 10, 0x00ff0000, addr[1]); glUnmapBufferARB(GL_PIXEL_PACK_BUFFER); glDeleteBuffersARB(1, &pbo); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
void GPU_update_mesh_buffers(void *buffers_v, MVert *mvert, int *vert_indices, int totvert) { GPU_Buffers *buffers = buffers_v; VertexBufferFormat *vert_data; int i; if(buffers->vert_buf) { /* Build VBO */ glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(VertexBufferFormat) * totvert, NULL, GL_STATIC_DRAW_ARB); vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); if(vert_data) { for(i = 0; i < totvert; ++i) { MVert *v = mvert + vert_indices[i]; VertexBufferFormat *out = vert_data + i; copy_v3_v3(out->co, v->co); memcpy(out->no, v->no, sizeof(short) * 3); } glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); } else { glDeleteBuffersARB(1, &buffers->vert_buf); buffers->vert_buf = 0; } glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); } buffers->mvert = mvert; }
void InitializeSites(int point_num) { int i, j, index; int v_per_site; VertexSiteType v; additional_passes = 0; additional_passes_before = 0; iSiteTextureHeight = point_num/screenwidth+1; bReCompute = true; // Allicate Host-Mem(site_list). for reading from Device(site_list_dev). memAllocHost<SiteType>(&site_list, &site_list_dev, point_num); // Buffer for swap site_list site_list_x = new float[(point_num) * 2]; site_list_x_bar = new float[(point_num) * 2]; site_perturb_step = 0.5f / sqrtf(point_num); if(!bReadSitesFromFile) { // ------------------------------------------------------------ // Randomize Site-position // ------------------------------------------------------------ bool *FlagArray = new bool[screenwidth*screenheight]; for (i=0; i<screenwidth*screenheight; i++) FlagArray[i] = false; for (i=0; i<point_num; i++) { SiteType s; v.x = (double)rand()/(double)RAND_MAX*(screenwidth-1.0)+1.0; v.y = (double)rand()/(double)RAND_MAX*(screenheight-1.0)+1.0; while(true) { index = int(v.y)*screenwidth+int(v.x); if (FlagArray[index]) { printf("\nDuplicate site found: #%d\n", i); v.x = v.x + ((float)rand() / (float)RAND_MAX * 2.0f - 1.0f) * (float)(screenwidth-1); v.y = v.y + ((float)rand() / (float)RAND_MAX * 2.0f - 1.0f) * (float)(screenwidth-1); while(v.x > (float)(screenwidth - 1)) { v.x -= (float)screenwidth; } while(v.x < 1.0f) { v.x += (float)screenwidth; } while(v.y > (float)(screenheight - 1)) { v.y -= (float)screenheight; } while(v.y < 1.0f) { v.y += (float)screenheight; } } else { FlagArray[index] = true; break; } } s.vertices[0] = v; s.color[0] = (float)rand()/(float)RAND_MAX; s.color[1] = (float)rand()/(float)RAND_MAX; s.color[2] = (float)rand()/(float)RAND_MAX; s.color[3] = i; site_list[i] = s; } delete FlagArray; } else { // ------------------------------------------------------------ // Read Site-position from input file. // ------------------------------------------------------------ FILE* fp = fopen("init.txt", "r"); for (i=0; i<point_num; i++) { SiteType s; fscanf(fp, "%f, %f\n", &v.x, &v.y); s.vertices[0] = v; s.color[0] = (float)rand()/(float)RAND_MAX; s.color[1] = (float)rand()/(float)RAND_MAX; s.color[2] = (float)rand()/(float)RAND_MAX; s.color[3] = i; site_list[i] = s; } fclose(fp); } // ------------------------------------------------------------ // Set Color_Texture as Site-Index // ------------------------------------------------------------ GLubyte *ColorTexImage = new GLubyte[screenwidth*screenheight*4]; for (i=0; i<screenheight; i++) for (j=0; j<screenwidth; j++) { int id = i*screenwidth+j; if (id<point_num) { ColorTexImage[id*4] = site_list[id].color[0]*255; ColorTexImage[id*4+1] = site_list[id].color[1]*255; ColorTexImage[id*4+2] = site_list[id].color[2]*255; ColorTexImage[id*4+3] = 255; } else { ColorTexImage[id*4] = ColorTexImage[id*4+1] = ColorTexImage[id*4+2] = ColorTexImage[id*4+3] = 0.0; } } glActiveTextureARB(GL_TEXTURE2_ARB); glGenTextures(1, &Color_Texture); glBindTexture(GL_TEXTURE_RECTANGLE_NV, Color_Texture); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, screenwidth, screenheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, ColorTexImage); delete ColorTexImage; // ------------------------------------------------------------ // Create Vertext-Buffer-Oobject(VBO) & Register graphic resource for VBO // DrawSites()에서 사용. CUDA를 통해 x를 VBO에 저장하기 위해 grVBO가 필요 // ------------------------------------------------------------ glGenBuffersARB(1, &vboId); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId); glBufferDataARB(GL_ARRAY_BUFFER_ARB, point_num * sizeof(VertexSiteType), NULL, GL_DYNAMIC_DRAW_ARB); cudaGraphicsGLRegisterBuffer(&grVbo, vboId, cudaGraphicsMapFlagsWriteDiscard); // ------------------------------------------------------------ // Create Color-Buffer-Object(CBO) and set from site_list // ------------------------------------------------------------ glGenBuffersARB(1, &colorboId); glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorboId); glBufferDataARB(GL_ARRAY_BUFFER_ARB, point_num * sizeof(float) * 4, NULL, GL_DYNAMIC_DRAW_ARB); GLvoid* pointer = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); float* sitelist = (float*)pointer; for (i=0; i<point_num; i++) { sitelist[i * 4 + 0] = site_list[i].color[0]; sitelist[i * 4 + 1] = site_list[i].color[1]; sitelist[i * 4 + 2] = site_list[i].color[2]; sitelist[i * 4 + 3] = site_list[i].color[3]; } glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); }
void EarthquakeSet::initContext(GLContextData& contextData) const { /* Create a context data item and store it in the context: */ DataItem* dataItem=new DataItem; contextData.addDataItem(this,dataItem); if(dataItem->vertexBufferObjectId>0) { typedef GLGeometry::Vertex<float,2,GLubyte,4,void,float,3> Vertex; /* Create a vertex buffer object to store the events: */ glBindBufferARB(GL_ARRAY_BUFFER_ARB,dataItem->vertexBufferObjectId); glBufferDataARB(GL_ARRAY_BUFFER_ARB,events.size()*sizeof(Vertex),0,GL_STATIC_DRAW_ARB); Vertex* vPtr=static_cast<Vertex*>(glMapBufferARB(GL_ARRAY_BUFFER_ARB,GL_WRITE_ONLY_ARB)); int numPoints=int(events.size()); for(int i=0;i<numPoints;++i,++vPtr) { /* Get a reference to the event in kd-tree order: */ const Event& e=events[treePointIndices[i]]; /* Copy the event's time: */ vPtr->texCoord[0]=Vertex::TexCoord::Scalar(e.magnitude)-4.0f; vPtr->texCoord[1]=Vertex::TexCoord::Scalar(e.time); /* Map the event's magnitude to color: */ float magnitudeMin=5.0f; float magnitudeMax=9.0f; const int numColors=5; static const Vertex::Color magColorMap[numColors]= { Vertex::Color(0,255,0), Vertex::Color(0,255,255), Vertex::Color(0,0,255), Vertex::Color(255,0,255), Vertex::Color(255,0,0) }; if(e.magnitude<=magnitudeMin) vPtr->color=magColorMap[0]; else if(e.magnitude>=magnitudeMax) vPtr->color=magColorMap[numColors-1]; else { int baseIndex=int(e.magnitude-magnitudeMin); float weight=(e.magnitude-magnitudeMin)-float(baseIndex); for(int i=0;i<4;++i) vPtr->color[i]=GLubyte(float(magColorMap[baseIndex][i])*(1.0f-weight)+float(magColorMap[baseIndex+1][i]*weight)+0.5f); } /* Copy the event's position: */ vPtr->position=e.position; } glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); /* Protect the vertex buffer object: */ glBindBufferARB(GL_ARRAY_BUFFER_ARB,0); } if(dataItem->pointRenderer!=0) { /* Create the point rendering shader: */ static const char* vertexProgram="\ uniform float scaledPointRadius; \ uniform float highlightTime; \ uniform float currentTime; \ uniform vec3 frontSphereCenter; \ uniform float frontSphereRadius2; \ uniform bool frontSphereTest; \ \ void main() \ { \ /* Check if the point is inside the front sphere: */ \ bool valid=dot(gl_Vertex-frontSphereCenter,gl_Vertex-frontSphereCenter)>=frontSphereRadius2; \ if(frontSphereTest) \ valid=!valid; \ if(valid) \ { \ /* Transform the vertex to eye coordinates: */ \ vec4 vertexEye=gl_ModelViewMatrix*gl_Vertex; \ \ /* Calculate point size based on vertex' eye distance along z direction: */ \ float pointSize=scaledPointRadius*2.0*vertexEye.w/vertexEye.z; \ pointSize*=gl_MultiTexCoord0.x; \ \ /* Adapt point size based on current time and time scale: */ \ float highlightFactor=gl_MultiTexCoord0.y-(currentTime-highlightTime); \ if(highlightFactor>0.0&&highlightFactor<=highlightTime) \ pointSize*=2.0*highlightFactor/highlightTime+1.0; \ \ /* Set point size: */ \ gl_PointSize=pointSize; \ \ /* Use standard color: */ \ gl_FrontColor=gl_Color; \ } \ else \ { \ /* Set point size to zero and color to invisible: */ \ gl_PointSize=0.0; \ gl_FrontColor=vec4(0.0,0.0,0.0,0.0); \ } \ \ /* Use standard vertex position for fragment generation: */ \ gl_Position=ftransform(); \ }"; static const char* fragmentProgram="\ uniform sampler2D pointTexture; \ \ void main() \ { \ gl_FragColor=texture2D(pointTexture,gl_TexCoord[0].xy)*gl_Color; \ }";
//Step the simulation void ParticleSystem::update(float deltaTime){ assert(m_bInitialized); setParameters(&m_params); setParametersHost(&m_params); //Download positions from VBO memHandle_t pos; if (!m_bQATest) { glBindBufferARB(GL_ARRAY_BUFFER, m_posVbo); pos = (memHandle_t)glMapBufferARB(GL_ARRAY_BUFFER, GL_READ_WRITE); copyArrayToDevice(m_dPos, pos, 0, m_numParticles * 4 * sizeof(float)); } integrateSystem( m_dPos, m_dVel, deltaTime, m_numParticles ); calcHash( m_dHash, m_dIndex, m_dPos, m_numParticles ); bitonicSort(NULL, m_dHash, m_dIndex, m_dHash, m_dIndex, 1, m_numParticles, 0); //Find start and end of each cell and //Reorder particle data for better cache coherency findCellBoundsAndReorder( m_dCellStart, m_dCellEnd, m_dReorderedPos, m_dReorderedVel, m_dHash, m_dIndex, m_dPos, m_dVel, m_numParticles, m_numGridCells ); collide( m_dVel, m_dReorderedPos, m_dReorderedVel, m_dIndex, m_dCellStart, m_dCellEnd, m_numParticles, m_numGridCells ); //Update buffers if (!m_bQATest) { copyArrayFromDevice(pos,m_dPos, 0, m_numParticles * 4 * sizeof(float)); glUnmapBufferARB(GL_ARRAY_BUFFER); } }
////////////////////////////////////////////////////////////////////// // readback // // Code to handle reading back of the FBO data (but with a specified FBO pointer) // ////////////////////////////////////////////////////////////////////// bool CheckFBO::readback( GLuint width, GLuint height, GLuint bufObject ) { bool ret = false; if (m_bUseFBO) { if (m_bUsePBO) { shrLog("CheckFBO::readback() FBO->PBO->m_pImageData\n"); // binds the PBO for readback bindReadback(); // bind FBO buffer (we want to transfer FBO -> PBO) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bufObject ); // Now initiate the readback to PBO glReadPixels(0, 0, width, height, getPixelFormat(), GL_UNSIGNED_BYTE, BUFFER_OFFSET(0)); ret = checkStatus(__FILE__, __LINE__, true); if (!ret) shrLog("CheckFBO::readback() FBO->PBO checkStatus = %d\n", ret); // map - unmap simulates readback without the copy void *ioMem = glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); memcpy(m_pImageData, ioMem, width*height*m_Bpp); glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); // release the FBO glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // release the PBO unbindReadback(); } else { shrLog("CheckFBO::readback() FBO->m_pImageData\n"); // Reading direct to FBO using glReadPixels glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, bufObject ); ret = checkStatus(__FILE__, __LINE__, true); if (!ret) shrLog("CheckFBO::readback::glBindFramebufferEXT() fbo=%d checkStatus = %d\n", (int)bufObject, (int)ret); glReadBuffer(static_cast<GLenum>(GL_COLOR_ATTACHMENT0_EXT)); ret &= checkStatus(__FILE__, __LINE__, true); if (!ret) shrLog("CheckFBO::readback::glReadBuffer() fbo=%d checkStatus = %d\n", (int)bufObject, (int)ret); glReadPixels(0, 0, width, height, getPixelFormat(), GL_UNSIGNED_BYTE, m_pImageData); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } } else { shrLog("CheckFBO::readback() PBO->m_pImageData\n"); // read from bufObject (PBO) to system memorys image glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, bufObject); // Bind the PBO // map - unmap simulates readback without the copy void *ioMem = glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); memcpy(m_pImageData, ioMem, width*height*m_Bpp); glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); // read from bufObject (PBO) to system memory image glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); // unBind the PBO } return CHECK_FBO; }
enum piglit_result test_pixel_map(void *null) { int use_unpack; int use_pack; GLuint pb_pack[1]; GLuint pb_unpack[1]; int i; int size; int max; GLushort *pbo_mem; glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); glGetIntegerv(GL_MAX_PIXEL_MAP_TABLE, &max); for (use_pack = 0; use_pack < 2; use_pack++) { for (use_unpack = 0; use_unpack < 2; use_unpack++) { glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); if (use_unpack) { glGenBuffersARB(1, pb_unpack); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pb_unpack[0]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, max * sizeof(GLushort), NULL, GL_STREAM_DRAW); } pbo_mem = NULL; if (use_unpack) { pbo_mem = (GLushort *) glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } else { pbo_mem = (GLushort *) malloc(sizeof(GLushort) * max); } for (i = 0; i < max; i++) pbo_mem[i] = max - i - 1; if (use_unpack) { glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); glPixelMapusv(GL_PIXEL_MAP_R_TO_R, max, NULL); glPixelMapusv(GL_PIXEL_MAP_G_TO_G, max, NULL); glPixelMapusv(GL_PIXEL_MAP_B_TO_B, max, NULL); glPixelMapusv(GL_PIXEL_MAP_A_TO_A, max, NULL); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } else { glPixelMapusv(GL_PIXEL_MAP_R_TO_R, max, pbo_mem); glPixelMapusv(GL_PIXEL_MAP_G_TO_G, max, pbo_mem); glPixelMapusv(GL_PIXEL_MAP_B_TO_B, max, pbo_mem); glPixelMapusv(GL_PIXEL_MAP_A_TO_A, max, pbo_mem); free(pbo_mem); } glGetIntegerv(GL_PIXEL_MAP_R_TO_R_SIZE, &size); if (size != max) { REPORT_FAILURE("glPixelMap failed"); return PIGLIT_FAIL; } glPixelTransferi(GL_MAP_COLOR, GL_FALSE); /* Read back pixel map */ if (use_pack) { glGenBuffersARB(1, pb_pack); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pb_pack[0]); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, max * sizeof(GLushort), NULL, GL_STREAM_DRAW); glGetPixelMapusv(GL_PIXEL_MAP_R_TO_R, NULL); pbo_mem = (GLushort *) glMapBufferARB( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); } else { pbo_mem = (GLushort *) malloc(sizeof(GLushort) * max); glGetPixelMapusv(GL_PIXEL_MAP_R_TO_R, pbo_mem); } for (i = 0; i < max; i++) { if (pbo_mem[i] != max - i - 1) { REPORT_FAILURE("get PixelMap failed"); return PIGLIT_FAIL; } } if (use_pack) { glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pb_pack); } else { free(pbo_mem); } if (use_unpack) { glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pb_unpack); } if (!piglit_automatic) piglit_present_results(); } } return PIGLIT_PASS; }
int dxt_encoder_compress_texture(struct dxt_encoder* encoder, int texture, unsigned char* image_compressed) { #ifdef USE_PBO_DXT_ENCODER GLubyte *ptr; #endif glBindTexture(GL_TEXTURE_2D, texture); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER)); glClearColor(1,0,0,1); glClear(GL_COLOR_BUFFER_BIT); if(encoder->legacy) { glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0); glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0); glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0); glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0); glEnd(); } else { #if ! defined HAVE_MACOSX || OS_VERSION_MAJOR >= 11 // Compress glBindVertexArray(encoder->g_vao); //glDrawElements(GL_TRIANGLE_STRIP, sizeof(m_quad.indices) / sizeof(m_quad.indices[0]), GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); #endif } #ifdef HAVE_GPUPERFAPI GPA_EndSample(); GPA_BeginSample(3); #endif #ifdef RTDXT_DEBUG glEndQuery(GL_TIME_ELAPSED_EXT); glBeginQuery(GL_TIME_ELAPSED_EXT, encoder->queries[3]); #endif #ifdef RTDXT_DEBUG_HOST glFinish(); TIMER_STOP_PRINT("Texture Compress: "); TIMER_START(); #endif glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); #ifdef USE_PBO_DXT_ENCODER // Read back // read pixels from framebuffer to PBO // glReadPixels() should return immediately. glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, encoder->pbo_out); if ( encoder->type == DXT_TYPE_DXT5_YCOCG ) glReadPixels(0, 0, (encoder->width + 3) / 4, (encoder->height + 3) / 4, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, 0); else glReadPixels(0, 0, (encoder->width + 3) / 4, (encoder->height + 3) / 4 , GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, 0); // map the PBO to process its data by CPU glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, encoder->pbo_out); ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); if(ptr) { memcpy(image_compressed, ptr, ((encoder->width + 3) / 4 * 4) * ((encoder->height + 3) / 4 * 4) / (encoder->type == DXT_TYPE_DXT5_YCOCG ? 1 : 2)); glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); } // back to conventional pixel operation glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); #else glReadPixels(0, 0, (encoder->width + 3) / 4, (encoder->height + 3) / 4, GL_RGBA_INTEGER_EXT, encoder->type == DXT_TYPE_DXT5_YCOCG ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, image_compressed); #endif #ifdef RTDXT_DEBUG_HOST glFinish(); TIMER_STOP_PRINT("Texture Save: "); #endif #ifdef RTDXT_DEBUG glEndQuery(GL_TIME_ELAPSED_EXT); { GLint available = 0; GLuint64 load = 0, convert = 0, compress = 0, store = 0; while (!available) { glGetQueryObjectiv(encoder->queries[3], GL_QUERY_RESULT_AVAILABLE, &available); } glGetQueryObjectui64vEXT(encoder->queries[0], GL_QUERY_RESULT, &load); glGetQueryObjectui64vEXT(encoder->queries[1], GL_QUERY_RESULT, &convert); glGetQueryObjectui64vEXT(encoder->queries[2], GL_QUERY_RESULT, &compress); glGetQueryObjectui64vEXT(encoder->queries[3], GL_QUERY_RESULT, &store); printf("Load: %8lu; YUV444->YUV422: %8lu; compress: %8lu; store: %8lu\n", load, convert, compress, store); } #endif #ifdef HAVE_GPUPERFAPI GPA_EndSample(); GPA_EndPass(); #endif return 0; }
enum piglit_result test_tex_image(void *null) { bool pass = true; int break_pbo_cow, break_tex_cow; /* cow = copy on write */ int use_unpack, use_pack; GLuint unpack_pb[1]; GLuint pack_pb[1]; GLenum pack = GL_PIXEL_PACK_BUFFER_ARB; GLenum unpack = GL_PIXEL_UNPACK_BUFFER_ARB; GLfloat t1[TEXTURE_SIZE]; GLfloat t2[TEXTURE_SIZE]; GLfloat *pbo_mem = NULL; int i, j; GLfloat green[3] = { 1.0, 1.0, 0.0 }; GLfloat black[3] = { 0.0, 0.0, 0.0 }; GLfloat buf[WINDOW_SIZE]; GLfloat exp_tex[TEXTURE_SIZE]; GLfloat exp_win[WINDOW_SIZE]; GLfloat tolerance[4]; piglit_compute_probe_tolerance(GL_RGB, tolerance); glBindBufferARB(unpack, 0); glBindBufferARB(pack, 0); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); for (use_pack = 0; use_pack < 2; use_pack++) { for (use_unpack = 0; use_unpack < 2; use_unpack++) { for (break_pbo_cow = 0; break_pbo_cow < use_unpack + 1; break_pbo_cow++) { for (break_tex_cow = 0; break_tex_cow < use_unpack + 1; break_tex_cow++) { if (use_unpack) { glGenBuffersARB(1, unpack_pb); glBindBufferARB(unpack, unpack_pb[0]); glBufferDataARB(unpack, TEXTURE_SIZE * sizeof(GLfloat), NULL, GL_STREAM_DRAW); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (use_unpack) { pbo_mem = (GLfloat *) glMapBufferARB(unpack, GL_WRITE_ONLY); } else { pbo_mem = t1; } for (i = 0; i < TEXTURE_SIZE/3; i++) { pbo_mem[3 * i] = 1.0; pbo_mem[3 * i + 1] = 1.0; pbo_mem[3 * i + 2] = 0.0; } if (use_unpack) { glUnmapBufferARB(unpack); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_RGB, GL_FLOAT, NULL); glBindBufferARB(unpack, 0); } else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_RGB, GL_FLOAT, pbo_mem); if (use_unpack && break_pbo_cow) { glBindBufferARB(unpack, unpack_pb[0]); pbo_mem = (GLfloat *) glMapBufferARB( unpack, GL_WRITE_ONLY); for (i = 0; i < TEXTURE_SIZE; i++) pbo_mem[i] = 0.2; glUnmapBufferARB(unpack); glBindBufferARB(unpack, 0); } if (use_unpack && break_tex_cow) { GLfloat temp[3]; for (i = 0; i < 3; i++) temp[i] = 0.8; glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGB, GL_FLOAT, temp); } /* Check PBO's content */ if (use_unpack) { glBindBufferARB(unpack, unpack_pb[0]); pbo_mem = (GLfloat *) glMapBuffer(unpack, GL_READ_ONLY); if (break_pbo_cow) { for (i = 0; i < TEXTURE_SIZE; i++) if (fabsf(pbo_mem[i] - 0.2f) > tolerance[0]) { REPORT_FAILURE ("PBO modified by someone else, " "there must be something wrong"); return PIGLIT_FAIL; } } glUnmapBufferARB(unpack); glBindBufferARB(unpack, 0); } /* Read texture back */ if (use_pack) { glGenBuffersARB(1, pack_pb); glBindBufferARB(pack, pack_pb[0]); glBufferDataARB(pack, TEXTURE_SIZE * sizeof(GLfloat), NULL, GL_STREAM_DRAW); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_FLOAT, NULL); pbo_mem = (GLfloat *) glMapBufferARB(pack, GL_READ_ONLY); } else { glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_FLOAT, t2); pbo_mem = t2; } /* Check texture image */ for (i = 0; i < TEXTURE_SIZE/3; i++) { int idx = i * 3; if (i == 0 && break_tex_cow && use_unpack) { exp_tex[idx + 0] = 0.8; exp_tex[idx + 1] = 0.8; exp_tex[idx + 2] = 0.8; } else { exp_tex[idx + 0] = 1.0; exp_tex[idx + 1] = 1.0; exp_tex[idx + 2] = 0.0; } } pass &= piglit_compare_images_color(0, 0, TEXSIZE, TEXSIZE, 3, tolerance, exp_tex, pbo_mem); if (use_pack) { glUnmapBufferARB(pack); glBindBufferARB(pack, 0); glDeleteBuffersARB(1, pack_pb); } if (use_unpack) { glDeleteBuffersARB(1, unpack_pb); } glEnable(GL_TEXTURE_2D); glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(TEXSIZE, 0); glTexCoord2f(1, 1); glVertex2f(TEXSIZE, TEXSIZE); glTexCoord2f(0, 1); glVertex2f(0, TEXSIZE); glEnd(); glDisable(GL_TEXTURE_2D); glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, buf); for (j = 0; j < WINSIZE; j++) { for (i = 0; i < WINSIZE; i++) { int idx = (j * WINSIZE + i) * 3; if (i == 0 && j == 0 && break_tex_cow && use_unpack) { exp_win[idx + 0] = 0.8; exp_win[idx + 1] = 0.8; exp_win[idx + 2] = 0.8; } else if (i < TEXSIZE && j < TEXSIZE) { exp_win[idx + 0] = green[0]; exp_win[idx + 1] = green[1]; exp_win[idx + 2] = green[2]; } else { exp_win[idx + 0] = black[0]; exp_win[idx + 1] = black[1]; exp_win[idx + 2] = black[2]; } } } pass &= piglit_compare_images_color(0, 0, WINSIZE, WINSIZE, 3, tolerance, exp_win, buf); } } } } return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
bool PixelBuffer::unmap ( ) { // TODO Tests if the Buffer is bound. Is this really important ? return glUnmapBufferARB ( target_ ) == GL_TRUE; }
void PoiseuilleFlowSystem::_initialize(int numParticles){ assert(!IsInitialized); numParticles = numParticles; hPos = new float[numParticles*4]; hVel = new float[numParticles*4]; hVelLeapFrog = new float[numParticles*4]; hMeasures = new float[numParticles*4]; hAcceleration = new float[numParticles*4]; memset(hPos, 0, numParticles*4*sizeof(float)); memset(hVel, 0, numParticles*4*sizeof(float)); memset(hVelLeapFrog, 0, numParticles*4*sizeof(float)); memset(hAcceleration, 0, numParticles*4*sizeof(float)); memset(hMeasures, 0, numParticles*4*sizeof(float)); for(uint i = 0; i < numParticles; i++) //todo: check density approximation hMeasures[4*i+0] = params.restDensity; unsigned int memSize = sizeof(float) * 4 * numParticles; if (IsOpenGL) { posVbo = createVBO(memSize); registerGLBufferObject(posVbo, &cuda_posvbo_resource); } else { checkCudaErrors( cudaMalloc( (void **)&cudaPosVBO, memSize )) ; } allocateArray((void**)&dVel, memSize); allocateArray((void**)&dVelLeapFrog, memSize); allocateArray((void**)&dAcceleration, memSize); allocateArray((void**)&dMeasures, memSize); allocateArray((void**)&dSortedPos, memSize); allocateArray((void**)&dSortedVel, memSize); allocateArray((void**)&dHash, numParticles*sizeof(uint)); allocateArray((void**)&dIndex, numParticles*sizeof(uint)); allocateArray((void**)&dCellStart, numGridCells*sizeof(uint)); allocateArray((void**)&dCellEnd, numGridCells*sizeof(uint)); if (IsOpenGL) { colorVBO = createVBO(numParticles*4*sizeof(float)); registerGLBufferObject(colorVBO, &cuda_colorvbo_resource); // fill color buffer glBindBufferARB(GL_ARRAY_BUFFER, colorVBO); float *data = (float *) glMapBufferARB(GL_ARRAY_BUFFER, GL_WRITE_ONLY); float *ptr = data; uint fluidParticles = params.fluidParticlesSize.x * params.fluidParticlesSize.y * params.fluidParticlesSize.z; for(uint i=0; i < numParticles; i++) { float t = 0.7f; if(i < fluidParticles) t = 0.5f; if(((i % params.gridSize.x) == 0) && i < fluidParticles) t = 0.2f; colorRamp(t, ptr); ptr+=3; *ptr++ = 1.0f; } glUnmapBufferARB(GL_ARRAY_BUFFER); } else { checkCudaErrors( cudaMalloc( (void **)&cudaColorVBO, sizeof(float)*numParticles*4) ); } setParameters(¶ms); IsInitialized = true; }
void displayCB() { static int shift = 0; static int index = 0; int nextIndex = 0; // pbo index used for next frame // brightness shift amount shift = ++shift % 200; // increment current index first then get the next index // "index" is used to read pixels from a framebuffer to a PBO // "nextIndex" is used to process pixels in the other PBO index = (index + 1) % 2; nextIndex = (index + 1) % 2; // set the framebuffer to read glReadBuffer(GL_FRONT); if(pboUsed) // with PBO { // read framebuffer /////////////////////////////// t1.start(); // copy pixels from framebuffer to PBO // Use offset instead of ponter. // OpenGL should perform asynch DMA transfer, so glReadPixels() will return immediately. glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[index]); glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, PIXEL_FORMAT, GL_UNSIGNED_BYTE, 0); // measure the time reading framebuffer t1.stop(); readTime = t1.getElapsedTimeInMilliSec(); /////////////////////////////////////////////////// // process pixel data ///////////////////////////// t1.start(); // map the PBO that contain framebuffer pixels before processing it glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[nextIndex]); GLubyte* src = (GLubyte*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); if(src) { // change brightness add(src, SCREEN_WIDTH, SCREEN_HEIGHT, shift, colorBuffer); glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); // release pointer to the mapped buffer } // measure the time reading framebuffer t1.stop(); processTime = t1.getElapsedTimeInMilliSec(); /////////////////////////////////////////////////// glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); } else // without PBO { // read framebuffer /////////////////////////////// t1.start(); glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, PIXEL_FORMAT, GL_UNSIGNED_BYTE, colorBuffer); // measure the time reading framebuffer t1.stop(); readTime = t1.getElapsedTimeInMilliSec(); /////////////////////////////////////////////////// // covert to greyscale //////////////////////////// t1.start(); // change brightness add(colorBuffer, SCREEN_WIDTH, SCREEN_HEIGHT, shift, colorBuffer); // measure the time reading framebuffer t1.stop(); processTime = t1.getElapsedTimeInMilliSec(); /////////////////////////////////////////////////// } // render to the framebuffer ////////////////////////// glDrawBuffer(GL_BACK); toPerspective(); // set to perspective on the left side of the window // clear buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // tramsform camera glTranslatef(0, 0, -cameraDistance); glRotatef(cameraAngleX, 1, 0, 0); // pitch glRotatef(cameraAngleY, 0, 1, 0); // heading // draw a cube glPushMatrix(); draw(); glPopMatrix(); // draw the read color buffer to the right side of the window toOrtho(); // set to orthographic on the right side of the window glRasterPos2i(0, 0); glDrawPixels(SCREEN_WIDTH, SCREEN_HEIGHT, PIXEL_FORMAT, GL_UNSIGNED_BYTE, colorBuffer); // draw info messages showInfo(); printTransferRate(); glutSwapBuffers(); }
//-------------------------------------------------------------- void testApp::update(){ cam.update(); fbo.begin(); ofClear(255, 0, 0); ofSetColor(255); cam.draw(0, 0); ofRect(0, 0, 100, 100); fbo.end(); ofClear(255, 0, 0); ofSetColor(255); fbo.draw(0, ofGetHeight()-HEIGHT); // increment current index first then get the next index // "index" is used to read pixels from a framebuffer to a PBO // "nextIndex" is used to process pixels in the other PBO index = (index + 1) % 2; nextIndex = (index + 1) % 2; //ofSleepMillis(50); // copy pixels from framebuffer to PBO // Use offset instead of ponter. // OpenGL should perform asynch DMA transfer, so glReadPixels() will return immediately. glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[index]); // Bind FBO //fbo.bind(); TIME_SAMPLE_START("FBO to PBO"); glReadPixels(0, 0, WIDTH, HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, NULL); TIME_SAMPLE_STOP("FBO to PBO"); // Unbind FBO //fbo.unbind(); ofSleepMillis(15); // map the PBO that contain framebuffer pixels before processing it glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[nextIndex]); TIME_SAMPLE_START("PBO to CPU"); GLubyte* src = (GLubyte*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); TIME_SAMPLE_STOP("PBO to CPU"); if(src){ TIME_SAMPLE_START("MEMCPY"); // copy the data to the image memcpy(image.getPixels(), src, WIDTH * HEIGHT * 4 * sizeof(unsigned char)); TIME_SAMPLE_STOP("MEMCPY"); TIME_SAMPLE_START("IMAGE UPDATE"); image.update(); TIME_SAMPLE_STOP("IMAGE UPDATE"); // release pointer to the mapped buffer glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); } // unbind PBO glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); }
void LLVertexBuffer::unmapBuffer(S32 type) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (!useVBOs()) { return ; //nothing to unmap } bool updated_all = false ; if (mMappedData && mVertexLocked && type != TYPE_INDEX) { updated_all = (mIndexLocked && type < 0) ; //both vertex and index buffers done updating if(sDisableVBOMapping) { stop_glerror(); glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (void*)mMappedData); stop_glerror(); } else { stop_glerror(); glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); stop_glerror(); mMappedData = NULL; } mVertexLocked = FALSE ; sMappedCount--; } if(mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX)) { if(sDisableVBOMapping) { stop_glerror(); glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), (void*)mMappedIndexData); stop_glerror(); } else { stop_glerror(); glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); stop_glerror(); mMappedIndexData = NULL ; } mIndexLocked = FALSE ; sMappedCount--; } if(updated_all) { if(mUsage == GL_STATIC_DRAW_ARB) { //static draw buffers can only be mapped a single time //throw out client data (we won't be using it again) mEmpty = TRUE; mFinal = TRUE; if(sDisableVBOMapping) { freeClientBuffer() ; } } else { mEmpty = FALSE; } } }
enum piglit_result test_polygon_stip(void *null) { int use_unpack = 0; int use_pack = 0; GLuint unpack_pb[1]; GLuint pack_pb[1]; GLubyte t1[32 * 32 / 8]; GLubyte t2[32 * 32 / 8]; GLubyte *pbo_mem = NULL; int i, j; GLfloat white[3] = { 1.0, 1.0, 1.0 }; GLfloat black[3] = { 0.0, 0.0, 0.0 }; GLfloat buf[WINSIZE * WINSIZE * 3]; bool pass = true; GLfloat expected[WINSIZE * WINSIZE * 3]; GLfloat tolerance[4]; piglit_compute_probe_tolerance(GL_RGB, &tolerance[0]); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); for (use_unpack = 0; use_unpack < 2; use_unpack++) { for (use_pack = 0; use_pack < 2; use_pack++) { glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); if (use_unpack) { glGenBuffersARB(1, unpack_pb); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, unpack_pb[0]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 32 * 32 / 8, NULL, GL_STREAM_DRAW); pbo_mem = (GLubyte *) glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } else { pbo_mem = t1; } /* Fill in the stipple pattern */ for (i = 0; i < 32 * 32 / 8; i++) { pbo_mem[i] = 0xAA; /* Checkerboard */ } if (use_unpack) { glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); glPolygonStipple(NULL); } else { glPolygonStipple(pbo_mem); } /* Read back the stipple pattern */ if (use_pack) { glGenBuffersARB(1, pack_pb); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pack_pb[0]); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, 32 * 32 / 8, NULL, GL_STREAM_DRAW); glGetPolygonStipple(NULL); pbo_mem = (GLubyte *) glMapBufferARB( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); } else { glGetPolygonStipple(t2); pbo_mem = t2; } for (i = 0; i < 32 * 32 / 8; i++) { if (pbo_mem[i] != 0xAA) { REPORT_FAILURE("glGetPolygonStipple failed"); return PIGLIT_FAIL; } } if (use_unpack) { glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, unpack_pb); } if (use_pack) { glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pack_pb); } glEnable(GL_POLYGON_STIPPLE); glColor4f(1.0, 1.0, 1.0, 0.0); glBegin(GL_POLYGON); glVertex2f(0, 0); glVertex2f(10, 0); glVertex2f(10, 10); glVertex2f(0, 10); glEnd(); glDisable(GL_POLYGON_STIPPLE); /* Check the result */ glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, buf); for (j = 0; j < WINSIZE; j++) { for (i = 0; i < WINSIZE; i++) { int idx = (j * WINSIZE + i) * 3; if (!(i & 1) && i < 10 && j < 10) { expected[idx + 0] = white[0]; expected[idx + 1] = white[1]; expected[idx + 2] = white[2]; } else { expected[idx + 0] = black[0]; expected[idx + 1] = black[1]; expected[idx + 2] = black[2]; } } } pass &= piglit_compare_images_color(0, 0, WINSIZE, WINSIZE, 3, tolerance, expected, buf); } } return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
enum piglit_result test_tex_sub_image(void *null) { GLuint pbs[1]; GLfloat t[TEXSIZE * TEXSIZE * 3]; int i, j; int use_unpack = 0; GLfloat green[3] = { 0.0, 1.0, 0.0 }; GLfloat black[3] = { 0.0, 0.0, 0.0 }; GLfloat *pbo_mem = NULL; GLfloat buf[WINSIZE * WINSIZE * 3]; bool pass = true; GLfloat expected[WINSIZE * WINSIZE * 3]; GLfloat tolerance[4]; piglit_compute_probe_tolerance(GL_RGB, &tolerance[0]); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); for (use_unpack = 0; use_unpack < 2; use_unpack++) { pbo_mem = NULL; glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); if (use_unpack) { glGenBuffersARB(1, pbs); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbs[0]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, TEXSIZE * TEXSIZE * 3 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_RGB, GL_FLOAT, NULL); if (use_unpack) { glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbs[0]); pbo_mem = (GLfloat *) glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } else { pbo_mem = t; } for (i = 0; i < TEXSIZE * TEXSIZE; i++) { pbo_mem[3 * i] = 0.0; pbo_mem[3 * i + 1] = 1.0; pbo_mem[3 * i + 2] = 0.0; } if (use_unpack) { glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEXSIZE, TEXSIZE, GL_RGB, GL_FLOAT, NULL); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } else glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEXSIZE, TEXSIZE, GL_RGB, GL_FLOAT, pbo_mem); glEnable(GL_TEXTURE_2D); glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(10, 0); glTexCoord2f(1, 1); glVertex2f(10, 10); glTexCoord2f(0, 1); glVertex2f(0, 10); glEnd(); glDisable(GL_TEXTURE_2D); glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, buf); for (j = 0; j < WINSIZE; j++) { for (i = 0; i < WINSIZE; i++) { int idx = (j * WINSIZE + i) * 3; if (i < 10 && j < 10) { expected[idx + 0] = green[0]; expected[idx + 1] = green[1]; expected[idx + 2] = green[2]; } else { expected[idx + 0] = black[0]; expected[idx + 1] = black[1]; expected[idx + 2] = black[2]; } } } pass &= piglit_compare_images_color(0, 0, WINSIZE, WINSIZE, 3, tolerance, expected, buf); } return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
PIGLIT_GL_TEST_CONFIG_END enum piglit_result piglit_display(void) { GLboolean pass = GL_TRUE; static float red[] = {1.0, 0.0, 0.0, 0.0}; static float green[] = {0.0, 1.0, 0.0, 0.0}; static float blue[] = {0.0, 0.0, 1.0, 0.0}; static float white[] = {1.0, 1.0, 1.0, 0.0}; uint32_t red_packed = 0x00ff0000; uint32_t green_packed = 0x0000ff00; uint32_t blue_packed = 0x000000ff; uint32_t white_packed = 0x00ffffff; uint32_t *pixels; GLuint pbo, tex; glClearColor(0.5, 0.5, 0.5, 0.0); glClear(GL_COLOR_BUFFER_BIT); glGenBuffersARB(1, &pbo); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, pbo); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER, 1289 * 2 * sizeof(uint32_t), NULL, GL_STREAM_DRAW_ARB); glPixelStorei(GL_UNPACK_ROW_LENGTH, 129); pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY_ARB); pixels[0] = red_packed; pixels[1] = green_packed; pixels[129] = blue_packed; pixels[130] = white_packed; glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, 0); glDeleteBuffersARB(1, &pbo); glEnable(GL_TEXTURE_2D); glBegin(GL_TRIANGLE_FAN); glTexCoord2f(0.0, 0.0); glVertex2f(10, 10); glTexCoord2f(1.0, 0.0); glVertex2f(20, 10); glTexCoord2f(1.0, 1.0); glVertex2f(20, 20); glTexCoord2f(0.0, 1.0); glVertex2f(10, 20); glEnd(); glDeleteTextures(1, &tex); pass &= piglit_probe_pixel_rgb(12, 12, red); pass &= piglit_probe_pixel_rgb(18, 12, green); pass &= piglit_probe_pixel_rgb(12, 18, blue); pass &= piglit_probe_pixel_rgb(18, 18, white); piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
void unmap() const { _testInitialized(); EQ_GL_CALL( glUnmapBufferARB( _getName( ))); unbind(); }
enum piglit_result test_bitmap(void *null) { GLuint pb_unpack[1]; GLuint pb_pack[1]; int use_unpack = 1; int use_pack = 0; GLubyte bitmap[TEXSIZE * TEXSIZE / 8]; GLfloat buf[WINSIZE * WINSIZE * 3]; GLfloat white[3] = { 1.0, 1.0, 1.0 }; GLfloat black[3] = { 0.0, 0.0, 0.0 }; int i, j; GLubyte *pbo_unpack_mem = NULL; GLfloat *pbo_pack_mem = NULL; GLfloat expected[WINSIZE * WINSIZE * 3]; float tolerance[4]; bool pass = true; glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); for (use_pack = 0; use_pack < 2; use_pack++) { for (use_unpack = 0; use_unpack < 2; use_unpack++) { glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); if (use_unpack) { glGenBuffersARB(1, pb_unpack); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pb_unpack[0]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, TEXSIZE * TEXSIZE, NULL, GL_STREAM_DRAW); pbo_unpack_mem = (GLubyte *) glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } else { pbo_unpack_mem = bitmap; } for (i = 0; i < TEXSIZE * TEXSIZE / 8; i++) { pbo_unpack_mem[i] = 0xAA; /* Binary 10101010 */ } glColor4f(1.0, 1.0, 1.0, 0.0); glRasterPos2f(0.0, 0.0); if (use_unpack) { glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); /* Draw white into every other pixel, * for a white/black checkerboard. */ glBitmap(TEXSIZE, TEXSIZE, 0, 0, 0, 0, NULL); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } else { glBitmap(TEXSIZE, TEXSIZE, 0, 0, 0, 0, pbo_unpack_mem); } if (!piglit_automatic) piglit_present_results(); /* Check the result */ if (use_pack) { glGenBuffersARB(1, pb_pack); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pb_pack[0]); glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, WINSIZE * WINSIZE * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, NULL); pbo_pack_mem = (GLfloat *) glMapBufferARB( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); } else { pbo_pack_mem = buf; glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, pbo_pack_mem); } /* Compute expected and compare it to the result. */ for (j = 0; j < WINSIZE; j++) { for (i = 0; i < WINSIZE; i++) { int idx = (j * WINSIZE + i) * 3; if ((i & 1) || (i >= TEXSIZE) || (j >= TEXSIZE)) { expected[idx + 0] = black[0]; expected[idx + 1] = black[1]; expected[idx + 2] = black[2]; } else { expected[idx + 0] = white[0]; expected[idx + 1] = white[1]; expected[idx + 2] = white[2]; } } } piglit_compute_probe_tolerance(GL_RGB, &tolerance[0]); pass &= piglit_compare_images_color(0, 0, WINSIZE, WINSIZE, 3, tolerance, expected, pbo_pack_mem); if (use_pack) { glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pb_pack); } if (use_unpack) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glDeleteBuffersARB(1, pb_unpack); } } } return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
int main( int argc, char * argv[] ) { printf( "networked physics demo\n" ); bool shadows = true; bool playback = false; bool video = false; for ( int i = 1; i < argc; ++i ) { if ( strcmp( argv[i], "playback" ) == 0 ) { printf( "playback\n" ); playback = true; } else if ( strcmp( argv[i], "video" ) == 0 ) { printf( "video\n" ); video = true; } } net::InitializeSockets(); while ( !net::IsInitialized() ) { printf( "error: failed to initialize sockets\n" ); net::ShutdownSockets(); return 1; } #ifndef PROFILE int displayWidth, displayHeight; GetDisplayResolution( displayWidth, displayHeight ); #ifdef LETTERBOX displayWidth = 1280; displayHeight = 800; #endif printf( "display resolution is %d x %d\n", displayWidth, displayHeight ); HideMouseCursor(); if ( !OpenDisplay( "Networked Physics", displayWidth, displayHeight ) ) { printf( "error: failed to open display" ); return 1; } #endif int currentDemo = 0; Demo * demo = CreateDemo( 0 ); assert( demo ); demo->InitializeWorld(); renderInterface = new render::Interface( displayWidth, displayHeight ); #ifndef PROFILE demo->SetRenderInterface( renderInterface ); #endif uint32_t frame = 0; // create 2 pixel buffer objects, you need to delete them when program exits. // glBufferDataARB with NULL pointer reserves only memory space. const int NumPBOs = 2; GLuint pboIds[NumPBOs]; int index = 0; const int dataSize = displayWidth * displayHeight * 3; if ( video ) { glGenBuffersARB( NumPBOs, pboIds ); for ( int i = 0; i < NumPBOs; ++i ) { glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[i] ); glBufferDataARB( GL_PIXEL_UNPACK_BUFFER_ARB, dataSize, 0, GL_STREAM_DRAW_ARB ); } glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, 0 ); } // record input to a file // read it back in playback mode for recording video FILE * inputFile = fopen( "output/recordedInputs", playback ? "rb" : "wb" ); if ( !inputFile ) { printf( "failed to open input file\n" ); return 1; } bool quit = false; while ( !quit ) { #ifdef PROFILE printf( "profiling frame %d\n", frame ); #endif platform::Input input; if ( !playback ) { input = platform::Input::Sample(); fwrite( &input, sizeof( platform::Input ), 1, inputFile ); fflush( inputFile ); } else { const int size = sizeof( platform::Input ); if ( !fread( &input, size, 1, inputFile ) ) quit = true; } #ifdef PROFILE if ( frame > 500 ) input.left = frame % 2; else if ( frame > 100 && ( frame % 5 ) == 0 ) input.left = true; input.z = true; #endif if ( input.alt ) { int demoIndex = -1; if ( input.one ) demoIndex = 0; if ( input.two ) demoIndex = 1; if ( input.three ) demoIndex = 2; if ( input.four ) demoIndex = 3; if ( input.five ) demoIndex = 4; if ( input.six ) demoIndex = 5; if ( input.seven ) demoIndex = 6; if ( input.eight ) demoIndex = 7; if ( input.nine ) demoIndex = 8; if ( input.zero ) demoIndex = 9; static bool enterDownLastFrame = false; if ( input.enter && !enterDownLastFrame ) shadows = !shadows; enterDownLastFrame = input.enter; if ( demoIndex != -1 ) { Demo * newDemo = CreateDemo( demoIndex ); if ( newDemo ) { #ifndef PROFILE renderInterface->ClearScreen(); #ifdef LETTERBOX renderInterface->LetterBox( 80 ); #endif UpdateDisplay( 1 ); #endif delete demo; demo = newDemo; assert( demo ); demo->InitializeWorld(); #ifndef PROFILE demo->SetRenderInterface( renderInterface ); #endif currentDemo = demoIndex; } } } static bool escapeDownLastFrame = false; if ( input.escape && !escapeDownLastFrame ) { #ifndef PROFILE renderInterface->ClearScreen(); #ifdef LETTERBOX renderInterface->LetterBox( 80 ); #endif UpdateDisplay( 1 ); #endif delete demo; demo = CreateDemo( currentDemo ); assert( demo ); demo->InitializeWorld(); #ifndef PROFILE demo->SetRenderInterface( renderInterface ); #endif } escapeDownLastFrame = input.escape; demo->ProcessInput( !input.alt ? input : platform::Input() ); demo->Update( DeltaTime ); if ( video ) { // "index" is used to read pixels from framebuffer to a PBO // "nextIndex" is used to update pixels in the other PBO index = ( index + 1 ) % NumPBOs; int prevIndex = ( index + NumPBOs - 1 ) % NumPBOs; // set the target framebuffer to read glReadBuffer( GL_FRONT ); // read pixels from framebuffer to PBO // glReadPixels() should return immediately. glBindBufferARB( GL_PIXEL_PACK_BUFFER_ARB, pboIds[index] ); glReadPixels( 0, 0, displayWidth, displayHeight, GL_BGR, GL_UNSIGNED_BYTE, 0 ); if ( frame > (unsigned) NumPBOs ) { // map the PBO to process its data by CPU glBindBufferARB( GL_PIXEL_PACK_BUFFER_ARB, pboIds[prevIndex] ); GLubyte * ptr = (GLubyte*) glMapBufferARB( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB ); if ( ptr ) { char filename[256]; sprintf( filename, "output/frame-%05d.tga", frame - NumPBOs ); #ifdef LETTERBOX WriteTGA( filename, displayWidth, displayHeight - 80, ptr + displayWidth * 3 * 40 ); #else WriteTGA( filename, displayWidth, displayHeight, ptr ); #endif glUnmapBufferARB( GL_PIXEL_PACK_BUFFER_ARB ); } } // back to conventional pixel operation glBindBufferARB( GL_PIXEL_PACK_BUFFER_ARB, 0 ); } demo->WaitForSim(); #ifndef PROFILE demo->Render( DeltaTime, shadows ); #ifdef LETTERBOX renderInterface->LetterBox( 80 ); #endif UpdateDisplay( video ? 0 : 1 ); #endif frame ++; } #ifndef PROFILE CloseDisplay(); #endif delete demo; delete renderInterface; printf( "shutdown\n" ); net::ShutdownSockets(); return 0; }
void drawEarth(int numStrips,int numQuads,double scaleFactor,unsigned int vertexBufferObjectId,unsigned int indexBufferObjectId) { typedef GLVertex<GLfloat,2,void,0,GLfloat,GLfloat,3> Vertex; Geometry::Geoid<double> wgs84; // Standard reference ellipsoid double wgs84E2=(2.0-wgs84.getFlatteningFactor())*wgs84.getFlatteningFactor(); GLVertexArrayParts::enable(Vertex::getPartsMask()); /* Upload the vertex data into the vertex buffer: */ glBindBufferARB(GL_ARRAY_BUFFER_ARB,vertexBufferObjectId); glBufferDataARB(GL_ARRAY_BUFFER_ARB,(numStrips+1)*(numQuads+1)*sizeof(Vertex),0,GL_STATIC_DRAW_ARB); Vertex* vPtr=static_cast<Vertex*>(glMapBufferARB(GL_ARRAY_BUFFER_ARB,GL_WRITE_ONLY_ARB)); for(int i=0;i<=numStrips;++i) { float texY=float(i)/float(numStrips); double lat=(double(i)/double(numStrips)-0.5)*Math::Constants<double>::pi; double s=Math::sin(lat); double c=Math::cos(lat); double chi=Math::sqrt(1.0-wgs84E2*s*s); double xy=wgs84.getRadius()/chi*c*scaleFactor; double z=wgs84.getRadius()*(1.0-wgs84E2)/chi*s*scaleFactor; for(int j=0;j<=numQuads;++j,++vPtr) { float texX=float(j)/float(numQuads)+0.5f; double lng=(2.0*Math::Constants<double>::pi*double(j))/double(numQuads); double sl=Math::sin(lng); double cl=Math::cos(lng); vPtr->texCoord[0]=texX; vPtr->texCoord[1]=texY; vPtr->normal[0]=float(c*cl); vPtr->normal[1]=float(c*sl); vPtr->normal[2]=float(s); vPtr->position[0]=float(xy*cl); vPtr->position[1]=float(xy*sl); vPtr->position[2]=z; } } glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); /* Upload the index data into the index buffer: */ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,indexBufferObjectId); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,numStrips*(numQuads+1)*2*sizeof(GLuint),0,GL_STATIC_DRAW_ARB); GLuint* iPtr=static_cast<GLuint*>(glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,GL_WRITE_ONLY_ARB)); for(int i=0;i<numStrips;++i) { for(int j=0;j<=numQuads;++j,iPtr+=2) { iPtr[0]=(i+1)*(numQuads+1)+j; iPtr[1]=(i+0)*(numQuads+1)+j; } } glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); /* Render the quad strips: */ glVertexPointer(static_cast<Vertex*>(0)); GLubyte* stripBaseIndexPtr=0; for(int i=0;i<numStrips;++i) { glDrawElements(GL_QUAD_STRIP,(numQuads+1)*2,GL_UNSIGNED_INT,stripBaseIndexPtr); stripBaseIndexPtr+=(numQuads+1)*2*sizeof(GLuint); } glBindBufferARB(GL_ARRAY_BUFFER_ARB,0); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,0); GLVertexArrayParts::disable(Vertex::getPartsMask()); }
void ParticleSystem::_initialize(int numParticles) { assert(!m_bInitialized); m_numParticles = numParticles; // allocate host storage m_hPos = new float[m_numParticles*4]; m_hVel = new float[m_numParticles*4]; memset(m_hPos, 0, m_numParticles*4*sizeof(float)); memset(m_hVel, 0, m_numParticles*4*sizeof(float)); m_hCellStart = new uint[m_numGridCells]; memset(m_hCellStart, 0, m_numGridCells*sizeof(uint)); m_hCellEnd = new uint[m_numGridCells]; memset(m_hCellEnd, 0, m_numGridCells*sizeof(uint)); // allocate GPU data unsigned int memSize = sizeof(float) * 4 * m_numParticles; if (m_bUseOpenGL) { m_posVbo = createVBO(memSize); registerGLBufferObject(m_posVbo, &m_cuda_posvbo_resource); } else { checkCudaErrors(cudaMalloc((void **)&m_cudaPosVBO, memSize)) ; } allocateArray((void **)&m_dVel, memSize); allocateArray((void **)&m_dSortedPos, memSize); allocateArray((void **)&m_dSortedVel, memSize); allocateArray((void **)&m_dGridParticleHash, m_numParticles*sizeof(uint)); allocateArray((void **)&m_dGridParticleIndex, m_numParticles*sizeof(uint)); allocateArray((void **)&m_dCellStart, m_numGridCells*sizeof(uint)); allocateArray((void **)&m_dCellEnd, m_numGridCells*sizeof(uint)); if (m_bUseOpenGL) { m_colorVBO = createVBO(m_numParticles*4*sizeof(float)); registerGLBufferObject(m_colorVBO, &m_cuda_colorvbo_resource); // fill color buffer glBindBufferARB(GL_ARRAY_BUFFER, m_colorVBO); float *data = (float *) glMapBufferARB(GL_ARRAY_BUFFER, GL_WRITE_ONLY); float *ptr = data; for (uint i=0; i<m_numParticles; i++) { float t = i / (float) m_numParticles; #if 0 *ptr++ = rand() / (float) RAND_MAX; *ptr++ = rand() / (float) RAND_MAX; *ptr++ = rand() / (float) RAND_MAX; #else colorRamp(t, ptr); ptr+=3; #endif *ptr++ = 1.0f; } glUnmapBufferARB(GL_ARRAY_BUFFER); } else { checkCudaErrors(cudaMalloc((void **)&m_cudaColorVBO, sizeof(float)*numParticles*4)); } sdkCreateTimer(&m_timer); setParameters(&m_params); m_bInitialized = true; }
void drawDomhan(int numStrips,int numQuads,double scaleFactor,unsigned int vertexBufferObjectId,unsigned int indexBufferObjectId) { typedef GLVertex<GLfloat,2,void,0,GLfloat,GLfloat,3> Vertex; const double a=6378.14e3; // Equatorial radius in m const double f=1.0/298.247; // Geoid flattening factor GLVertexArrayParts::enable(Vertex::getPartsMask()); /* Upload the vertex data into the vertex buffer: */ glBindBufferARB(GL_ARRAY_BUFFER_ARB,vertexBufferObjectId); glBufferDataARB(GL_ARRAY_BUFFER_ARB,(numStrips+1)*(numQuads+1)*sizeof(Vertex),0,GL_STATIC_DRAW_ARB); Vertex* vPtr=static_cast<Vertex*>(glMapBufferARB(GL_ARRAY_BUFFER_ARB,GL_WRITE_ONLY_ARB)); for(int i=0;i<=numStrips;++i) { float texY=float(i)/float(numStrips); double lat=(double(i)/double(numStrips)-0.5)*Math::Constants<double>::pi; double s0=Math::sin(lat); double c0=Math::cos(lat); double r=a*(1.0-f*s0*s0)*scaleFactor; double xy=r*c0; float z=r*s0; for(int j=0;j<=numQuads;++j,++vPtr) { float texX=float(j)/float(numQuads)+0.5f; vPtr->texCoord[0]=texX; vPtr->texCoord[1]=texY; double lng=(2.0*Math::Constants<double>::pi*double(j))/double(numQuads); double s1=Math::sin(lng); double c1=Math::cos(lng); double nx=(1.0-3.0*f*s0*s0)*c0*c1; double ny=(1.0-3.0*f*s0*s0)*c0*s1; double nz=(1.0+3.0*f*c0*c0-f)*s0; double nl=Math::sqrt(nx*nx+ny*ny+nz*nz); vPtr->normal[0]=float(nx/nl); vPtr->normal[1]=float(ny/nl); vPtr->normal[2]=float(nz/nl); vPtr->position[0]=float(xy*c1); vPtr->position[1]=float(xy*s1); vPtr->position[2]=z; } } glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); /* Upload the index data into the index buffer: */ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,indexBufferObjectId); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,numStrips*(numQuads+1)*2*sizeof(GLuint),0,GL_STATIC_DRAW_ARB); GLuint* iPtr=static_cast<GLuint*>(glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,GL_WRITE_ONLY_ARB)); for(int i=0;i<numStrips;++i) { for(int j=0;j<=numQuads;++j,iPtr+=2) { iPtr[0]=(i+1)*(numQuads+1)+j; iPtr[1]=(i+0)*(numQuads+1)+j; } } glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); /* Render the quad strips: */ glVertexPointer(static_cast<Vertex*>(0)); GLubyte* stripBaseIndexPtr=0; for(int i=0;i<numStrips;++i) { glDrawElements(GL_QUAD_STRIP,(numQuads+1)*2,GL_UNSIGNED_INT,stripBaseIndexPtr); stripBaseIndexPtr+=(numQuads+1)*2*sizeof(GLuint); } glBindBufferARB(GL_ARRAY_BUFFER_ARB,0); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,0); GLVertexArrayParts::disable(Vertex::getPartsMask()); }
/** Documented at declaration */ int dxt_encoder_compress(struct dxt_encoder* encoder, DXT_IMAGE_TYPE* image, unsigned char* image_compressed) { #ifdef RTDXT_DEBUG glBeginQuery(GL_TIME_ELAPSED_EXT, encoder->queries[0]); #endif #ifdef RTDXT_DEBUG_HOST TIMER_INIT(); TIMER_START(); #endif #ifdef HAVE_GPUPERFAPI GPA_BeginPass(); GPA_BeginSample(0); #endif #ifdef USE_PBO_DXT_ENCODER GLubyte *ptr; #endif int data_size = encoder->width * encoder->height; switch(encoder->format) { case DXT_FORMAT_YUV422: data_size *= 2; break; case DXT_FORMAT_RGB: data_size *= 3; break; case DXT_FORMAT_RGBA: case DXT_FORMAT_YUV: data_size *= 4; break; } switch(encoder->format) { case DXT_FORMAT_YUV422: glBindFramebuffer(GL_FRAMEBUFFER, encoder->fbo444_id); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, encoder->texture_id, 0); glBindTexture(GL_TEXTURE_2D, encoder->texture_yuv422); glPushAttrib(GL_VIEWPORT_BIT); glViewport( 0, 0, encoder->width, encoder->height); #ifdef USE_PBO_DXT_ENCODER glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, encoder->pbo_in); // current pbo glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width / 2, encoder->height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, data_size, 0, GL_STREAM_DRAW_ARB); ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB); if(ptr) { // update data directly on the mapped buffer memcpy(ptr, image, data_size); glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release pointer to mapping buffer } #else glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width / 2, encoder->height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, image); #endif glUseProgram(encoder->yuv422_to_444_program); #ifdef RTDXT_DEBUG glEndQuery(GL_TIME_ELAPSED_EXT); glBeginQuery(GL_TIME_ELAPSED_EXT, encoder->queries[1]); #endif #ifdef HAVE_GPUPERFAPI GPA_EndSample(); GPA_BeginSample(1); #endif if(encoder->legacy) { glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0); glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0); glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0); glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0); glEnd(); } else { #if ! defined HAVE_MACOSX || OS_VERSION_MAJOR >= 11 // Compress glBindVertexArray(encoder->g_vao_422); //glDrawElements(GL_TRIANGLE_STRIP, sizeof(m_quad.indices) / sizeof(m_quad.indices[0]), GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); #endif } glPopAttrib(); /* there is some problem with restoring viewport state (Mac OS Lion, OpenGL 3.2) */ glViewport( 0, 0, (encoder->width + 3) / 4, encoder->height / 4); //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glUseProgram(encoder->program_compress); glBindFramebuffer(GL_FRAMEBUFFER, encoder->fbo_id); glBindTexture(GL_TEXTURE_2D, encoder->texture_id); //gl_check_error(); break; case DXT_FORMAT_YUV: case DXT_FORMAT_RGBA: glBindTexture(GL_TEXTURE_2D, encoder->texture_id); #ifdef USE_PBO_DXT_ENCODER glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, encoder->pbo_in); // current pbo glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width, encoder->height, GL_RGBA, DXT_IMAGE_GL_TYPE, 0); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, data_size, 0, GL_STREAM_DRAW_ARB); ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB); if(ptr) { // update data directly on the mapped buffer memcpy(ptr, image, data_size); glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release pointer to mapping buffer } #else glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width, encoder->height, GL_RGBA, DXT_IMAGE_GL_TYPE, image); #endif break; case DXT_FORMAT_RGB: glBindTexture(GL_TEXTURE_2D, encoder->texture_id); #ifdef USE_PBO_DXT_ENCODER glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, encoder->pbo_in); // current pbo glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width, encoder->height, GL_RGB, GL_UNSIGNED_BYTE, 0); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, data_size, 0, GL_STREAM_DRAW_ARB); ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB); if(ptr) { // update data directly on the mapped buffer memcpy(ptr, image, data_size); glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release pointer to mapping buffer } #else glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width, encoder->height, GL_RGB, GL_UNSIGNED_BYTE, image); #endif break; } #ifdef RTDXT_DEBUG glEndQuery(GL_TIME_ELAPSED_EXT); glBeginQuery(GL_TIME_ELAPSED_EXT, encoder->queries[2]); #endif #ifdef RTDXT_DEBUG_HOST glFinish(); TIMER_STOP_PRINT("Tex Load (+->444): "); TIMER_START(); #endif #ifdef HAVE_GPUPERFAPI GPA_EndSample(); GPA_BeginSample(2); #endif return dxt_encoder_compress_texture(encoder, encoder->texture_id, image_compressed); }
//////////////////////////////////////////////////////// // render // ///////////////////////////////////////////////////////// void pix_texture :: render(GemState *state) { m_didTexture=false; pushTexCoords(state); if(!m_textureOnOff)return; bool upsidedown=false; bool normalized=true; bool canMipmap=m_canMipmap; int texType = m_textureType; int x_2=1, y_2=1; bool useExternalTexture=false; int do_rectangle = (m_rectangle)?m_canRectangle:0; int newfilm = 0; pixBlock*img=NULL; state->get(GemState::_PIX, img); if(img) newfilm = img->newfilm; if (!img || !img->image.data){ if(m_extTextureObj>0) { useExternalTexture= true; m_rebuildList = false; m_textureObj = m_extTextureObj; if(m_extType)m_textureType=m_extType; texType=m_textureType; upsidedown=m_extUpsidedown; m_xRatio=m_extWidth; m_yRatio=m_extHeight; m_upsidedown=upsidedown; } else /* neither do we have an image nor an external texture */ return; } tex2state(state, m_coords, 4); if(!useExternalTexture){ upsidedown = img->image.upsidedown; if (img->newimage) m_rebuildList = true; m_imagebuf.xsize =img->image.xsize; m_imagebuf.ysize =img->image.ysize; m_imagebuf.csize =img->image.csize; m_imagebuf.format=img->image.format; m_imagebuf.type =img->image.type; m_imagebuf.data =img->image.data; x_2 = powerOfTwo(m_imagebuf.xsize); y_2 = powerOfTwo(m_imagebuf.ysize); normalized = ((m_imagebuf.xsize==x_2) && (m_imagebuf.ysize==y_2)); debug("normalized=%d\t%d - %d\t%d - %d", normalized, m_imagebuf.xsize, x_2, m_imagebuf.ysize, y_2); switch(do_rectangle) { case 2: m_textureType = GL_TEXTURE_RECTANGLE_ARB; debug("using mode 1:GL_TEXTURE_RECTANGLE_ARB"); normalized = 0; canMipmap = false; break; case 1: m_textureType = GL_TEXTURE_RECTANGLE_EXT; debug("using mode 1:GL_TEXTURE_RECTANGLE_EXT"); normalized = 0; canMipmap = false; break; default: m_textureType = GL_TEXTURE_2D; debug("using mode 0:GL_TEXTURE_2D"); normalized = 0; break; } debug("normalized=%d", normalized); } if (m_textureType!=texType){ debug("texType != m_textureType"); stopRendering();startRendering(); } if(GLEW_VERSION_1_3) { glActiveTexture(GL_TEXTURE0_ARB + m_texunit); } glEnable(m_textureType); glBindTexture(m_textureType, m_textureObj); if ((!useExternalTexture)&&newfilm ){ // tigital: shouldn't we also allow TEXTURE_2D here? if(NULL!=glTextureRangeAPPLE) { if ( GLEW_APPLE_texture_range ){ if(glTextureRangeAPPLE == NULL) { glTextureRangeAPPLE( m_textureType, m_imagebuf.xsize * m_imagebuf.ysize * m_imagebuf.csize, m_imagebuf.data ); debug("using glTextureRangeAPPLE()"); }else{ glTextureRangeAPPLE( m_textureType, 0, NULL ); } } } /* hmm, GL_TEXTURE_STORAGE_HINT_APPLE throws a GL-error on linux (and probably on w32 too) * how to do a run-time check for it? * * according to http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/chapter_10_section_2.html * this seems to be a part of the texture_range extension, so we check for that! */ if(GLEW_APPLE_texture_range) glTexParameteri( m_textureType, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE ); // GL_STORAGE_SHARED_APPLE - AGP texture path // GL_STORAGE_CACHED_APPLE - VRAM texture path // GL_STORAGE_PRIVATE_APPLE - normal texture path if(m_clientStorage) glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); } /* here comes the work: a new image has to be transfered from main memory to GPU and attached to a texture object */ if (m_rebuildList) { // if YUV is not supported on this platform, we have to convert it to RGB //(skip Alpha since it isnt used) const bool do_yuv = m_yuv && GLEW_APPLE_ycbcr_422; if (!do_yuv && m_imagebuf.format == GL_YUV422_GEM){ m_imagebuf.format=GL_RGB; m_imagebuf.csize=3; m_imagebuf.reallocate(); if(img)m_imagebuf.fromYUV422(img->image.data); } if (normalized) { m_buffer.xsize = m_imagebuf.xsize; m_buffer.ysize = m_imagebuf.ysize; m_buffer.csize = m_imagebuf.csize; m_buffer.format = m_imagebuf.format; m_buffer.type = m_imagebuf.type; m_buffer.reallocate(); m_xRatio=1.0; m_yRatio=1.0; m_upsidedown=upsidedown; tex2state(state, m_coords, 4); if (m_buffer.csize != m_dataSize[0] || m_buffer.xsize != m_dataSize[1] || m_buffer.ysize != m_dataSize[2]){ m_dataSize[0] = m_buffer.csize; m_dataSize[1] = m_buffer.xsize; m_dataSize[2] = m_buffer.ysize; } //if the texture is a power of two in size then there is no need to subtexture glTexImage2D(m_textureType, 0, m_imagebuf.csize, m_imagebuf.xsize, m_imagebuf.ysize, 0, m_imagebuf.format, m_imagebuf.type, m_imagebuf.data); m_hasMipmap = false; } else { // !normalized m_xRatio = (float)m_imagebuf.xsize; m_yRatio = (float)m_imagebuf.ysize; if ( !do_rectangle ) { m_xRatio /= (float)x_2; m_yRatio /= (float)y_2; m_buffer.xsize = x_2; m_buffer.ysize = y_2; } else { m_buffer.xsize = m_imagebuf.xsize; m_buffer.ysize = m_imagebuf.ysize; } m_buffer.csize = m_imagebuf.csize; m_buffer.format = m_imagebuf.format; m_buffer.type = m_imagebuf.type; m_buffer.reallocate(); m_upsidedown=upsidedown; tex2state(state, m_coords, 4); if (m_buffer.csize != m_dataSize[0] || m_buffer.xsize != m_dataSize[1] || m_buffer.ysize != m_dataSize[2]){ newfilm = 1; } //end of loop if size has changed // okay, load in the actual pixel data //when doing rectangle textures the buffer changes after every film is loaded this call makes sure the //texturing is updated as well to prevent crashes if(newfilm) { m_dataSize[0] = m_buffer.csize; m_dataSize[1] = m_buffer.xsize; m_dataSize[2] = m_buffer.ysize; if (m_buffer.format == GL_YUV422_GEM && !m_rectangle)m_buffer.setBlack(); if(m_numPbo>0) { if(GLEW_ARB_pixel_buffer_object) { if(m_pbo) { delete[]m_pbo; m_pbo=NULL; } m_pbo=new GLuint[m_numPbo]; glGenBuffersARB(m_numPbo, m_pbo); int i=0; for(i=0; i<m_numPbo; i++) { glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, m_pbo[i]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, m_buffer.xsize*m_buffer.ysize*m_buffer.csize, 0, GL_STREAM_DRAW_ARB); } glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } else { verbose(1, "PBOs not supported! disabling"); m_numPbo=0; } } //this is for dealing with power of 2 textures which need a buffer that's 2^n if ( !do_rectangle ) { glTexImage2D( m_textureType, 0, //m_buffer.csize, GL_RGBA, m_buffer.xsize, m_buffer.ysize, 0, m_buffer.format, m_buffer.type, m_buffer.data); m_hasMipmap = false; debug("TexImage2D non rectangle"); } else {//this deals with rectangle textures that are h*w glTexImage2D(m_textureType, 0, // m_buffer.csize, GL_RGBA, m_imagebuf.xsize, m_imagebuf.ysize, 0, m_imagebuf.format, m_imagebuf.type, m_imagebuf.data); m_hasMipmap = false; debug("TexImage2D rectangle"); } // just to make sure... img->newfilm = 0; } if(m_pbo && m_numPbo) { m_curPbo=(m_curPbo+1)%m_numPbo; int index=m_curPbo; int nextIndex=(m_curPbo+1)%m_numPbo; glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, m_pbo[index]); glTexSubImage2D(m_textureType, 0, 0, 0, m_imagebuf.xsize, m_imagebuf.ysize, m_imagebuf.format, m_imagebuf.type, NULL); /* <-- that's the key */ m_hasMipmap = false; glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, m_pbo[nextIndex]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, m_imagebuf.xsize * m_imagebuf.ysize * m_imagebuf.csize, 0, GL_STREAM_DRAW_ARB); GLubyte* ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB); if(ptr) { // update data off the mapped buffer memcpy(ptr, m_imagebuf.data, m_imagebuf.xsize * m_imagebuf.ysize * m_imagebuf.csize); glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release pointer to mapping buffer } /* unbind the current buffer */ glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } else { glTexSubImage2D(m_textureType, 0, 0, 0, // position m_imagebuf.xsize, m_imagebuf.ysize, m_imagebuf.format, m_imagebuf.type, m_imagebuf.data); m_hasMipmap = false; } } } // rebuildlist if (m_wantMipmap && canMipmap && !m_hasMipmap) { glGenerateMipmap(m_textureType); m_hasMipmap = true; } setTexFilters(m_textureMinQuality != GL_LINEAR_MIPMAP_LINEAR || (m_wantMipmap && canMipmap)); setTexCoords(m_coords, m_xRatio, m_yRatio, m_upsidedown); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, m_env); /* cleanup */ m_rebuildList = false; m_didTexture=true; state->set(GemState::_GL_TEX_UNITS, m_numTexUnits); // if we are using rectangle textures, this is a way to inform the downstream objects // (this is important for things like [pix_coordinate] // we don't use switch/case as _ARB and _EXT might be the same... if(m_textureType==GL_TEXTURE_RECTANGLE_ARB || m_textureType==GL_TEXTURE_RECTANGLE_EXT) { state->set(GemState::_GL_TEX_TYPE, 2); } else { state->set(GemState::_GL_TEX_TYPE, 1); } m_baseCoord.s=m_xRatio; m_baseCoord.t=m_yRatio; state->set(GemState::_GL_TEX_BASECOORD, m_baseCoord); state->set(GemState::_GL_TEX_ORIENTATION, upsidedown); sendExtTexture(m_textureObj, m_xRatio, m_yRatio, m_textureType, upsidedown); }
////////////////////////////////////////////////////////////////////// // readback // // Code to handle reading back of the FBO data (but with a specified FBO pointer) // ////////////////////////////////////////////////////////////////////// bool CheckBackBuffer::readback( GLuint width, GLuint height, GLuint bufObject ) { bool ret = false; if (m_bUseFBO) { if (m_bUsePBO) { printf("CheckBackBuffer::readback() FBO->PBO->m_pImageData\n"); // binds the PBO for readback bindReadback(); // bind FBO buffer (we want to transfer FBO -> PBO) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bufObject ); // Now initiate the readback to PBO glReadPixels(0, 0, width, height, getPixelFormat(), GL_UNSIGNED_BYTE, BUFFER_OFFSET(0)); ret = checkStatus(__FILE__, __LINE__, true); if (!ret) printf("CheckBackBuffer::readback() FBO->PBO checkStatus = %d\n", ret); // map - unmap simulates readback without the copy void *ioMem = glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); memcpy(m_pImageData, ioMem, width*height*m_Bpp); glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); // release the FBO glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // release the PBO unbindReadback(); } else { printf("CheckBackBuffer::readback() FBO->m_pImageData\n"); // Reading direct to FBO using glReadPixels glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, bufObject ); ret = checkStatus(__FILE__, __LINE__, true); if (!ret) printf("CheckBackBuffer::readback::glBindFramebufferEXT() fbo=%d checkStatus = %d\n", bufObject, ret); glReadBuffer(static_cast<GLenum>(GL_COLOR_ATTACHMENT0_EXT)); ret &= checkStatus(__FILE__, __LINE__, true); if (!ret) printf("CheckBackBuffer::readback::glReadBuffer() fbo=%d checkStatus = %d\n", bufObject, ret); glReadPixels(0, 0, width, height, getPixelFormat(), GL_UNSIGNED_BYTE, m_pImageData); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } } else { printf("CheckBackBuffer::readback() PBO->m_pImageData\n"); // read from bufObject (PBO) to system memorys image glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, bufObject); // Bind the PBO // map - unmap simulates readback without the copy void *ioMem = glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB); // allocate a buffer so we can flip the image unsigned char * temp_buf = (unsigned char *)malloc(width*height*m_Bpp); memcpy( temp_buf, ioMem, width*height*m_Bpp ); // let's flip the image as we copy for (unsigned int y = 0; y < height; y++) { memcpy( (void *)&(m_pImageData[(height-y)*width*m_Bpp]), (void *)&(temp_buf[y*width*m_Bpp]), width*m_Bpp); } free(temp_buf); glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); // read from bufObject (PBO) to system memory image glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); // unBind the PBO } return CHECK_FBO; }
void CVertexBuffer::_unmap(){ glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); }