/** Run a couple of tests with the given base texture size */ static int test_size(GLuint basew, GLuint baseh) { int lvls, lvl; GLuint w = basew; GLuint h = baseh; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); teximage2d(0, w, h, testnr); if (!cell(testnr, 0, basew, baseh, testnr, "Nearest filtering, base size %ix%i", basew, baseh)) return 0; testnr++; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); for(lvls = 0; w >= 1 || h >= 1; lvls++, w >>= 1, h >>= 1) { if (!w) w = 1; if (!h) h = 1; teximage2d(lvls, w, h, testnr+lvls); } for(lvl = 0; lvl < lvls; ++lvl) { if (!cell(testnr+lvl, lvl, basew, baseh, testnr+lvl, "Mip filtering, base size %ix%i, level %i", basew, baseh, lvl)) return 0; } testnr += lvls; return 1; }
//this function currently assumes that the new texture has the same size as the old int r1_opengl_texture_manager_class::set_texture_image(r1_texture_handle handle, i4_image_class * im) { w32 tid=registered_tnames[handle].id; i4_image_class * memim; for (int i=0; i<memory_images.size(); i++) { if (memory_images[i].id==tid) { delete memory_images[i].image; memory_images[i].image=im->copy(); //replace saved memory image with new copy sw32 act_w=0,act_h=0; r1_miplevel_t * mip=get_texture(handle,0,max_texture_dimention,act_w,act_h); used_node * u=(used_node *) mip->vram_handle; float b1,b2; select_texture(u,b1,b2); u->data=im->data; teximage2d(u); u->data=0; return i4_T; } } return i4_F; }
// bind all textures respresented in finished_array void r1_opengl_texture_manager_class::next_frame() { r1_texture_manager_class::next_frame(); if (!finished_array.size()) { return; } array_lock.lock(); i4_image_class * im=NULL; // get texture names GLuint * texnames = (GLuint *)I4_MALLOC(finished_array.size() * sizeof(GLuint),"failure calling i4_malloc"); glGenTextures(finished_array.size(), texnames); for (sw32 i=0; i<finished_array.size(); i++) { used_node * u = finished_array[i]; // put it in vram u->mip->vram_handle = u; u->mip->flags &= (~R1_MIPLEVEL_IS_LOADING); if (u->mip->last_frame_used != -1) { u->mip->last_frame_used = frame_count; } tex_no_heap->update_usage((r1_tex_no_heap_used_node *)u); if (u->mip->flags & R1_MIPLEVEL_JPG_ALREADY_LOADED) { //Case 2: The file was already in mem, just copy data for(int x=0; x<image_list.size(); x++) { if (image_list[x].id==u->mip->entry->id) { im=image_list[x].image; image_list[x].usage=30; image_list[x].unlock(); } //image_list[x].usage--; //if (image_list[x].usage==0) image_list[x].usage=1; } I4_ASSERT(im,"Internal error in texture loader: Image deleted during access."); if (u->data) { delete u->data; } u->data=0; u->data=new w8[u->mip->width*u->mip->height*2]; size_image_to_texture(u->data,im, u->mip->width,u->mip->height,2, u->mip->entry->is_transparent(), u->mip->entry->is_alphatexture()); u->mip->flags &=~R1_MIPLEVEL_JPG_ALREADY_LOADED; } // assign the texture handle, bind it u->gltexname = texnames[i]; glBindTexture(GL_TEXTURE_2D, u->gltexname); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); teximage2d(u); delete u->data; u->data = 0; no_of_textures_loaded--; } i4_free(texnames); finished_array.clear(); array_lock.unlock(); if (tex_no_heap->needs_cleanup) { tex_no_heap->free_really_old(); } bytes_loaded = 0; //no_of_textures_loaded = 0; }
i4_bool r1_opengl_texture_manager_class::immediate_mip_load(r1_mip_load_info * load_info) { if (no_of_textures_loaded > 0) { if (load_info->dest_mip->last_frame_used != -1) { load_info->error = R1_MIP_LOAD_BUSY; return i4_F; } } r1_miplevel_t * mip = load_info->dest_mip; used_node * new_used = make_new_used_node(load_info); if (!new_used) { return i4_F; } new_used->async_fp=0; new_used->mip=0; new_used->data = (w8 *) new w8[(mip->width*mip->height*2) ]; //(w8 *)i4_malloc(mip->width * mip->height * 2,"failure calling i4_malloc"); if (load_info->src_file) { //for opengl, we currently use only this case, since we support only 16 bit color depth //This is for loading data from the tex_cache only, where the data format //is always known. //Unfortunatelly, the above statement is just plain wrong... This //code is also used to load up the lowest miplevel (distant terrain) //texture. Therefore, we convert here if (load_info->flags & R1_MIPFLAGS_SRC32) { w32 co=0,r=0,g=0,b=0; w16 * tex=(w16 *)(new_used->data); const i4_pal * p=i4_pal_man.default_no_alpha_32(); for (int i=0; i<mip->width*mip->height; i++) { //The order here is a bit strange (argb backwards). //I don't know why it should be like this (testing shows it's right on my system, //but it might as well be hardware dependent) b=load_info->src_file->read_8(); g=load_info->src_file->read_8(); r=load_info->src_file->read_8(); load_info->src_file->read_8(); co=p->convert(r<<16|g<<8|b,®ular_format); tex[i]=(w16)co; } } else { load_info->src_file->read(new_used->data,mip->width * mip->height * 2); } } else { load_texture_from_file(load_info->texture_name, mip->entry->id,new_used->data, mip->width, mip->height, mip->width*2, 2, mip->entry->is_transparent(), mip->entry->is_alphatexture()); } mip->vram_handle = new_used; if (mip->last_frame_used != -1) { mip->last_frame_used = frame_count; } new_used->mip = mip; new_used->async_fp = 0; glGenTextures(1,&new_used->gltexname); glBindTexture(GL_TEXTURE_2D, new_used->gltexname); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); teximage2d(new_used); //i4_free(new_used->data); delete [] new_used->data; new_used->data = 0; //bytes_loaded += mip->width * mip->height * 2; //no_of_textures_loaded++; return i4_T; }