Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Mon, 4 Jun 2018 07:10:51 +0000 (09:10 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 4 Jun 2018 07:11:45 +0000 (09:11 +0200)
13 files changed:
1  2 
source/blender/gpu/GPU_texture.h
source/blender/gpu/intern/gpu_basic_shader.c
source/blender/gpu/intern/gpu_buffers.c
source/blender/gpu/intern/gpu_codegen.c
source/blender/gpu/intern/gpu_framebuffer.c
source/blender/gpu/intern/gpu_material.c
source/blender/gpu/intern/gpu_select_pick.c
source/blender/gpu/intern/gpu_select_sample_query.c
source/blender/gpu/intern/gpu_shader.c
source/blender/gpu/intern/gpu_texture.c
source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
source/blender/gpu/shaders/gpu_shader_vertex.glsl

@@@ -39,8 -39,7 +39,8 @@@ extern "C" 
  struct Image;
  struct ImageUser;
  struct PreviewImage;
-       
 +struct Gwn_VertBuf;
  struct GPUFrameBuffer;
  typedef struct GPUTexture GPUTexture;
  
@@@ -237,8 -388,8 +237,8 @@@ static GPUShader *gpu_basic_shader(int 
                        datatoc_gpu_shader_basic_frag_glsl,
                        geom_glsl,
                        NULL,
 -                      defines, 0, 0, 0);
 +                      defines);
-               
                if (shader) {
                        /* set texture map to first texture unit */
                        if (options & (GPU_SHADER_TEXTURE_2D | GPU_SHADER_TEXTURE_RECT)) {
@@@ -438,30 -1283,29 +438,30 @@@ void GPU_pbvh_grid_buffers_update
                                for (y = 0; y < key->grid_size; y++) {
                                        for (x = 0; x < key->grid_size; x++) {
                                                CCGElem *elem = CCG_grid_elem(key, grid, x, y);
 +                                              GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, CCG_elem_co(key, elem));
  
 -                                              copy_v3_v3(vd->co, CCG_elem_co(key, elem));
                                                if (buffers->smooth) {
 -                                                      normal_float_to_short_v3(vd->no, CCG_elem_no(key, elem));
 +                                                      short no_short[3];
 +                                                      normal_float_to_short_v3(no_short, CCG_elem_no(key, elem));
 +                                                      GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
  
                                                        if (has_mask) {
 +                                                              uchar color_ub[3];
                                                                if (show_mask) {
                                                                        gpu_color_from_mask_copy(*CCG_elem_mask(key, elem),
 -                                                                                               diffuse_color, vd->color);
 +                                                                                               diffuse_color, color_ub);
                                                                }
                                                                else {
 -                                                                      unit_float_to_uchar_clamp_v3(vd->color, diffuse_color);
 +                                                                      unit_float_to_uchar_clamp_v3(color_ub, diffuse_color);
                                                                }
 +                                                              GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
                                                        }
                                                }
 -                                              vd++;
 +                                              vbo_index += 1;
                                        }
                                }
-                               
                                if (!buffers->smooth) {
 -                                      /* for flat shading, recalc normals and set the last vertex of
 -                                       * each triangle in the index buffer to have the flat normal as
 -                                       * that is what opengl will use */
                                        for (j = 0; j < key->grid_size - 1; j++) {
                                                for (k = 0; k < key->grid_size - 1; k++) {
                                                        CCGElem *elems[4] = {
@@@ -865,13 -1739,12 +865,13 @@@ void GPU_pbvh_bmesh_buffers_update
                                                fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset);
                                        }
                                        fmask /= 3.0f;
-                                       
                                        for (i = 0; i < 3; i++) {
 -                                              gpu_bmesh_vert_to_buffer_copy(v[i], vert_data,
 -                                                                            &v_index, f->no, &fmask,
 -                                                                            cd_vert_mask_offset, diffuse_color,
 -                                                                            show_mask);
 +                                              gpu_bmesh_vert_to_buffer_copy__gwn(
 +                                                      v[i], buffers->vert_buf,
 +                                                      &v_index, f->no, &fmask,
 +                                                      cd_vert_mask_offset, diffuse_color,
 +                                                      show_mask);
                                        }
                                }
                        }
@@@ -679,8 -503,7 +679,8 @@@ GPUOffScreen *GPU_offscreen_create(int 
        /* check validity at the very end! */
        if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
                GPU_offscreen_free(ofs);
-               return NULL;            
 +              gpuPopAttrib();
+               return NULL;
        }
  
        GPU_framebuffer_restore();
@@@ -82,12 -97,8 +82,12 @@@ struct GPUMaterial 
  
        /* material for mesh surface, worlds or something else.
         * some code generation is done differently depending on the use case */
 -      int type;
 +      int type; /* DEPRECATED */
 +      GPUMaterialStatus status;
 +
 +      const void *engine_type;   /* attached engine type */
 +      int options;    /* to identify shader variations (shadow, probe, world background...) */
-       
        /* for creating the material */
        ListBase nodes;
        GPUNodeLink *outlink;
@@@ -670,6 -2228,686 +670,6 @@@ void GPU_materials_free(void
  
        for (wo = G.main->world.first; wo; wo = wo->id.next)
                GPU_material_free(&wo->gpumaterial);
-       
        GPU_material_free(&defmaterial.gpumaterial);
 -
 -      for (ob = G.main->object.first; ob; ob = ob->id.next)
 -              GPU_lamp_free(ob);
  }
 -
 -/* Lamps and shadow buffers */
 -
 -static void gpu_lamp_calc_winmat(GPULamp *lamp)
 -{
 -      float temp, angle, pixsize, wsize;
 -
 -      if (lamp->type == LA_SUN) {
 -              wsize = lamp->la->shadow_frustum_size;
 -              orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
 -      }
 -      else if (lamp->type == LA_SPOT) {
 -              angle = saacos(lamp->spotsi);
 -              temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
 -              pixsize = lamp->d / temp;
 -              wsize = pixsize * 0.5f * lamp->size;
 -              /* compute shadows according to X and Y scaling factors */
 -              perspective_m4(
 -                      lamp->winmat,
 -                      -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0],
 -                      -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1],
 -                      lamp->d, lamp->clipend);
 -      }
 -}
 -
 -void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
 -{
 -      float mat[4][4];
 -      float obmat_scale[3];
 -
 -      lamp->lay = lay;
 -      lamp->hide = hide;
 -
 -      normalize_m4_m4_ex(mat, obmat, obmat_scale);
 -
 -      copy_v3_v3(lamp->vec, mat[2]);
 -      copy_v3_v3(lamp->co, mat[3]);
 -      copy_m4_m4(lamp->obmat, mat);
 -      invert_m4_m4(lamp->imat, mat);
 -
 -      if (lamp->type == LA_SPOT) {
 -              /* update spotlamp scale on X and Y axis */
 -              lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2];
 -              lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2];
 -      }
 -
 -      if (GPU_lamp_has_shadow_buffer(lamp)) {
 -              /* makeshadowbuf */
 -              gpu_lamp_calc_winmat(lamp);
 -      }
 -}
 -
 -void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
 -{
 -      lamp->energy = energy;
 -      if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
 -
 -      lamp->col[0] = r;
 -      lamp->col[1] = g;
 -      lamp->col[2] = b;
 -}
 -
 -void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
 -                              float coeff_const, float coeff_lin, float coeff_quad)
 -{
 -      lamp->dist = distance;
 -      lamp->att1 = att1;
 -      lamp->att2 = att2;
 -      lamp->coeff_const = coeff_const;
 -      lamp->coeff_lin = coeff_lin;
 -      lamp->coeff_quad = coeff_quad;
 -}
 -
 -void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
 -{
 -      lamp->spotsi = cosf(spotsize * 0.5f);
 -      lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
 -}
 -
 -static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
 -{
 -      lamp->scene = scene;
 -      lamp->ob = ob;
 -      lamp->par = par;
 -      lamp->la = la;
 -
 -      /* add_render_lamp */
 -      lamp->mode = la->mode;
 -      lamp->type = la->type;
 -
 -      lamp->energy = la->energy;
 -      if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
 -
 -      lamp->col[0] = la->r;
 -      lamp->col[1] = la->g;
 -      lamp->col[2] = la->b;
 -
 -      GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
 -
 -      lamp->spotsi = la->spotsize;
 -      if (lamp->mode & LA_HALO)
 -              if (lamp->spotsi > DEG2RADF(170.0f))
 -                      lamp->spotsi = DEG2RADF(170.0f);
 -      lamp->spotsi = cosf(lamp->spotsi * 0.5f);
 -      lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend;
 -      lamp->k = la->k;
 -
 -      lamp->dist = la->dist;
 -      lamp->falloff_type = la->falloff_type;
 -      lamp->att1 = la->att1;
 -      lamp->att2 = la->att2;
 -      lamp->coeff_const = la->coeff_const;
 -      lamp->coeff_lin = la->coeff_lin;
 -      lamp->coeff_quad = la->coeff_quad;
 -      lamp->curfalloff = la->curfalloff;
 -
 -      /* initshadowbuf */
 -      lamp->bias = 0.02f * la->bias;
 -      lamp->size = la->bufsize;
 -      lamp->d = la->clipsta;
 -      lamp->clipend = la->clipend;
 -
 -      /* arbitrary correction for the fact we do no soft transition */
 -      lamp->bias *= 0.25f;
 -}
 -
 -static void gpu_lamp_shadow_free(GPULamp *lamp)
 -{
 -      if (lamp->tex) {
 -              GPU_texture_free(lamp->tex);
 -              lamp->tex = NULL;
 -      }
 -      if (lamp->depthtex) {
 -              GPU_texture_free(lamp->depthtex);
 -              lamp->depthtex = NULL;
 -      }
 -      if (lamp->fb) {
 -              GPU_framebuffer_free(lamp->fb);
 -              lamp->fb = NULL;
 -      }
 -      if (lamp->blurtex) {
 -              GPU_texture_free(lamp->blurtex);
 -              lamp->blurtex = NULL;
 -      }
 -      if (lamp->blurfb) {
 -              GPU_framebuffer_free(lamp->blurfb);
 -              lamp->blurfb = NULL;
 -      }
 -}
 -
 -GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
 -{
 -      Lamp *la;
 -      GPULamp *lamp;
 -      LinkData *link;
 -
 -      for (link = ob->gpulamp.first; link; link = link->next) {
 -              lamp = (GPULamp *)link->data;
 -
 -              if (lamp->par == par && lamp->scene == scene)
 -                      return link->data;
 -      }
 -
 -      lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
 -
 -      link = MEM_callocN(sizeof(LinkData), "GPULampLink");
 -      link->data = lamp;
 -      BLI_addtail(&ob->gpulamp, link);
 -
 -      la = ob->data;
 -      gpu_lamp_from_blender(scene, ob, par, la, lamp);
 -
 -      if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
 -          (la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
 -      {
 -              /* opengl */
 -              lamp->fb = GPU_framebuffer_create();
 -              if (!lamp->fb) {
 -                      gpu_lamp_shadow_free(lamp);
 -                      return lamp;
 -              }
 -
 -              if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
 -                      /* Shadow depth map */
 -                      lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
 -                      if (!lamp->depthtex) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -
 -                      if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, NULL)) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -
 -                      /* Shadow color map */
 -                      lamp->tex = GPU_texture_create_vsm_shadow_map(lamp->size, NULL);
 -                      if (!lamp->tex) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -
 -                      if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -
 -                      if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -
 -                      /* FBO and texture for blurring */
 -                      lamp->blurfb = GPU_framebuffer_create();
 -                      if (!lamp->blurfb) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -
 -                      lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size * 0.5, NULL);
 -                      if (!lamp->blurtex) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -
 -                      if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, NULL)) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -
 -                      /* we need to properly bind to test for completeness */
 -                      GPU_texture_bind_as_framebuffer(lamp->blurtex);
 -
 -                      if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -
 -                      GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
 -              }
 -              else {
 -                      lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
 -                      if (!lamp->tex) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -
 -                      if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -
 -                      if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
 -                              gpu_lamp_shadow_free(lamp);
 -                              return lamp;
 -                      }
 -              }
 -
 -              GPU_framebuffer_restore();
 -
 -              lamp->shadow_color[0] = la->shdwr;
 -              lamp->shadow_color[1] = la->shdwg;
 -              lamp->shadow_color[2] = la->shdwb;
 -      }
 -      else {
 -              lamp->shadow_color[0] = 1.0;
 -              lamp->shadow_color[1] = 1.0;
 -              lamp->shadow_color[2] = 1.0;
 -      }
 -
 -      return lamp;
 -}
 -
 -void GPU_lamp_free(Object *ob)
 -{
 -      GPULamp *lamp;
 -      LinkData *link;
 -      LinkData *nlink;
 -      Material *ma;
 -
 -      for (link = ob->gpulamp.first; link; link = link->next) {
 -              lamp = link->data;
 -
 -              while (lamp->materials.first) {
 -                      nlink = lamp->materials.first;
 -                      ma = nlink->data;
 -                      BLI_freelinkN(&lamp->materials, nlink);
 -
 -                      if (ma->gpumaterial.first)
 -                              GPU_material_free(&ma->gpumaterial);
 -              }
 -
 -              gpu_lamp_shadow_free(lamp);
 -
 -              MEM_freeN(lamp);
 -      }
 -
 -      BLI_freelistN(&ob->gpulamp);
 -}
 -
 -bool GPU_lamp_has_shadow_buffer(GPULamp *lamp)
 -{
 -      return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) &&
 -              !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) &&
 -              lamp->tex && lamp->fb);
 -}
 -
 -void GPU_lamp_update_buffer_mats(GPULamp *lamp)
 -{
 -      float rangemat[4][4], persmat[4][4];
 -
 -      /* initshadowbuf */
 -      invert_m4_m4(lamp->viewmat, lamp->obmat);
 -      normalize_v3(lamp->viewmat[0]);
 -      normalize_v3(lamp->viewmat[1]);
 -      normalize_v3(lamp->viewmat[2]);
 -
 -      /* makeshadowbuf */
 -      mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat);
 -
 -      /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */
 -      unit_m4(rangemat);
 -      rangemat[0][0] = 0.5f;
 -      rangemat[1][1] = 0.5f;
 -      rangemat[2][2] = 0.5f;
 -      rangemat[3][0] = 0.5f;
 -      rangemat[3][1] = 0.5f;
 -      rangemat[3][2] = 0.5f;
 -
 -      mul_m4_m4m4(lamp->persmat, rangemat, persmat);
 -}
 -
 -void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4])
 -{
 -      GPU_lamp_update_buffer_mats(lamp);
 -
 -      /* opengl */
 -      glDisable(GL_SCISSOR_TEST);
 -      GPU_texture_bind_as_framebuffer(lamp->tex);
 -      if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
 -              GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
 -
 -      /* set matrices */
 -      copy_m4_m4(viewmat, lamp->viewmat);
 -      copy_m4_m4(winmat, lamp->winmat);
 -      *winsize = lamp->size;
 -}
 -
 -void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
 -{
 -      if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
 -              GPU_shader_unbind();
 -              GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
 -      }
 -
 -      GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
 -      GPU_framebuffer_restore();
 -      glEnable(GL_SCISSOR_TEST);
 -}
 -
 -int GPU_lamp_shadow_buffer_type(GPULamp *lamp)
 -{
 -      return lamp->la->shadowmap_type;
 -}
 -
 -int GPU_lamp_shadow_bind_code(GPULamp *lamp)
 -{
 -      return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1;
 -}
 -
 -float *GPU_lamp_dynpersmat(GPULamp *lamp)
 -{
 -      return &lamp->dynpersmat[0][0];
 -}
 -
 -int GPU_lamp_shadow_layer(GPULamp *lamp)
 -{
 -      if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW)))
 -              return lamp->lay;
 -      else
 -              return -1;
 -}
 -
 -GPUNodeLink *GPU_lamp_get_data(
 -        GPUMaterial *mat, GPULamp *lamp,
 -        GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy)
 -{
 -      GPUNodeLink *visifac;
 -
 -      *r_col = GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob);
 -      *r_energy = GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob);
 -      visifac = lamp_get_visibility(mat, lamp, r_lv, r_dist);
 -
 -      shade_light_textures(mat, lamp, r_col);
 -
 -      if (GPU_lamp_has_shadow_buffer(lamp)) {
 -              GPUNodeLink *vn, *inp;
 -
 -              GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &vn);
 -              GPU_link(mat, "shade_inp", vn, *r_lv, &inp);
 -              mat->dynproperty |= DYN_LAMP_PERSMAT;
 -
 -              if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
 -                      GPU_link(mat, "shadows_only_vsm",
 -                               GPU_builtin(GPU_VIEW_POSITION),
 -                               GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
 -                               GPU_dynamic_uniform((float *)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
 -                               GPU_uniform(&lamp->bias), GPU_uniform(&lamp->la->bleedbias),
 -                               GPU_uniform(lamp->shadow_color), inp, r_shadow);
 -              }
 -              else {
 -                      GPU_link(mat, "shadows_only",
 -                               GPU_builtin(GPU_VIEW_POSITION),
 -                               GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
 -                               GPU_dynamic_uniform((float *)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
 -                               GPU_uniform(&lamp->bias), GPU_uniform(lamp->shadow_color), inp, r_shadow);
 -              }
 -      }
 -      else {
 -              GPU_link(mat, "set_rgb_one", r_shadow);
 -      }
 -
 -      /* ensure shadow buffer and lamp textures will be updated */
 -      add_user_list(&mat->lamps, lamp);
 -      add_user_list(&lamp->materials, mat->ma);
 -
 -      return visifac;
 -}
 -
 -/* export the GLSL shader */
 -
 -GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
 -{
 -      static struct {
 -              GPUBuiltin gputype;
 -              GPUDynamicType dynamictype;
 -              GPUDataType datatype;
 -      } builtins[] = {
 -              { GPU_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWMAT, GPU_DATA_16F },
 -              { GPU_INVERSE_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWIMAT, GPU_DATA_16F },
 -              { GPU_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_MAT, GPU_DATA_16F },
 -              { GPU_INVERSE_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_IMAT, GPU_DATA_16F },
 -              { GPU_LOC_TO_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_LOCTOVIEWMAT, GPU_DATA_16F },
 -              { GPU_INVERSE_LOC_TO_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_LOCTOVIEWIMAT, GPU_DATA_16F },
 -              { GPU_OBCOLOR, GPU_DYNAMIC_OBJECT_COLOR, GPU_DATA_4F },
 -              { GPU_AUTO_BUMPSCALE, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE, GPU_DATA_1F },
 -              { 0 }
 -      };
 -
 -      GPUShaderExport *shader = NULL;
 -      GPUInput *input;
 -      int liblen, fraglen;
 -
 -      /* TODO(sergey): How to determine whether we need OSD or not here? */
 -      GPUMaterial *mat = GPU_material_from_blender(scene, ma, false);
 -      GPUPass *pass = (mat) ? mat->pass : NULL;
 -
 -      if (pass && pass->fragmentcode && pass->vertexcode) {
 -              shader = MEM_callocN(sizeof(GPUShaderExport), "GPUShaderExport");
 -
 -              for (input = pass->inputs.first; input; input = input->next) {
 -                      GPUInputUniform *uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
 -
 -                      if (input->ima) {
 -                              /* image sampler uniform */
 -                              uniform->type = GPU_DYNAMIC_SAMPLER_2DIMAGE;
 -                              uniform->datatype = GPU_DATA_1I;
 -                              uniform->image = input->ima;
 -                              uniform->texnumber = input->texid;
 -                              BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
 -                      }
 -                      else if (input->tex) {
 -                              /* generated buffer */
 -                              uniform->texnumber = input->texid;
 -                              uniform->datatype = GPU_DATA_1I;
 -                              BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
 -
 -                              switch (input->textype) {
 -                                      case GPU_SHADOW2D:
 -                                              uniform->type = GPU_DYNAMIC_SAMPLER_2DSHADOW;
 -                                              uniform->lamp = input->dynamicdata;
 -                                              break;
 -                                      case GPU_TEX2D:
 -                                              if (GPU_texture_opengl_bindcode(input->tex)) {
 -                                                      uniform->type = GPU_DYNAMIC_SAMPLER_2DBUFFER;
 -                                                      glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(input->tex));
 -                                                      uniform->texsize = GPU_texture_width(input->tex) * GPU_texture_height(input->tex);
 -                                                      uniform->texpixels = MEM_mallocN(uniform->texsize * 4, "RGBApixels");
 -                                                      glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, uniform->texpixels);
 -                                                      glBindTexture(GL_TEXTURE_2D, 0);
 -                                              }
 -                                              break;
 -
 -                                      case GPU_NONE:
 -                                      case GPU_TEXCUBE:
 -                                      case GPU_FLOAT:
 -                                      case GPU_VEC2:
 -                                      case GPU_VEC3:
 -                                      case GPU_VEC4:
 -                                      case GPU_MAT3:
 -                                      case GPU_MAT4:
 -                                      case GPU_ATTRIB:
 -                                              break;
 -                              }
 -                      }
 -                      else {
 -                              uniform->type = input->dynamictype;
 -                              BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
 -                              switch (input->type) {
 -                                      case GPU_FLOAT:
 -                                              uniform->datatype = GPU_DATA_1F;
 -                                              break;
 -                                      case GPU_VEC2:
 -                                              uniform->datatype = GPU_DATA_2F;
 -                                              break;
 -                                      case GPU_VEC3:
 -                                              uniform->datatype = GPU_DATA_3F;
 -                                              break;
 -                                      case GPU_VEC4:
 -                                              uniform->datatype = GPU_DATA_4F;
 -                                              break;
 -                                      case GPU_MAT3:
 -                                              uniform->datatype = GPU_DATA_9F;
 -                                              break;
 -                                      case GPU_MAT4:
 -                                              uniform->datatype = GPU_DATA_16F;
 -                                              break;
 -
 -                                      case GPU_NONE:
 -                                      case GPU_TEX2D:
 -                                      case GPU_TEXCUBE:
 -                                      case GPU_SHADOW2D:
 -                                      case GPU_ATTRIB:
 -                                              break;
 -                              }
 -
 -                              if (GPU_DYNAMIC_GROUP_FROM_TYPE(uniform->type) == GPU_DYNAMIC_GROUP_LAMP)
 -                                      uniform->lamp = input->dynamicdata;
 -
 -                              if (GPU_DYNAMIC_GROUP_FROM_TYPE(uniform->type) == GPU_DYNAMIC_GROUP_MAT)
 -                                      uniform->material = input->dynamicdata;
 -                      }
 -
 -                      if (uniform->type != GPU_DYNAMIC_NONE)
 -                              BLI_addtail(&shader->uniforms, uniform);
 -                      else
 -                              MEM_freeN(uniform);
 -              }
 -
 -              /* process builtin uniform */
 -              for (int i = 0; builtins[i].gputype; i++) {
 -                      if (mat->builtins & builtins[i].gputype) {
 -                              GPUInputUniform *uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
 -                              uniform->type = builtins[i].dynamictype;
 -                              uniform->datatype = builtins[i].datatype;
 -                              BLI_strncpy(uniform->varname, GPU_builtin_name(builtins[i].gputype), sizeof(uniform->varname));
 -                              BLI_addtail(&shader->uniforms, uniform);
 -                      }
 -              }
 -
 -              /* now link fragment shader with library shader */
 -              /* TBD: remove the function that are not used in the main function */
 -              liblen = (pass->libcode) ? strlen(pass->libcode) : 0;
 -              fraglen = strlen(pass->fragmentcode);
 -              shader->fragment = (char *)MEM_mallocN(liblen + fraglen + 1, "GPUFragShader");
 -              if (pass->libcode)
 -                      memcpy(shader->fragment, pass->libcode, liblen);
 -              memcpy(&shader->fragment[liblen], pass->fragmentcode, fraglen);
 -              shader->fragment[liblen + fraglen] = 0;
 -
 -              // export the attribute
 -              for (int i = 0; i < mat->attribs.totlayer; i++) {
 -                      GPUInputAttribute *attribute = MEM_callocN(sizeof(GPUInputAttribute), "GPUInputAttribute");
 -                      attribute->type = mat->attribs.layer[i].type;
 -                      attribute->number = mat->attribs.layer[i].glindex;
 -                      BLI_snprintf(attribute->varname, sizeof(attribute->varname), "att%d", mat->attribs.layer[i].attribid);
 -
 -                      switch (attribute->type) {
 -                              case CD_TANGENT:
 -                                      attribute->datatype = GPU_DATA_4F;
 -                                      break;
 -                              case CD_MTFACE:
 -                                      attribute->datatype = GPU_DATA_2F;
 -                                      attribute->name = mat->attribs.layer[i].name;
 -                                      break;
 -                              case CD_MCOL:
 -                                      attribute->datatype = GPU_DATA_4UB;
 -                                      attribute->name = mat->attribs.layer[i].name;
 -                                      break;
 -                              case CD_ORCO:
 -                                      attribute->datatype = GPU_DATA_3F;
 -                                      break;
 -                      }
 -
 -                      if (attribute->datatype != GPU_DATA_NONE)
 -                              BLI_addtail(&shader->attributes, attribute);
 -                      else
 -                              MEM_freeN(attribute);
 -              }
 -
 -              /* export the vertex shader */
 -              shader->vertex = BLI_strdup(pass->vertexcode);
 -      }
 -
 -      return shader;
 -}
 -
 -void GPU_free_shader_export(GPUShaderExport *shader)
 -{
 -      if (shader == NULL)
 -              return;
 -
 -      for (GPUInputUniform *uniform = shader->uniforms.first; uniform; uniform = uniform->next)
 -              if (uniform->texpixels)
 -                      MEM_freeN(uniform->texpixels);
 -
 -      BLI_freelistN(&shader->uniforms);
 -      BLI_freelistN(&shader->attributes);
 -
 -      if (shader->vertex)
 -              MEM_freeN(shader->vertex);
 -      if (shader->fragment)
 -              MEM_freeN(shader->fragment);
 -
 -      MEM_freeN(shader);
 -}
 -
 -#ifdef WITH_OPENSUBDIV
 -void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
 -                                     DerivedMesh *dm)
 -{
 -      GPUPass *pass = gpu_material->pass;
 -      GPUShader *shader = (pass != NULL ? pass->shader : NULL);
 -      ListBase *inputs = (pass != NULL ? &pass->inputs : NULL);
 -      GPUInput *input;
 -
 -      if (shader == NULL) {
 -              return;
 -      }
 -
 -      GPU_shader_bind(shader);
 -
 -      for (input = inputs->first;
 -           input != NULL;
 -           input = input->next)
 -      {
 -              if (input->source == GPU_SOURCE_ATTRIB &&
 -                  input->attribtype == CD_MTFACE)
 -              {
 -                      char name[64];
 -                      /* TODO(sergey): This will work for until names are
 -                       * consistent, we'll need to solve this somehow in the future.
 -                       */
 -                      int layer_index;
 -                      int location;
 -
 -                      if (input->attribname[0] != '\0') {
 -                              layer_index = CustomData_get_named_layer(&dm->loopData,
 -                                                                       CD_MLOOPUV,
 -                                                                       input->attribname);
 -                      }
 -                      else {
 -                              layer_index = CustomData_get_active_layer(&dm->loopData,
 -                                                                        CD_MLOOPUV);
 -                      }
 -
 -                      BLI_snprintf(name, sizeof(name),
 -                                   "fvar%d_offset",
 -                                   input->attribid);
 -                      location = GPU_shader_get_uniform(shader, name);
 -                      GPU_shader_uniform_int(shader, location, layer_index);
 -              }
 -      }
 -
 -      GPU_shader_unbind();
 -}
 -#endif
@@@ -756,13 -452,11 +756,13 @@@ GPUTexture *GPU_texture_from_preview(Pr
        tex->refcount = 1;
        tex->target = GL_TEXTURE_2D;
        tex->target_base = GL_TEXTURE_2D;
-       
 +      tex->format = -1;
 +      tex->components = -1;
        prv->gputexture[0] = tex;
-       
        if (!glIsTexture(tex->bindcode)) {
 -              GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
 +              GPU_print_error_debug("Blender Texture Not Loaded");
        }
        else {
                GLint w, h;
@@@ -1104,48 -713,17 +1104,48 @@@ void GPU_texture_free(GPUTexture *tex
  
        if (tex->refcount < 0)
                fprintf(stderr, "GPUTexture: negative refcount\n");
-       
        if (tex->refcount == 0) {
 -              if (tex->fb)
 -                      GPU_framebuffer_texture_detach(tex);
 -              if (tex->bindcode && !tex->fromblender)
 -                      glDeleteTextures(1, &tex->bindcode);
 +              for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
 +                      if (tex->fb[i] != NULL) {
 +                              GPU_framebuffer_texture_detach_slot(tex->fb[i], tex, tex->fb_attachment[i]);
 +                      }
 +              }
  
 -              MEM_freeN(tex);
 +              /* TODO(fclem): Check if the thread has an ogl context. */
 +              if (BLI_thread_is_main()) {
 +                      gpu_texture_delete(tex);
 +              }
-               else{
++              else {
 +                      BLI_mutex_lock(&g_orphan_lock);
 +                      BLI_addtail(&g_orphaned_tex, BLI_genericNodeN(tex));
 +                      BLI_mutex_unlock(&g_orphan_lock);
 +              }
        }
  }
  
-       while((link = BLI_pophead(&g_orphaned_tex))) {
 +void GPU_texture_init_orphans(void)
 +{
 +      BLI_mutex_init(&g_orphan_lock);
 +}
 +
 +void GPU_texture_delete_orphans(void)
 +{
 +      BLI_mutex_lock(&g_orphan_lock);
 +      LinkData *link;
++      while ((link = BLI_pophead(&g_orphaned_tex))) {
 +              gpu_texture_delete((GPUTexture *)link->data);
 +              MEM_freeN(link);
 +      }
 +      BLI_mutex_unlock(&g_orphan_lock);
 +}
 +
 +void GPU_texture_exit_orphans(void)
 +{
 +      GPU_texture_delete_orphans();
 +      BLI_mutex_end(&g_orphan_lock);
 +}
 +
  void GPU_texture_ref(GPUTexture *tex)
  {
        tex->refcount++;