1dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com/*
2dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com * Copyright 2012 Google Inc.
3dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com *
4dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
5dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com * found in the LICENSE file.
6dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com */
7dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
8dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com#ifndef GrFakeRefObj_DEFINED
9dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com#define GrFakeRefObj_DEFINED
10dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
11a0b40280a49a8a43af7929ead3b3489951c58501commit-bot@chromium.org#include "SkTypes.h"
12dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com#include "gl/GrGLInterface.h"
13dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
14dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com////////////////////////////////////////////////////////////////////////////////
15dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com// This object is used to track the OpenGL objects. We don't use real
16fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// reference counting (i.e., we don't free the objects when their ref count
17dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com// goes to 0) so that we can detect invalid memory accesses. The refs we
18dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com// are tracking in this class are actually OpenGL's references to the objects
19dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com// not "ours"
20dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com// Each object also gets a unique globally identifying ID
21e3beb6bd7de7fa211681abbb0be58e80b19885e0commit-bot@chromium.orgclass GrFakeRefObj : SkNoncopyable {
22dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.compublic:
23fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    GrFakeRefObj()
24dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        : fRef(0)
25dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        , fHighRefCount(0)
26dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        , fMarkedForDeletion(false)
27dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        , fDeleted(false) {
28dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
290dd84a399ae8903784eac1c361c08449f822307frobertphillips@google.com        // source for globally unique IDs - 0 is reserved!
30fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        static int fNextID = 0;
31dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
32dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        fID = ++fNextID;
33dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    }
34dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    virtual ~GrFakeRefObj() {};
35dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
36fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    void ref() {
37fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        fRef++;
38dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        if (fHighRefCount < fRef) {
39dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com            fHighRefCount = fRef;
40dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        }
41dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    }
42fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    void unref() {
43fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        fRef--;
44dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        GrAlwaysAssert(fRef >= 0);
45dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
46fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        // often in OpenGL a given object may still be in use when the
47dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        // delete call is made. In these cases the object is marked
48dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        // for deletion and then freed when it is no longer in use
49dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        if (0 == fRef && fMarkedForDeletion) {
50fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            this->deleteAction();
51dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        }
52dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    }
530dd84a399ae8903784eac1c361c08449f822307frobertphillips@google.com    int getRefCount() const             { return fRef; }
540dd84a399ae8903784eac1c361c08449f822307frobertphillips@google.com    int getHighRefCount() const         { return fHighRefCount; }
55dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
560dd84a399ae8903784eac1c361c08449f822307frobertphillips@google.com    GrGLuint getID() const              { return fID; }
57dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
580dd84a399ae8903784eac1c361c08449f822307frobertphillips@google.com    void setMarkedForDeletion()         { fMarkedForDeletion = true; }
590dd84a399ae8903784eac1c361c08449f822307frobertphillips@google.com    bool getMarkedForDeletion() const   { return fMarkedForDeletion; }
60dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
610dd84a399ae8903784eac1c361c08449f822307frobertphillips@google.com    bool getDeleted() const             { return fDeleted; }
62dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
63dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    // The deleteAction fires if the object has been marked for deletion but
64dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    // couldn't be deleted earlier due to refs
65dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    virtual void deleteAction() {
66dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        this->setDeleted();
67dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    }
68dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
69dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.comprotected:
70dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.comprivate:
710dd84a399ae8903784eac1c361c08449f822307frobertphillips@google.com    int         fRef;               // ref count
72dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    int         fHighRefCount;      // high water mark of the ref count
730dd84a399ae8903784eac1c361c08449f822307frobertphillips@google.com    GrGLuint    fID;                // globally unique ID
74dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    bool        fMarkedForDeletion;
75dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    // The deleted flag is only set when OpenGL thinks the object is deleted
76dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    // It is obviously still allocated w/in this framework
77dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    bool        fDeleted;
78dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
79dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    // setDeleted should only ever appear in the deleteAction method!
800dd84a399ae8903784eac1c361c08449f822307frobertphillips@google.com    void setDeleted()                   { fDeleted = true; }
81dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com};
82dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
83dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com////////////////////////////////////////////////////////////////////////////////
84dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com// Each class derived from GrFakeRefObj should use this macro to add a
85dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com// factory creation entry point. This entry point is used by the GrGLDebug
86dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com// object to instantiate the various objects
87dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com// all globally unique IDs
88dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com#define GR_DEFINE_CREATOR(className)                        \
89dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    public:                                                 \
90dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    static GrFakeRefObj *create ## className() {            \
91dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com        return SkNEW(className);                            \
92dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com    }
93dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com
94dd743fefad9764ad86d7f69deec32e9a3b5de47frobertphillips@google.com#endif // GrFakeRefObj_DEFINED
95