<div dir="ltr"><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Feb 26, 2019 at 4:39 PM Chris Wilson <<a href="mailto:chris@chris-wilson.co.uk">chris@chris-wilson.co.uk</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">A few of the GEM drivers provide matching ioctls to allow control of<br>
their bo caches. Hook these up to APPLE_object_purgeable to allow<br>
clients to discard video memory under pressure where they are able to<br>
fallback to restoring content themselves, e.g. from their own (presumably<br>
compressed, on disk) caches.<br>
<br>
Cc: Eric Anholt <<a href="mailto:eric@anholt.net" target="_blank">eric@anholt.net</a>><br>
Cc: Kenneth Graunke <<a href="mailto:kenneth@whitecape.org" target="_blank">kenneth@whitecape.org</a>><br>
Cc: Rob Clark <<a href="mailto:robdclark@gmail.com" target="_blank">robdclark@gmail.com</a>><br>
---<br>
 .../drivers/freedreno/freedreno_resource.c    |  10 ++<br>
 .../drivers/freedreno/freedreno_screen.c      |   1 +<br>
 src/gallium/drivers/iris/iris_resource.c      |  10 ++<br>
 src/gallium/drivers/iris/iris_screen.c        |   1 +<br>
 src/gallium/drivers/vc4/vc4_bufmgr.c          |  15 ++<br>
 src/gallium/drivers/vc4/vc4_bufmgr.h          |   3 +<br>
 src/gallium/drivers/vc4/vc4_resource.c        |  10 ++<br>
 src/gallium/drivers/vc4/vc4_screen.c          |   3 +<br>
 src/gallium/include/pipe/p_defines.h          |   1 +<br>
 src/gallium/include/pipe/p_screen.h           |  20 +++<br>
 src/mesa/Makefile.sources                     |   2 +<br>
 src/mesa/meson.build                          |   2 +<br>
 src/mesa/state_tracker/st_cb_objectpurge.c    | 161 ++++++++++++++++++<br>
 src/mesa/state_tracker/st_cb_objectpurge.h    |  38 +++++<br>
 src/mesa/state_tracker/st_context.c           |   2 +<br>
 src/mesa/state_tracker/st_extensions.c        |   1 +<br>
 16 files changed, 280 insertions(+)<br>
 create mode 100644 src/mesa/state_tracker/st_cb_objectpurge.c<br>
 create mode 100644 src/mesa/state_tracker/st_cb_objectpurge.h<br>
<br>
diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c<br>
index 163fa70312a..5638d8efe33 100644<br>
--- a/src/gallium/drivers/freedreno/freedreno_resource.c<br>
+++ b/src/gallium/drivers/freedreno/freedreno_resource.c<br>
@@ -702,6 +702,15 @@ fd_resource_get_handle(struct pipe_screen *pscreen,<br>
                        rsc->slices[0].pitch * rsc->cpp, handle);<br>
 }<br>
<br>
+static boolean<br>
+fd_resource_madvise(struct pipe_screen *pscreen,<br>
+                    struct pipe_resource *resource,<br>
+                    boolean dontneed)<br>
+{<br>
+   struct fd_resource *rsc = fd_resource(prsc);<br>
+   return rsc->bo->madvise(rsc->bo, !dontneed);<br>
+}<br>
+<br>
 static uint32_t<br>
 setup_slices(struct fd_resource *rsc, uint32_t alignment, enum pipe_format format)<br>
 {<br>
@@ -1196,6 +1205,7 @@ fd_resource_screen_init(struct pipe_screen *pscreen)<br>
        pscreen->resource_create_with_modifiers = fd_resource_create_with_modifiers;<br>
        pscreen->resource_from_handle = fd_resource_from_handle;<br>
        pscreen->resource_get_handle = fd_resource_get_handle;<br>
+       pscreen->resource_madvise = fd_resource_madvise;<br>
        pscreen->resource_destroy = u_transfer_helper_resource_destroy;<br>
<br>
        pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl,<br>
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c<br>
index 5b107b87ba8..909cfecd6f9 100644<br>
--- a/src/gallium/drivers/freedreno/freedreno_screen.c<br>
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c<br>
@@ -194,6 +194,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)<br>
        case PIPE_CAP_MIXED_COLOR_DEPTH_BITS:<br>
        case PIPE_CAP_TEXTURE_BARRIER:<br>
        case PIPE_CAP_INVALIDATE_BUFFER:<br>
+       case PIPE_CAP_RESOURCE_MADVISE:<br>
                return 1;<br>
<br>
        case PIPE_CAP_VERTEXID_NOBASE:<br>
diff --git a/src/gallium/drivers/iris/iris_resource.c b/src/gallium/drivers/iris/iris_resource.c<br>
index b5829e94b36..d681dca7321 100644<br>
--- a/src/gallium/drivers/iris/iris_resource.c<br>
+++ b/src/gallium/drivers/iris/iris_resource.c<br>
@@ -1199,6 +1199,15 @@ iris_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource)<br>
 {<br>
 }<br>
<br>
+static boolean<br>
+iris_resource_madvise(struct pipe_screen *pscreen,<br>
+                      struct pipe_resource *resource,<br>
+                      boolean dontneed)<br>
+{<br>
+   struct iris_resource *res = (struct iris_resource *)resource;<br>
+   return iris_bo_madvise(res->bo, dontneed);<br>
+}<br>
+<br>
 void<br>
 iris_flush_and_dirty_for_history(struct iris_context *ice,<br>
                                  struct iris_batch *batch,<br>
@@ -1269,6 +1278,7 @@ iris_init_screen_resource_functions(struct pipe_screen *pscreen)<br>
    pscreen->resource_create = u_transfer_helper_resource_create;<br>
    pscreen->resource_from_user_memory = iris_resource_from_user_memory;<br>
    pscreen->resource_from_handle = iris_resource_from_handle;<br>
+   pscreen->resource_madvise = iris_resource_madvise;<br>
    pscreen->resource_get_handle = iris_resource_get_handle;<br>
    pscreen->resource_destroy = u_transfer_helper_resource_destroy;<br>
    pscreen->transfer_helper =<br>
diff --git a/src/gallium/drivers/iris/iris_screen.c b/src/gallium/drivers/iris/iris_screen.c<br>
index d831ffbc0a2..ecccf6af5e2 100644<br>
--- a/src/gallium/drivers/iris/iris_screen.c<br>
+++ b/src/gallium/drivers/iris/iris_screen.c<br>
@@ -172,6 +172,7 @@ iris_get_param(struct pipe_screen *pscreen, enum pipe_cap param)<br>
    case PIPE_CAP_GLSL_TESS_LEVELS_AS_INPUTS:<br>
    case PIPE_CAP_LOAD_CONSTBUF:<br>
    case PIPE_CAP_NIR_COMPACT_ARRAYS:<br>
+   case PIPE_CAP_RESOURCE_MADVISE:<br>
       return true;<br>
    case PIPE_CAP_TGSI_FS_FBFETCH:<br>
    case PIPE_CAP_POST_DEPTH_COVERAGE:<br>
diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.c b/src/gallium/drivers/vc4/vc4_bufmgr.c<br>
index 716ca50ea06..de0d3fcafeb 100644<br>
--- a/src/gallium/drivers/vc4/vc4_bufmgr.c<br>
+++ b/src/gallium/drivers/vc4/vc4_bufmgr.c<br>
@@ -663,6 +663,21 @@ vc4_bo_map(struct vc4_bo *bo)<br>
         return map;<br>
 }<br>
<br>
+bool<br>
+vc4_bo_madvise(struct vc4_bo *bo, bool dontneed)<br>
+{<br>
+       struct drm_vc4_gem_madvise arg = {<br>
+               .handle = bo->handle,<br>
+               .madv = dontneed ? VC4_MADV_DONTNEED : VC4_MADV_WILLNEED,<br>
+               .retained = true;<br>
+       };<br>
+<br>
+       if (bo->screen->has_madvise)<br>
+               vc4_ioctl(bo->screen->fd, DRM_IOCTL_VC4_GEM_MADVISE, &arg);<br>
+<br>
+       return arg.retained;<br>
+}<br>
+<br>
 void<br>
 vc4_bufmgr_destroy(struct pipe_screen *pscreen)<br>
 {<br>
diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.h b/src/gallium/drivers/vc4/vc4_bufmgr.h<br>
index 30a388ee599..dfb3aa65160 100644<br>
--- a/src/gallium/drivers/vc4/vc4_bufmgr.h<br>
+++ b/src/gallium/drivers/vc4/vc4_bufmgr.h<br>
@@ -143,6 +143,9 @@ vc4_wait_seqno(struct vc4_screen *screen, uint64_t seqno, uint64_t timeout_ns,<br>
 void<br>
 vc4_bo_label(struct vc4_screen *screen, struct vc4_bo *bo, const char *fmt, ...);<br>
<br>
+bool<br>
+vc4_bo_madvise(struct vc4_bo *bo, bool dontneed);<br>
+<br>
 void<br>
 vc4_bufmgr_destroy(struct pipe_screen *pscreen);<br>
<br>
diff --git a/src/gallium/drivers/vc4/vc4_resource.c b/src/gallium/drivers/vc4/vc4_resource.c<br>
index c12187d7872..d844c5d888a 100644<br>
--- a/src/gallium/drivers/vc4/vc4_resource.c<br>
+++ b/src/gallium/drivers/vc4/vc4_resource.c<br>
@@ -269,6 +269,15 @@ vc4_texture_subdata(struct pipe_context *pctx,<br>
                               box);<br>
 }<br>
<br>
+static boolean<br>
+vc4_resource_madvise(struct pipe_screen *pscreen,<br>
+                     struct pipe_resource *prsc,<br>
+                     boolean dontneed)<br>
+{<br>
+        struct vc4_resource *rsc = vc4_resource(prsc);<br>
+        return vc4_bo_madvise(rsc->bo, dontneed);<br>
+}<br>
+<br>
 static void<br>
 vc4_resource_destroy(struct pipe_screen *pscreen,<br>
                      struct pipe_resource *prsc)<br>
@@ -1136,6 +1145,7 @@ vc4_resource_screen_init(struct pipe_screen *pscreen)<br>
         pscreen->resource_from_handle = vc4_resource_from_handle;<br>
         pscreen->resource_destroy = u_resource_destroy_vtbl;<br>
         pscreen->resource_get_handle = vc4_resource_get_handle;<br>
+        pscreen->resource_madvise = vc4_resource_madvise;<br>
         pscreen->resource_destroy = vc4_resource_destroy;<br>
         pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl,<br>
                                                             false, false,<br>
diff --git a/src/gallium/drivers/vc4/vc4_screen.c b/src/gallium/drivers/vc4/vc4_screen.c<br>
index 5fc8c35f8a9..3b725b791bd 100644<br>
--- a/src/gallium/drivers/vc4/vc4_screen.c<br>
+++ b/src/gallium/drivers/vc4/vc4_screen.c<br>
@@ -150,6 +150,9 @@ vc4_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)<br>
         case PIPE_CAP_TEXTURE_BARRIER:<br>
                 return 1;<br>
<br>
+        case PIPE_CAP_RESOURCE_MADVISE:<br>
+               return screen->has_madvise;<br>
+<br>
         case PIPE_CAP_NATIVE_FENCE_FD:<br>
                 return screen->has_syncobj;<br>
<br>
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h<br>
index e2b0104ce43..edf733f70a8 100644<br>
--- a/src/gallium/include/pipe/p_defines.h<br>
+++ b/src/gallium/include/pipe/p_defines.h<br>
@@ -858,6 +858,7 @@ enum pipe_cap<br>
    PIPE_CAP_DEST_SURFACE_SRGB_CONTROL,<br>
    PIPE_CAP_NIR_COMPACT_ARRAYS,<br>
    PIPE_CAP_MAX_VARYINGS,<br>
+   PIPE_CAP_RESOURCE_MADVISE,<br>
 };<br>
<br>
 /**<br>
diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h<br>
index c4d6e1cc94f..8c5fa06d0bc 100644<br>
--- a/src/gallium/include/pipe/p_screen.h<br>
+++ b/src/gallium/include/pipe/p_screen.h<br>
@@ -222,6 +222,26 @@ struct pipe_screen {<br>
                                                        const struct pipe_resource *t,<br>
                                                        void *user_memory);<br>
<br>
+   /**<br>
+    * Mark the resource as either being unneeded or needed for the near future.<br>
+    *<br>
+    * If the resource is marked as dontneed, then the backend is at liberty<br>
+    * to free it as it chooses. Prior to future use, the client must call<br>
+    * with willneed, at which point it will be told whether the resource<br></blockquote><div><br></div><div>"willneed" doesn't occur in the interface.</div><div><br></div><div>Marek<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+    * is still available. The backend is only allowed to discard the<br>
+    * contents (and recover the memory used by the resource) while the<br>
+    * resource is marked as dontneed.<br>
+    *<br>
+    * Used by APPLE_object_purgeable.<br>
+    *<br>
+    * Returns true if the resource is still available (with its contents<br>
+    * retained), or false if the backend has freed it and discarded its contents<br>
+    * in the meantime.<br>
+    */<br>
+   boolean (*resource_madvise)(struct pipe_screen *screen,<br>
+                               struct pipe_resource *resource,<br>
+                               boolean dontneed);<br>
+<br>
    /**<br>
     * Unlike pipe_resource::bind, which describes what state trackers want,<br>
     * resources can have much greater capabilities in practice, often implied<br>
diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources<br>
index 1e25f47e509..2804b3475e9 100644<br>
--- a/src/mesa/Makefile.sources<br>
+++ b/src/mesa/Makefile.sources<br>
@@ -481,6 +481,8 @@ STATETRACKER_FILES = \<br>
        state_tracker/st_cb_memoryobjects.h \<br>
        state_tracker/st_cb_msaa.c \<br>
        state_tracker/st_cb_msaa.h \<br>
+       state_tracker/st_cb_objectpurge.c \<br>
+       state_tracker/st_cb_objectpurge.h \<br>
        state_tracker/st_cb_perfmon.c \<br>
        state_tracker/st_cb_perfmon.h \<br>
        state_tracker/st_cb_program.c \<br>
diff --git a/src/mesa/meson.build b/src/mesa/meson.build<br>
index d8a5682f6a0..ea69a5e5ef2 100644<br>
--- a/src/mesa/meson.build<br>
+++ b/src/mesa/meson.build<br>
@@ -525,6 +525,8 @@ files_libmesa_gallium = files(<br>
   'state_tracker/st_cb_memoryobjects.h',<br>
   'state_tracker/st_cb_msaa.c',<br>
   'state_tracker/st_cb_msaa.h',<br>
+  'state_tracker/st_cb_objectpurge.c',<br>
+  'state_tracker/st_cb_objectpurge.h',<br>
   'state_tracker/st_cb_perfmon.c',<br>
   'state_tracker/st_cb_perfmon.h',<br>
   'state_tracker/st_cb_program.c',<br>
diff --git a/src/mesa/state_tracker/st_cb_objectpurge.c b/src/mesa/state_tracker/st_cb_objectpurge.c<br>
new file mode 100644<br>
index 00000000000..c8c777481fe<br>
--- /dev/null<br>
+++ b/src/mesa/state_tracker/st_cb_objectpurge.c<br>
@@ -0,0 +1,161 @@<br>
+/**************************************************************************<br>
+ *<br>
+ * Copyright 2019 Intel Corporation<br>
+ * All Rights Reserved.<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the<br>
+ * "Software"), to deal in the Software without restriction, including<br>
+ * without limitation the rights to use, copy, modify, merge, publish,<br>
+ * distribute, sub license, and/or sell copies of the Software, and to<br>
+ * permit persons to whom the Software is furnished to do so, subject to<br>
+ * the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the<br>
+ * next paragraph) shall be included in all copies or substantial portions<br>
+ * of the Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS<br>
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br>
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.<br>
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR<br>
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,<br>
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE<br>
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<br>
+ *<br>
+ **************************************************************************/<br>
+<br>
+#include "st_cb_bufferobjects.h"<br>
+#include "st_cb_fbo.h"<br>
+#include "st_cb_objectpurge.h"<br>
+#include "st_context.h"<br>
+#include "st_texture.h"<br>
+<br>
+#include "pipe/p_screen.h"<br>
+<br>
+static boolean<br>
+pipe_resource_madvise(struct st_context *st,<br>
+                      struct pipe_resource *res,<br>
+                      boolean dontneed)<br>
+{<br>
+   struct pipe_screen *screen = st->pipe->screen;<br>
+   return screen->resource_madvise(screen, res, dontneed);<br>
+}<br>
+<br>
+static GLenum<br>
+st_buffer_object_purgeable(struct gl_context *ctx,<br>
+                           struct gl_buffer_object *obj,<br>
+                           GLenum option)<br>
+{<br>
+   struct st_context *st = st_context(ctx);<br>
+   struct st_buffer_object *stobj = st_buffer_object(obj);<br>
+<br>
+   if (stobj->buffer && pipe_resource_madvise(st, stobj->buffer, true))<br>
+      return GL_VOLATILE_APPLE;<br>
+   else<br>
+      return GL_RELEASED_APPLE;<br>
+}<br>
+<br>
+static GLenum<br>
+st_render_object_purgeable(struct gl_context *ctx,<br>
+                           struct gl_renderbuffer *obj,<br>
+                           GLenum option)<br>
+{<br>
+   struct st_context *st = st_context(ctx);<br>
+   struct st_renderbuffer *stobj = st_renderbuffer(obj);<br>
+<br>
+   if (stobj->texture && pipe_resource_madvise(st, stobj->texture, true))<br>
+      return GL_VOLATILE_APPLE;<br>
+   else<br>
+      return GL_RELEASED_APPLE;<br>
+}<br>
+<br>
+static GLenum<br>
+st_texture_object_purgeable(struct gl_context *ctx,<br>
+                            struct gl_texture_object *obj,<br>
+                            GLenum option)<br>
+{<br>
+   struct st_context *st = st_context(ctx);<br>
+   struct st_texture_object *stobj = st_texture_object(obj);<br>
+<br>
+   if (stobj->pt && pipe_resource_madvise(st, stobj->pt, true))<br>
+      return GL_VOLATILE_APPLE;<br>
+   else<br>
+      return GL_RELEASED_APPLE;<br>
+}<br>
+<br>
+static GLenum<br>
+st_buffer_object_unpurgeable(struct gl_context * ctx,<br>
+                             struct gl_buffer_object *obj,<br>
+                             GLenum option)<br>
+{<br>
+   struct st_context *st = st_context(ctx);<br>
+   struct st_buffer_object *stobj = st_buffer_object(obj);<br>
+<br>
+   if (!stobj->buffer)<br>
+      return GL_UNDEFINED_APPLE;<br>
+<br>
+   if (option == GL_UNDEFINED_APPLE ||<br>
+       !pipe_resource_madvise(st, stobj->buffer, false)) {<br>
+      pipe_resource_reference(&stobj->buffer, NULL);<br>
+      return GL_UNDEFINED_APPLE;<br>
+   }<br>
+<br>
+   return GL_RETAINED_APPLE;<br>
+}<br>
+<br>
+static GLenum<br>
+st_render_object_unpurgeable(struct gl_context * ctx,<br>
+                             struct gl_renderbuffer *obj,<br>
+                             GLenum option)<br>
+{<br>
+   struct st_context *st = st_context(ctx);<br>
+   struct st_renderbuffer *stobj = st_renderbuffer(obj);<br>
+<br>
+   if (!stobj->texture)<br>
+      return GL_UNDEFINED_APPLE;<br>
+<br>
+   if (option == GL_UNDEFINED_APPLE ||<br>
+       !pipe_resource_madvise(st, stobj->texture, false)) {<br>
+      pipe_resource_reference(&stobj->texture, NULL);<br>
+      return GL_UNDEFINED_APPLE;<br>
+   }<br>
+<br>
+   return GL_RETAINED_APPLE;<br>
+}<br>
+<br>
+static GLenum<br>
+st_texture_object_unpurgeable(struct gl_context * ctx,<br>
+                              struct gl_texture_object *obj,<br>
+                              GLenum option)<br>
+{<br>
+   struct st_context *st = st_context(ctx);<br>
+   struct st_texture_object *stobj = st_texture_object(obj);<br>
+<br>
+   if (!stobj->pt)<br>
+      return GL_UNDEFINED_APPLE;<br>
+<br>
+   if (option == GL_UNDEFINED_APPLE ||<br>
+       !pipe_resource_madvise(st, stobj->pt, false)) {<br>
+      pipe_resource_reference(&stobj->pt, NULL);<br>
+      return GL_UNDEFINED_APPLE;<br>
+   }<br>
+<br>
+   return GL_RETAINED_APPLE;<br>
+}<br>
+<br>
+void<br>
+st_init_objectpurge_functions(struct pipe_screen *screen,<br>
+                              struct dd_function_table *functions)<br>
+{<br>
+   if (!screen->get_param(screen, PIPE_CAP_RESOURCE_MADVISE))<br>
+      return;<br>
+<br>
+   functions->BufferObjectPurgeable = st_buffer_object_purgeable;<br>
+   functions->RenderObjectPurgeable = st_render_object_purgeable;<br>
+   functions->TextureObjectPurgeable = st_texture_object_purgeable;<br>
+<br>
+   functions->BufferObjectUnpurgeable = st_buffer_object_unpurgeable;<br>
+   functions->RenderObjectUnpurgeable = st_render_object_unpurgeable;<br>
+   functions->TextureObjectUnpurgeable = st_texture_object_unpurgeable;<br>
+}<br>
diff --git a/src/mesa/state_tracker/st_cb_objectpurge.h b/src/mesa/state_tracker/st_cb_objectpurge.h<br>
new file mode 100644<br>
index 00000000000..4bdc1881211<br>
--- /dev/null<br>
+++ b/src/mesa/state_tracker/st_cb_objectpurge.h<br>
@@ -0,0 +1,38 @@<br>
+/**************************************************************************<br>
+ *<br>
+ * Copyright 2019 Intel Corporation<br>
+ * All Rights Reserved.<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the<br>
+ * "Software"), to deal in the Software without restriction, including<br>
+ * without limitation the rights to use, copy, modify, merge, publish,<br>
+ * distribute, sub license, and/or sell copies of the Software, and to<br>
+ * permit persons to whom the Software is furnished to do so, subject to<br>
+ * the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the<br>
+ * next paragraph) shall be included in all copies or substantial portions<br>
+ * of the Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS<br>
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br>
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.<br>
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR<br>
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,<br>
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE<br>
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<br>
+ *<br>
+ **************************************************************************/<br>
+<br>
+#ifndef ST_CB_OBJECT_PURGE_H<br>
+#define ST_CB_OBJECT_PURGE_H<br>
+<br>
+struct dd_function_table;<br>
+struct pipe_screen;<br>
+<br>
+extern void<br>
+st_init_objectpurge_functions(struct pipe_screen *screen,<br>
+                              struct dd_function_table *functions);<br>
+<br>
+#endif /* ST_CB_OBJECT_PURGE_H */<br>
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c<br>
index 45451531df9..647bb5a9325 100644<br>
--- a/src/mesa/state_tracker/st_context.c<br>
+++ b/src/mesa/state_tracker/st_context.c<br>
@@ -56,6 +56,7 @@<br>
 #include "st_cb_feedback.h"<br>
 #include "st_cb_memoryobjects.h"<br>
 #include "st_cb_msaa.h"<br>
+#include "st_cb_objectpurge.h"<br>
 #include "st_cb_perfmon.h"<br>
 #include "st_cb_program.h"<br>
 #include "st_cb_queryobj.h"<br>
@@ -727,6 +728,7 @@ st_init_driver_functions(struct pipe_screen *screen,<br>
    st_init_draw_functions(functions);<br>
    st_init_blit_functions(functions);<br>
    st_init_bufferobject_functions(screen, functions);<br>
+   st_init_objectpurge_functions(screen, functions);<br>
    st_init_clear_functions(functions);<br>
    st_init_bitmap_functions(functions);<br>
    st_init_copy_image_functions(functions);<br>
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c<br>
index 528e6b74a54..7e5e056dd3e 100644<br>
--- a/src/mesa/state_tracker/st_extensions.c<br>
+++ b/src/mesa/state_tracker/st_extensions.c<br>
@@ -765,6 +765,7 @@ void st_init_extensions(struct pipe_screen *screen,<br>
       { o(ATI_meminfo),                      PIPE_CAP_QUERY_MEMORY_INFO                },<br>
       { o(AMD_seamless_cubemap_per_texture), PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE    },<br>
       { o(ATI_texture_mirror_once),          PIPE_CAP_TEXTURE_MIRROR_CLAMP             },<br>
+      { o(APPLE_object_purgeable),           PIPE_CAP_RESOURCE_MADVISE                 },<br>
       { o(MESA_tile_raster_order),           PIPE_CAP_TILE_RASTER_ORDER                },<br>
       { o(NV_conditional_render),            PIPE_CAP_CONDITIONAL_RENDER               },<br>
       { o(NV_fill_rectangle),                PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE      },<br>
-- <br>
2.20.1<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a></blockquote></div></div>